#💻・modding-dev
1 messages · Page 618 of 1
does that have to be a hook, or is it as simple as you're writing it?
bump
it is as simple as im writing it
Log?
I'm not sure how i could access it since my game crash imediatly without any usual error screen
lovely/log in mods folder
if context.modify_ante and context.ante_end and G.GAME.round_resets.ante >= G.GAME.win_ante then
return {modify = (G.GAME.win_ante-1)-G.GAME.round_resets.ante}
end
context.main_scoring doesn't seem to be working, all I'm seeing is noh
yeah because
context.main_scoring only calculates for playing cards that have been scored
im having a hard time figuring out which context im meant to be using then
@slim ferry forgot to ping reply
individual?
wdym
context.individual
would anyone know why i would be getting a file not found main.lua error, or a sprite issue indicated from the stack trace? the animated sprite that's being inited has a non-null W and H
i haven't changed anything for months and apparently the mod has just stopped working from the flame_handler Moveables in the hand scoring UI
local seal = nil
local edition = nil
local enhancement = nil
for i = 1, math.min(#G.hand.highlighted, self.config.max_highlighted) do
_card = G.hand.highlighted[i]
if _card.seal and seal == nil then
seal = _card.seal
end
if _card.edition and edition == nil then
edition = _card.edition
end
if _card.enhancement and enhancement == nil then
enhancement = _card.enhancement
end
end
for i = 1, math.min(#G.hand.highlighted, self.config.max_highlighted) do
_card = G.hand.highlighted[1]
G.E_MANAGER:add_event(Event({func = function()
_card:set_seal(seal)
_card:set_edition(edition)
_card:set_ability(enhancement)
return true
end}))
end
end```
when i use this consumable, only one card gets the effects, and also for some reason the enhancement part doesnt work. does anyone know why?
It's _card:get_seal() and SMODS.get_enhancements(_card)[1]
i tried it before when i do that i get a crash
Code?
key = 'idol',
set = 'Tarot',
config = {max_highlighted = 3},
loc_txt = {
name = 'Idol',
text = {
'Select up to {C:attention}#1#{} cards.',
'They all gain eachothers {C:blue}Seals{},',
'{C:attention}Enhancements{}, and {C:attention}Editions{}'
}
},
cost = 3,
atlas = 'ConsumablesPlus',
pos = {x=0,y=0},
loc_vars = function(self , info_queue, card)
return { vars = { (card.ability or self.config).max_highlighted } }
end,
use = function(self, area, copier)
local seal = nil
local edition = nil
local enhancement = nil
for i = 1, math.min(#G.hand.highlighted, self.config.max_highlighted) do
_card = G.hand.highlighted[i]
if _card.get_seal() and seal == nil then
seal = _card.get_seal()
end
if _card.edition and edition == nil then
edition = _card.edition
end
if SMODS.get_enhancements(_card)[1] and enhancement == nil then
enhancement = SMODS.get_enhancements(_card)[1]
end
end
for i = 1, math.min(#G.hand.highlighted, self.config.max_highlighted) do
_card = G.hand.highlighted[1]
G.E_MANAGER:add_event(Event({func = function()
_card:set_seal(seal)
_card:set_edition(edition)
_card:set_ability(enhancement)
return true
end}))
end
end
}```
No, it's _card:get_seal()
It's : not .
how do i modify probabilities with a Joker?
Because _card is always the first highlighted card.
i'd like its modifier to be assessed in before, and removed in after
context.mod_probability
what are its returns?
numerator and denominator
👍
for i = 1, #G.deck.cards do
if context.joker_main then
if G.deck.cards[i]:is_suit("Hearts") then
SMODS.destroy_cards(card, nil, nil, true)
return {
message = "Adieu !"}
end
end
end
i'm close to get but trying to make the joker destroy all heart cards in the deck, rn just messed and made itself vanish instead lol
help would be appreciate thanks
if context.joker_main then
local hearts = {}
for k, v in pairs(G.deck.cards) do
if v:is_suit('Hearts') then
hearts[#hearts+1] = v
end
end
SMODS.destroy_cards(hearts, nil, nil, true)
end
thanks again
How do I get variables from config = {} to show up within the in_pool() specification?
self.config?
That did the trick.
Does context.card.ability.consumeable really determine whether or not a certain card is a consumable? I have a SMODS.curent_mod.calculate() function that goes off of if context.selling_card and context.card.ability.consumeable, but it apparently doesn't activate.
Yes.
And does context.consumeable.config.center.key specify the name of the consumable card being sold?
No, it's context.card
bumping again
I looked in Crimson Heart's code for guidance, and it uses <id_used_for_joker>.ability.crimson_heart_chosen to debuff a Joker.
So, is context.card.config.center.key correct?
if context.setting_blind then return {func = function() SMODS.debuff_card(card, true, self.key) end} end
banned_cards = function()
local banned = {}
for k, v in pairs(G.P_CENTERS) do
if v.set == 'Voucher' then
banned[#banned+1] = {id = v.key}
end
end
return banned
end
wouldnt that still generate blanks
Yes.
Yeah defaults cannot be banned
i mean even then
blank does nothing
though its probably more efficient to just set voucher slots to 0
oh i didnt know you could change voucher slots, that sounds like what i need
I also looked at crimson heart, but it seems like crimson heart's wway of debuffing didn't support "undebuffing" in this sort
yea but if i replace it with G.hand_highlighted[i] in the code i get another crash
Yes, G.hand_highlighted doesn't exist.
so how can i make it work?
_card = G.hand.highlighted[i]
yes but then it will always be the first one as you said?
to_big is a thing that the talisman mod uses
the way talisman stores numbers is by converting them to tables
generally a lot of functions are incompatible with them, but if you're not specifically working with talisman, then you can define these somewhere in your code and it should(?) work
local to_big = to_big or function(num)
return num
end
local to_number = to_number or function(num)
return num
end
what should I use instead? I just want to check if hand defeated the blind
it scored = or > the required chips
No, you should keep it like that but add to_big = to_big or function(x) return x end to the top of your file.
Anything that I put in SMODS.current_mod.calculate() doesn't execute. What do I do?
now joker doesnt do anything😭
Is it inherently incorrect?
Code?
you probably want to be checking context.end_of_round and context.main_eval
instead of checking blind requirement
and joker main
Within my utility/functions.lua file there is:
SMODS.current_mod.calculate = function(self, context)
-- My code is in here
end
Is that file being loaded?
Yes, of course! And I was told that SMODS.current_mod.calculate was like an invisible Joker card that's always being held no matter what.
Also, everything else in the file works without a hitch.
Oh yeah, like at end of round check num of hand played is equal to 1
thanks!
What is your SMODS version?
Probably not the latest one, I don't know how to update Steamodded.
i have a deck that's supposed to unlock when you have gold stake stickers on 10 or more jokers. i might've implemented this wrong, but i'm not sure what i've done wrong
check_for_unlock = function(self, args)
if G.P_CENTER_POOLS["joker"] then
local count = 0
for k, v in pairs(G.P_CENTER_POOLS["joker"]) do
if get_joker_win_sticker(v.config.center) >= 10 then
count = count + 1
end
end
if count >= 10 then
unlock_card(self)
end
end
end,
https://github.com/Steamodded/smods/releases/tag/1.0.0-beta-1016c
download the latest release from here, and replace the old smods in your mod folder
Those anyone know if the moder behind Jokers Evolve still active?
No, because that mod doesn't exist.
Those go by different name? I mean, I have active and downloaded it
Updated Steamodded, but even still, no code within this function activates.
SMODS.current_mod.calculate = function(self, context)
-- My code is in here
end
Where are you putting that code
At the very end of my utility/functions.lua file, which has a bunch of useful functions such as checking if a table contains a specified value, determining whether or not a played hand contains a certain rank, and so on.
how would i get these tags to show description boxes when hovered?
try putting it as the first thing in your main file
what is the code inside of the function?
It's meant to keep a table of every consumable card that's been sold in the run.
SMODS.current_mod.calculate = function(self, context)
G.GAME.LAPSEMS_consumables_sold = G.GAME.LAPSEMS_consumables_sold or {}
if context.selling_card and context.card.ability.consumeable then
if not (LAPSEMS.contains(G.GAME.LAPSEMS_consumables_sold, context.card.config.center.key)) then
G.GAME.LAPSEMS_consumables_sold[#G.GAME.LAPSEMS_consumables_sold + 1] = context.card.config.center.key
end
end
end
have you tried putting prints at different parts to see where it goes wrong?
I haven't. Also, where would the print statements even show up, in the Lovely window that accompanies an open Balatro game?
it should show up in the debugplus console
just make sure to turn off "Only show commands" in the debugplus config
how do i make destroying cards outside of a calculate function do the context stuff like context.remove_playing_cards
either use SMODS.destroy_cards (calculates the context automatically) or use SMODS.calculate_context to manually do it
Tried it just now, none of the print statements showed up.
do any of the other functions in the same file load?
Yes!
do you return anywhere outside of a function in the file?
Have you tried doing eval SMODS.Mods.modid.calculate?
replace modid with your actual mod id
What do I do with this?
that means the function exists, so it should be getting called
Apparently not.
Still nothing.
try selecting the blind
Still nil.
It's nil even after I've beaten the Small Blind.
And even after I've beaten the first Ante, nothing changes.
okay idk, try eval SMODS.Mods.Lapsems:calculate({})
Since there's the code to initialize the table if it doesn't already exist, I should se something like this:
That returns nil.
And it doesn't print this?
the message you have in your function
Nuh-uh.
Are you defining the function twice in your code or something?
No, I've only defined it once!
you didn't type this and not save your changes, right?
I've done that a non zero amount of times
Nope, I've saved it all.
can you check so that you're 100% sure you have not defined it somewhere else after the first time, maybe in some other file you forgot about
cus I can't think of any other reason if you have it saved
Have you tried eval debug.getinfo(SMODS.Mods.Lapsems.calculate)?
I did have it defined a second time in my src/jokers.lua file -- with nothing in it.
removing that one should fix it then
I've done just that, and I've got it sorted out!
Now it's telling me that cards_to_select is a nil value!
--[[
Code adapted from The Emperor.
--]]
use = function(self, card, area, copier)
local cards_to_select = G.GAME.LAPSEMS_consumables_sold
for i = 1, math.min(card.ability.max_cards, G.consumeables.config.card_limit - #G.consumeables.cards) do
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.4,
func = function()
if G.consumeables.config.card_limit > #G.consumeables.cards then
play_sound('timpani')
SMODS.add_card({key = table.remove(cards_to_select, math.random(1, #cards_to_select))})
print('Card taken from cards_to_select!')
card:juice_up(0.3, 0.5)
end
return true
end
}))
end
delay(0.6)
cards_to_select = nil
end
Wouldn't that leave cards_to_select's value floating around in memory?
No, it would get collected by the garbage collector.
^ after there are no more references to it, in this case after the events run
actually, not even, since cards_to_select is by itself a reference to consumables_sold
its a local variable anyway
well anyway, you don't need to do = nil for this
Using The Prisoner takes cards out of the G.GAME.LAPSEMS_consumables_sold pool, which I wanted to avoid by stuffing them in a cards_to_select table. What do I do?
dont use table.remove
cus cards_to_select isn't a copy of the table, it's just a reference to the same one
doing x = <table> makes x reference the same table, rather than copying over the values
you can use balatro's copy_table function to make a copy if you want
local cards_to_select = copy_table(G.GAME.blah blah blah)
also you probably wanna use pseudorandom instead of math.random so your random number stuff is seeded
?
Use pseudorandom_element
malcheck is always set to false when calculate is called.
You need to iterate over context.full_hand
quick question how would I go about setting the upcoming boss blind to a specific one?
G.GAME.round_resets.blind_choices.Boss = 'bl_modprefix_key'
Awesome thank you
if you're doing it before the ante in question, G.GAME.perscribed_bosses[ante number] = "bl_modprefix_key"
Okay good to know tysm
i forgot can i just debuff a voucher or do i have to code that in
You mean ban a voucher?
no like debuff it
like the way a bossblind might do cards
Yes, but it wont do anything unless it is a voucher that uses calculate
hi everybody , can someone explain to me why it didn't work ? i think i don't realy understand what context.card do
when i play a card the game crash and tell me that the context.card is nil
What is the goal?
you want context.other_card
when you discard my joker flip and then when you play a card the value of the card stack on the joker , when the face of the joker is front and you play a card it add all of the chip he have and reset to 0
so i need to get the value of the card i played when he is face down
context.card only exists in a small handful of contexts; in this case you want context.other_card
okay thank you !
context.other_card:get_chip_bonus()
Does anyone know what the animation speed on the blind chips is?
Is there any functional difference between these two statements?
table[#table + 1] = element
table.insert(table, element)
table.insert is slower
in terms of performance
i dont think the difference is that big tho
well table.insert is meant to insert values into the middle of number-indexed tables and shift over all elements appropriately
so it like does a bunch of extra checks for that
if youre adding to the end itll still do all those checks but just do nothing
or well itll do more stuff than the table[#table+1] thing
i think it would just be one check to see if it should shift no?
hey gang - I'm wanting to create a new type of "tag" that will ideally in the future be distinct from the ingame tags, but right now i'm just using SMODS.Tag for proof-of-concept's sake
what would be a good way to make a tag do something when cards are scored? right now i have it to where a custom tag gets consumed after the scoring hand is played, but i can't really think of a great way to access the scoring hand let alone add mult from the SMODS.Tag apply function, so I imagine it'd have to be another way, and I'm not sure where to go from there ;P
well one check is already slower than no check
indexing table is also another operation
you should probably look at Entropy's runes for something like that
These are some wise words
in reality it doesn't matter
that is an extension of tags with most things you need i imagine
I am tbh unsure on how you'd create a new card type, but for my custom things i use the SMODS.current_mod.calculate
https://github.com/lord-ruby/Entropy/blob/main/items/misc/runes.lua all the code for it is in this file (as far as i know)
well the calculate stuff is probably elsewhere
but idk where that is
also you should probably not store the extension in the global SMODS table, idk why entropy does that when it has the Entropy table
while we're at new card types: I'm in search of having a function to be able to create a ui card element (not a new class/type) so i can have it be able to render a background, a sprite + a soul sprite from an atlas and convert it to an ui element. does anything like that already exist?
also basically anything referencing providence can usually be ignored since thats related to a voucher
isn't there a way to upgrade a hand by more than one level in one fell swoop?
how would it be faster
im inclined to trust eris with an explanation more than somethingcom "let me react when i dont know something instead of just saying that" 515
sorry for the extremely late ping, but what does it do and how does it work
oh hi paradox :)
I'd think the biggest slowdown is the actual function call itself not the indexing of table, so while that would make it faster I doubt it's faster than getting the length and adding one
i guess you could test it by trying to insert like 10 million elements
and see what's faster
https://github.com/Steamodded/smods/pull/917 this is all i can find about it. not much but it shouldnt be too hard to understand i hope(?)
hi graphax
great I gotta reinvent E:1
Bit of confusion: yahimod doesn't seem to have a file like the 'load the mod's files' file like my mod has. Considering how much of my boss code is ripped from that, do I load both files at once along with everything or do I wait until the boss is called?
load everything at once
the file loading code is at the bottom of core.lua btw
Made an effect that swaps the sprite of joker, but it doesn't save on a reload, so I'm trying to make sure it does. However, I keep getting an error on a reload... extra is apparently nil.
load = function(self, card, card_table, other_card)
local atlas_x = 0
if card.ability.extra.flip == 0 then
card.ability.extra.flip = 1
atlas_x = 1
else
card.ability.extra.flip = 0
atlas_x = 0
end
card.children.center:set_sprite_pos({x = atlas_x, y = self.pos.y})
end
Yes, the cards ability wouldn't be set yet.
Okay, what would be the best way to save values to get the sprite I want?
Do it in an event.
What went wrong now?
key = "corporate_entity_overlord",
path = "1472583690.png",
px = 128,
py = 128
}
SMODS.Blind {
name = "boss_quiz",
key = "boss_quiz",
atlas = "corporate_entity_overlord",
pos = { y = 0 },
dollars = 7,
mult = 2,
boss = { min = 1 },
loc_txt = {
name = "The Splapp",
text = {
"Answer an impossible question",
}
},
boss_colour = HEX('cd93e12'),
recalc_debuff = function(self)
quizLoad()
end,
defeat = function(self)
endDino()
end,
disable = function(self)
endDino()
end,
}```
Code
cd93e12 is not a valid colour.
anything else?
Your atlas needs to be an ANIMATION_ATLAS
Just a name swap or...
No, atlas_table = 'ANIMATION_ATLAS'
ah. so change SMODS.atlas to SMODS.atlas_table too?
anything else for the main atlas part?
Yes, you also need frames
Is it just a number?
seems to be working fine now. thanks
Yes.
So I could just set it to 1?
Yes, if you don't want your blind to have the shine.
I just want it to work right now, not be flashy and shiny
key = "corporate_entity_overlord",
path = "1472583690.png",
frames = 1,
px = 128,
py = 128
}
SMODS.Blind {
name = "boss_quiz",
key = "boss_quiz",
atlas = "corporate_entity_overlord",
atlas_table = 'ANIMATION_ATLAS',
pos = { y = 0 },
dollars = 7,
mult = 2,
boss = { min = 1 },
loc_txt = {
name = "The Splapp",
text = {
"Answer an impossible question",
}
},
boss_colour = HEX('cd9e12'),
recalc_debuff = function(self)
quizLoad()
end
}```
Something(com515) like this?
No, in the atlas.
that all?
please someone make sure this doesn't crash immediately this time
Start from the top, what's the intention of it and waht's the code?
It seems so.
not args and args.source ~= "jud" will crash the game and will never be true.
Change and to or
Also it would be not args or (args.source ~= 'jud' and args.source ~= 'sho')
if not blind.disabled then
if context.press_play then
G.GAME.blind.chips = math.floor(G.GAME.blind.chips + G.GAME.blind.chips * 0.25)
G.GAME.blind.chip_text = number_format(G.GAME.blind.chips)
blind.triggered = true
G.E_MANAGER:add_event(Event({
trigger = 'immediate',
func = (function()
SMODS.juice_up_blind()
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.06 * G.SETTINGS.GAMESPEED,
blockable = false,
blocking = false,
func = function()
play_sound('tarot2', 0.76, 0.4)
return true
end
}))
play_sound('tarot2', 1, 0.4)
return true
end)
}))
delay(0.4)
end
end``` I need help trying to figure out how to get a card's enhancement when played, specifically to increase blind requirments per one found
this si just a placeholder
Did you find a solution to this? I'm having the same problem
ease_dollars((G.GAME.dollars+G.GAME.dollar_buffer) * 1.5)
if context.round_eval and G.GAME.last_blind then
G.E_MANAGER:add_event(Event({
func = function()
add_tag(Tag('jabong_tag_luchatag'))
play_sound('generic1', 0.9 + math.random() * 0.1, 0.8)
play_sound('holo1', 1.2 + math.random() * 0.1, 0.4)
return true
end
}))
end
end,``` this is good code if i want to make a tag after every blind defeated
No, if context.beat_boss and context.end_of_round and context.main_eval
So yes I did find a way to make it work, basically I had the joker set a local variable as 1 then change when hand was played to be the same a G.GAME.dollars because G.GAME.dollars can't be updated mid hand which is what I wanted (Btw the reason why I have it set as / 3 is because I didn't want to adjust my numbers while still having X1.5 work):
if context.individual and context.cardarea == G.play and not context.repetition then if card.ability.extra.current_dollars == 1 then card.ability.extra.current_dollars = G.GAME.dollars / 3 end
Then in the function to trigger and give money I had it multiply the local variable that is G.GAME.dollars by my multiplier (1.5) you could also just do it or (0.5):
if context.other_card:is_suit("Diamonds") then card.ability.extra.current_dollars = card.ability.extra.current_dollars * 1.5 card.ability.extra.current_dollars = math.floor(card.ability.extra.current_dollars * 10) / 10 end if context.other_card:is_suit("Diamonds") and context.other_card:is_suit("Spades") then card:juice_up(1,0.5) return { card:juice_up(1,0.5), message = "X1.5", colour = G.C.MONEY, extra = { ease_dollars(card.ability.extra.dollars * card.ability.extra.current_dollars), extra = { xchips = card.ability.extra.xchips } } }
Also the xchips is because this specific trigger is for a wild card that trigger two different effects, one spades and one diamonds
Also big fan of your work on Pokermon Sonfive, been playing your version with friends for a whiiiile, thanks for making it so good
No, it can.
Also you should be returning dollars.
idk when I tried it was finicky
Also you can just use G.GAME.dollar_buffer
I've used various different forms of returning dollars in the mod I"m working on this is just what I know works for this and I didn't wanna give false information, I just know this works because this is what I made
No, it doesn't because if you get dollars from something else it wont work.
???
You're not using G.GAME.dollar_buffer
other returns work though
What do you mean other returns?
like ease_dollars or dollars.card.extra.dollars, sorry for the slow response im eating tacos
Have you tried having this joker along with Rough Gem?
Lemme try
Fair enough something isn't working right I'll look into that, also for anybody looking into this the logic of how the money scales works I'm just an idiot on making the return work
I understand my flaw in the logic, basically because I have used ease_dollars in various things that timing isn't important in, that when I applied it to the triggers since it doesn't use the same return (G.GAME.dollar_buffer) it doesn't interact correctly with other things that make money, thanks for letting me know
does anyone know who the high contrast version of my custom FoJ face cards aren't using the high contrast number cards?
Okay, the boss is up, but the buttons aren't.
G.splapp_config = G.splapp_config or {}
local disbuff = function()
if G.GAME.blind == splapp then
G.GAME.blind:disable()
end
G.FUNCS.DT_lose_game = function()
if G.STAGE == G.STAGES.RUN then
G.STATE = G.STATES.GAME_OVER; G.STATE_COMPLETE = false
end
end
local t = {n=G.UIT.ROOT, config = {align = 'cm', r = 0.1}, nodes={
UIBox_dyn_container({
{n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={
{n=G.UIT.R, config={align = "cm", padding = 0.05}, nodes={
{n=G.UIT.T, config={text = "HOW MANY HOLES IN A POLO?", scale = 0.25, colour = G.C.WHITE, shadow = true}}
}},
{n=G.UIT.R, config={align = "cm", padding = 0.15}, nodes={
{n=G.UIT.C, config={align = "cm", padding = 0.15}, nodes={
UIBox_button{ label = {"One"}, button = "DT_lose_game", minw = 1.7, minh = 0.4, scale = 0.35},
UIBox_button{ label = {"Two"}, button = "DT_lose_game", minw = 1.7, minh = 0.4, scale = 0.35},
}},
{n=G.UIT.C, config={align = "cm", padding = 0.15}, nodes={
UIBox_button{ label = {"Three"}, button = "DT_lose_game", minw = 1.7, minh = 0.4, scale = 0.35},
UIBox_button{ label = {"Four"}, button = disbuff, minw = 1.7, minh = 0.4, scale = 0.35},
}}
}},
}}
}, true)
}}
return t
end
end```
Could be because I'm missing a few things at the top, but I don't know what is
You have to specify all the ranks it should apply to. You're likely only specifying the face ranks
oh
alternatively, set hc_default = true
thanks
which on a given palette will use default hc cards for unchanged cards if you don't specify them in the atla
off topic where do i get those little faces from i like them a lot
little faces?
sorry the little custom face cards you made
ah
i am entirely forgetting the term for it
they'll be in my mod once i update it
but i'm also respriting the left one
they’re so cuteee
will prob release it separately from my main mod
the design's outdated lol
here's her current joker art for reference
bump
holy guacamole ur good at pixel art omg
tyyy
thoughts?
does anyone know how to fix this crash in cryptid?
When does this happen?
on bootup
Have you tried reinstalling Talisman?
why in modding dev and why common
because im developing my mod
:P
common because i need the player to actually find it
well developing is a strong word
do not hate on my proficient use of the forge of jokers
this is what we in the indestry call "Bad game design"
this is what we in the indestry call "Shits and giggles"
hey gang, I made a mechanism using SMODS.current_mod.calculate to apply +5 Mult to context.other_card when a certain tag is present & then juice it up -- just a prototype for a feature that'll probably eventually be distinct from tags! however i've deduced that it is very specifically SMODS.calculate_effect that causes the deck to juice up in a very strange way for some reason? i'm not sure if it's because it thinks other_card is the deck yet somehow applies +Mult to the scoring card directly or if it's both?? lmaoooo either way how do i get the deck to stop doing that without a card argument from the calculate func? :3c
if context.individual and context.cardarea == G.play then
for i = 1, #G.GAME.tags do
if G.GAME.tags[i].key == "tag_spm_fireburst" then
G.E_MANAGER:add_event(Event({
func = (function()
G.GAME.tags[i]:juice_up()
return true
end)
}))
SMODS.calculate_effect({mult = 5}, context.other_card)
return true
end
end
end
oh volume warning potentially
also i have no idea why it's scoring before the chips, but like, i don't super hate it
i am curious if there's a way to queue it after chips and before other scoring mechanisms like editions and enhancements, though
no image can express my disgust
BOY OH BOY I SURE DO LOVE ^1.5 MULT ON A COMMON JOKER 💔
if context.individual and context.cardarea == G.play then
local effects = {}
for k, v in pairs(G.GAME.tags) do
if v.key == "tag_spm_fireburst" then
table.insert(effects, {mult = 5, message_card = context.other_card, juice_card = v})
end
end
return SMODS.merge_effects(effects)
end
actually ill make it ^1.1 for you ❤️
yah i was about to say, return wouldn't quite work iirc but i didn't even think of table.insert(effects, ...)
tysm
i'll try that rn
beautiful, it works! :D
<@&1133519078540185692>
first time working with labels, how do you change its color 😭
badge_colour
under the localization?
No, in the SMODS.Seal
ohhh tnx ✌️
what if it was on a joker though
like a sub catgory
is it just the same?
Jokers don't have individual badges.
how does one make those then (i.e the sticker stuff without actually having a sticker)
Patch G.UIDEF.card_h_popup
tnxx
ngl kinda proud of this concept what do yall think
can anyone who understands lua tell me why my game crashed please?
im at my fucking wits end so im coming here for help
does anyone here know how quantum ranks work 😭
im doing something Very similar but simpler
and there's this one last bit of code that refuses to work
What is it?
Hook Card:is_suit
Hook Card:get_id
currently, they don't
the branch isn't merged yet
im, not asking how to use them, moreso just,, the theory behind them?
No, they do, it's just not very stable.
the theory is that they let a card have additional ranks
the theory is that theres a function like is_suit
but for ranks
the issue is its hard as fuck to do straight detection with
yeahhh fair
its literally just quantum suits and quantum enhancements and straights are the only thing in the way
oooh
what if they were gay and they were pairs instaed
okay thats good, maybe ill just look into how the branch worked
bluestorm yuri confirmed???
cause im just figuring out how quantum pairs works
no, because those are jokers, not playing cards
for my own specific non-rank and non-suit thing
What is the goal?
im making my own game overhaul
where colors count as ranks and pairs and
its,,, a lot to explain
You mean you want each color to be its own suit and rank?
basically a custom hand system that allows for quantum colors and ranks for pairs thatu ses an entirely different algorithm from base game
yes its a lot and yes its probably not worth it
Patch get_X_same
yes
that is what im doing
and in fact
what im asking for help with
Because im trying to figure out how quantum ranks work on a Code Level
I think -$5 in yellow text is the proper formatting but otherwise interesting card. Tho I wonder if a constant tax (say, $2) would be better. I suppose it's just feel and playtesting
but i get that its already in the quantum ranks thing in the steamodded branch
SO instead im just going to look there
later
thats just a placeholder joker from my old mod 😭
ah
I havent made any jokers for this yet
Within get_blind_amount(), how do I tell if the blind in question is a Boss Blind?
you don't
it's getting the base amount for the ante
im confused looking back at this, wouldnt this code result in double counting?
It shouldn't, because I tested it, and it works.
you arent great for conversation huh
does anyone know why negative mult is not showing up in the ui with this code? still functions it just shows up blank
this is what i'm tryna do
What shows up blank?
Remove the first 2 lines in the if context.joker_main
nothing changes
card.ability.extra.mult = card.ability.extra.mult + card.ability.extra.mult_gain
return {
message = 'Upgraded!',
colour = G.C.MULT,
card = card
}
end```
for some reason the game crashes at the first line of this code
if context.using_consumeable and not context.blueprint and context.consumeable.ability.set == 'Spectral'
oh
bruuuh
i was looking at the code for constellation
i didint see that
the jokers are gruped
like there is a bunch of jokers inside of if context.using_consumeable
and then they have separate conditions for themselves
tysm
Yeah, the update's ass lmao
me when i decide to reply to someone exactly 3 months later for some reason
dphb moment
local oldunlockcard = unlock_card
function unlock_card(card)
local g = oldunlockcard(card)
if card.key == 'j_modprefix_key' then discover_card(card) end
return g
end
Yatta
<@&1133519078540185692>
how do i check if a joker is on the left of the current one
local passed = false
for k, v in pairs(G.jokers.cards) do
if v == card and G.jokers.cards[k-1] == joker then
passed = true
end
end
if passed then
end
this will set the passed variable to 1 if its true right
No, it will set it to true
okay thanks!
Hi ! I'm new to modding and I'm struggling with the ability part of jokers. Could someone help ?
state your issue to start
someone know how to get sell value i forgor
yes sorry
card.sell_cost
like of an other joker
thats like the actual joker cost but i want to check the sell value of a specific joker
otherjoker.sell_cost
so how would i check for a specific one? just replace the otherjoker thing or is it something else
replace otherjoker with another card object
I'm just trying to make an xmult joker but when I try to have access to anything in "card.ability.extra", it crash my game with the error "attempt to index field 'extra' (a nill vallue)"
what does the card config look like
SMODS.Joker {
key = 'joker2',
loc_txt = {
name = 'Joker 2',
text = {
"{X:mult,C:white}x#1# {} Mult #2#"
}
},
config = { extra = {Xmult = 10.0, oui = 1} },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.Xmult, card.ability.extra.oui } }
end,
...```
Did you start a new run?
yes but I think it's supposed to be
ooohhhh no
but like, i wanna get the sell value of the joker to the left of this one
that's might be that
local sell_cost = 0
for k, v in pairs(G.jokers.cards) do
if v == card and k >= 2 then
sell_cost = G.jokers.cards[k-1].sell_cost
end
end
thanks!
How can I place a Joker in my deck by default for testing ?
DebugPlus
thanks
@daring fern for some reason, the code you provided seems to not be working
its detecting an error on the second line of the code
wait
this one: sell_cost = G.jokers.cards[k-1].sell_cost
try if v == card and k > 1
how do i check if my joker is being held in the joker tray thingy
if card.area == G.jokers?
my lovely patch appears to be not even loading at all
im trying to patch another mod and ive tried putting it in lovely folder in my mod and even lovely.toml
i see no logs about my patch
Is there a way to do this but with the card:shatter effect instead of the default one?
Maybe a different mod patching even before your mod? Try checking the lovely dump.
idk, my lovely patches didn't work because the code I was trying to patch was already being patched by something else before.
i dont think you can with the context but you can hook SMODS.shatters and check for that flag you set there
ah
the file i am patching doesnt exist in the dump at all
Code?
how would i have a blind check for enhenaced cards on press play?
Per chance, is this for an enhancement?
if context.before then
local found = false
for _,v in ipairs(G.hand.cards) do
if v.config.center.key ~= 'c_base' then found = true end
end
if found then
-- Your logic here
end
end
That's my best guess. I have never coded a blind in my life, so the context might be wrong.
[manifest]
version = "1.0.0"
dump_lua = true
priority = 1
[[patches]]
[patches.pattern]
target = '=[SMODS Yggdrasil "code/loot_system.lua"]'
pattern = '''
{
card_key = "j_misprint",
recipe = {
{"cs", "cs", "cs"},
{"cs", "me", "cs"},
{"cs", "cs", "cs"},
},
config = {
amount = 1,
immediate_emplace = true,
specific_area = "jokers"
}
},
'''
position = 'after'
payload = '''
{
card_key = "ygg_mat_ygg_soul_fragment",
recipe = {
{"goi", "goi", "ast_h"},
{"cs", "cs", "cs"},
{"cs", "cs", "cs"},
},
config = {
amount = 1,
unique = true
}
},
'''
match_indent = true
yes
@sharp arch
ah
thanks
Not sure it will work, but it's worth the shot
No, you're missing a )
god fuckign dammit
Also it's not next(SMODS.get_enhancements(v))
either works
(discounting the missing parenthesis)
No, card.key doesn't exist.
No, if not next(SMODS.get_enhancements(v)) then found = true end
shrug
The id is YGGDRASIL not Yggdrasil
oh
if not blind.disabled then
if context.before then
local found = false
for _,v in ipairs(G.hand.cards) do
if not next(SMODS.get_enhancements(v)) then found = true end
end
if found then
G.GAME.blind.chips = math.floor(G.GAME.blind.chips + G.GAME.blind.chips * 0.25)
G.GAME.blind.chip_text = number_format(G.GAME.blind.chips)
end
end
blind.triggered = true
G.E_MANAGER:add_event(Event({
trigger = 'immediate',
func = (function()
SMODS.juice_up_blind()
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.06 * G.SETTINGS.GAMESPEED,
blockable = false,
blocking = false,
func = function()
play_sound('tarot2', 0.76, 0.4)
return true
end
}))
play_sound('tarot2', 1, 0.4)
return true
end)
}))
delay(0.4)
end
end,
}``` ok now my blind is triggering per animation HELP
Yes, you need a context check.
so like ```if context.press_play then
-- do code
No, put everything in the if found check.
if not blind.disabled then
if context.before then
local found = false
for _,v in ipairs(G.hand.cards) do
if not next(SMODS.get_enhancements(v)) then found = true end
end
if found then
G.GAME.blind.chips = math.floor(G.GAME.blind.chips + G.GAME.blind.chips * 0.25)
G.GAME.blind.chip_text = number_format(G.GAME.blind.chips)
blind.triggered = true
G.E_MANAGER:add_event(Event({
trigger = 'immediate',
func = (function()
SMODS.juice_up_blind()
G.E_MANAGER:add_event(Event({
trigger = 'after',
delay = 0.06 * G.SETTINGS.GAMESPEED,
blockable = false,
blocking = false,
func = function()
play_sound('tarot2', 0.76, 0.4)
return true
end
}))
play_sound('tarot2', 1, 0.4)
return true
end)
}))
delay(0.4)
end
end
end
end,
so this is good
Yes, but you should fix the formatting.
oki
is it possible to have the hand score as a Three of a Kind if a high card is played, and cards turn into 7s?
shoot is this the wrong chat for this lol
Yes, change the cards in context.press_play
works beautifully now
How would you make this compatible with other suits? It's supposed to give +20 mult if all cards held in hand are the same suit
like modded suits
just save the first card's suit, and if any other card held in hand doesn't match the first card's suit then it's false. otherwise it's true
how do i hook into a joker's calculate function (NOT taking ownership)
or should i patch
idk
i think its like
you go to the center pools and get the key
then hook it the normal way?
ok
You take ownership of it but you save the original function.
G.P_CENTER_POOLS.Joker[full_key]
No, it's G.P_CENTERS
? whats the diff
G.P_CENTER_POOLS.Joker is number indexed.
oh
how do i change a joker's atlas position?
update pos ig
i've only done it for the center before but i wanna do it for specific cards
card.children.center:set_sprite_pos({x = x, y = y})
i think youd need a custom draw step
ty
oh
what would be the best way have blinds have higher rewards in a challenge? im trying to make a challenge that x3 the reward. at the moment im overwriting Blind:set_blind and using blind.dollars = blind.dollars * G.GAME.modifiers.blind_reward_mult but this is very buggy and just doesnt work right so i wanna ask if there is a different/better way of doing this?
Yes, you would patch instead.
patch?
Welcome back to another episode of Vivi's insane UI code
what about soul pos?
card.children.floating_sprite:set_sprite_pos({x = x, y = y})
ty
how do you add legendary jokers into the shop
Hook get_current_pool
Is there a way by looking at the crash log to figure out which mod or mods causes the crash
if it's not in a lovely patch, then yea it should usually be able to tell you which mod the crash happened in (and the file, and even the line number)
depends on the crash tho, sometimes it's crashing because modded code is sending improper arguments to a vanilla function and that means you might have to dig through the stack trace a bit
just post the crash tho, easier to have more eyes on it
yes should i not have it, im new here lol
i think you have a different balatro+ to the one i'm thinking of
god, where do they keep the definitions
more importantly tho, i have no idea what mod's causing it sorry
No, it's in common_events
get_current_pool is a vanilla function
Dang, I guess ill have to just go the old fashioned way and disable things until it works, thankfully this time the crash is on the first round before i have any jokers or anything and not on ante 8 round 2 or something
if it's not in the overrides file in smods, then you'll want to look at the lovely dump. as somethingcom said, it's in the functions/common_events.lua file in the lovely dump
all i wanna do is add legendary jokers in the shop and make them free. i thought copying jester's privilege in all in jest would do the trick but apparently it uses a lovely patch to work.
i still dunno where to find documentation on mod config screens tho
doesn't smods have a page dedicated to that
can't find it
how do i use get_current_pool to do that though?
i found the page for ui but not one for mod config
isn't there something to instantly win a blind
the button in the debugplus tab screen?
pretty much
There's this page https://github.com/Steamodded/Wiki/blob/cc0a21927d79bd15c491a01d33341cc86a596097/SMODS.config_tab.md that now no longer exists
found out it's bc it's in the The Mod Object page
how do i use create_option_cycle
it just says it takes an args table
oh i found an example i think
see the source code for implementation, and check the source code or other mods for usage
looking at https://github.com/DivvyCr/Balatro-Preview
if _type == 'Joker' and _append == 'sho' then
local poll = pseudorandom('rarity'..G.GAME.round_resets.ante.._append)
if poll < rate then
_legendary = true
end
end
```?
huh, neat
would i put this in an add_to_deck if it was for a joker
ok guys i feel like im going crazy and it's over something dumb
I'm trying to make a baseball card but for negatives. what would I put for the "context" if to check for negative (currently this is checking for rares)
No, you would put it in the get_current_pool hook.
hmm
if context.other_joker and context.other_joker.edition and context.other_joker.edition.negative then return {xmult = 1.5} end
awesome, that seemed to work, thanks so much :D
how do i fix this
i've already figured that out dw
No, you need to hook it.
oh nvmd
that showed me the w thingy
which is exactly the problem i'm having
you have to set the width in advance
i forget how to do this but you can check it somewhere
yeah that
ignore the if true then but why does this not immedaitely end the round when this blind is selected i just took it from debugplus and feel like it should work
set_blind = function(self, reset, silent)
if true then
G.FUNCS.DT_win_blind = function()
G.GAME.chips = G.GAME.blind.chips
G.STATE = G.STATES.HAND_PLAYED
G.STATE_COMPLETE = true
end_round()
end
end
end,
Because you're just defining a function.
card.edition.key
ty
okay again ignore the if true then but how can i get this to activate after cards are drawn because it's being all weird as of now
if true then
G.E_MANAGER:add_event(Event({
trigger = "after",
delay = 1,
func = function()
G.GAME.chips = G.GAME.blind.chips
G.STATE = G.STATES.HAND_PLAYED
G.STATE_COMPLETE = true
end_round()
return true
end
}))
end
Put it in another event.
like literally
if true then
G.E_MANAGER:add_event(Event({
trigger = "after",
delay = 1,
func = function()
G.E_MANAGER:add_event(Event({
trigger = "after",
delay = 1,
func = function()
G.GAME.chips = G.GAME.blind.chips
G.STATE = G.STATES.HAND_PLAYED
G.STATE_COMPLETE = true
end_round()
return true
end
}))
return true
end
}))
end
end,
still gets this
It needs to be outside of a joker and you're missing 2 inputs.
What is the goal?
for the cards to be drawn back to deck as if the round had actually ended
like you enter blind -> any effects that happen at like end of round (e.g. gold cards and stuff) -> draw cards back -> all that
inputs?
High card deck skin
The cards they are the same from High card
it's just the very popular high card deck skin
They are from an anime
i just find it funny that you randomly come in here and go "high card deck skin!"
Cause the anime is cool
took a small break, i got it out of the joker
You're still missing 2 function arguments.
how do i make a custom language
i'm trying to figure it out myself but i'm lost
your hook should have the same arguments as the original function
like this?
i want to make it so that if the played poker hand is a flush, cards get upgraded by +50 chips when scored but it just crashes
this is a blind btw
calculate = function(self, blind, context)
if next(context.poker_hands["Flush"]) then
if context.individual and context.cardarea == G.play then
context.other_card.ability.perma_bonus = (context.other_card.ability.perma_bonus or 0) + self.config.chips
return {
message = localize("k_upgrade_ex"),
colour = G.C.CHIPS
}
end
end
end,
try putting the outer if condition inside the context.individual one
umm
i think its also missing _append?
nope it just crashes with this error
this the code that gon make legendary jokers show up in the shop
how does someone go around about removing the shaders on a booster pack object
glalaflwap how fix 💔
i'm still waiting for someone to correct me
cause i don't know what i'm doing
Rate is underlined yellow, meaning it's an undefined global
how do i define it?
What do you want the rate to be
5% of the time i guess?
Then you can replace it with 1/20
poll < 1/20?
basically a bump but this is happening when selecting my blind
calculate = function(self, blind, context)
if next(context.poker_hands["Flush"]) and context.individual and context.cardarea == G.play then
context.other_card.ability.perma_x_mult = (context.other_card.ability.perma_x_mult or 1) + self.config.xmult
return {
message = localize("k_upgrade_ex"),
colour = G.C.MULT,
}
end
end,
i want it to upgrade played cards if the played hand is a flush
if context.cardarea == G.play and context.individual and next(context.poker_hands["Flush"])
is that not exactly what i did?
No, the order is reversed.
short circuit logic; if theres logic like if x and y and x is false it will not bother to check y at all
how do i replace .png files in a mod from another mod
i want to replace assets/2x/complete_ygg_mat_atlas.png from yggdrasil
but im pretty sure lovely patches are only txt
No, you should replace the atlas.
how do i do that
how do i do that
func = function() G.E_MANAGER:add_event(Event({ func = (function() SMODS.add_card { set = 'Tarot', } G.GAME.consumeable_buffer = 0 return true end) })) end,
So I've got this for generating a random Tarot but how would I make a specific tarot like Justice
why do you write it like that
Idk thats how I got it from someone else
Oh if you mean like visually in discord its because I can't remember how to do the cool thing and make it look nice with lua
i've misread this entirely
calculate = function(self, card, context)
if context.main_scoring and context.cardarea == G.play then
local new_total = math.floor(G.GAME.dollars * self.config.extra.dollar)
local gain = new_total - G.GAME.dollars
ease_dollars(gain, true)
return {
message = "x1.25$",
colour = G.C.MONEY
}
end
end,
replace_base_card = true,
no_rank = true,
no_suit = false,
any_suit = true,
always_scores = false
Trying to make my Enhancement give x1.25 $ of the current money but it wont' work out properly when i play more than one of them (if i play 5 of them it only give x1.25 $ of the current money once and before normally scoring),
hello??
is there a way to know if a lucky card is triggered ?
context.other_card.lucky_trigger
thanks you
You can check Lucky Cat here for full implementation https://github.com/nh6574/VanillaRemade/blob/main/src/jokers.lua
bump
if context.starting_shop then
for i = 1, #G.GAME.tags do
if G.GAME.tags[i]:apply_to_run({ type = 'new_blind_choice' }) then break end
end
end
This code causes all the booster tags to overlap - is there a way to make each tag wait until the previous tag is resolved?
Hello, when I buy my voucher, I always get the same crash. Here is the crash log (message.txt) and my voucher.
SMODS.Voucher{
key="displayset",
loc_txt={
name = "Display Set",
text = {
"{C:gold}+#1#{} Booster Pack",
"in the shop"
}
},
config = {
extra = { booster_slots = 1 }
},
cost = 10,
loc_vars = function(self, info_queue, center)
return { vars = { center.ability.extra.booster_slots } }
end,
redeem = function(self)
G.GAME.modifiers.extra_boosters =(G.GAME.modifiers.extra_boosters or 0) + center.ability.extra.booster_slots
SMODS.add_booster_to_shop()
end
}```
in
redeem = function(self) you need to add center so it gives
redeem = function(self, center)
Oh, thx a lot. The solution make me kind of dumb. But thx.
oh yeah happened to me before, usually when copy pasting the function you tend to forget
oh and if center won't work, replace all centers by card (card.ability, (self ,info_queue, card), etc..
SMODS.add_card{ set = 'Tarot', key = 'c_wheel_of_fortune',skip_materialize = false,}```
in this case it's for wheel of fortune, you just need to replace by the key of justice that must be c_justice or smth like that
return {dollars = (G.GAME.dollars+(G.GAME.dollar_buffer or 0))*(card.ability.extra.dollar-1), dollar_message = {message = 'X'..card.ability.extra.dollar..localize('$'), colour = G.C.MONEY, sound = 'coin3'}}
got this error
also i changed the card.ability.extra.dollar by self.ability.extra.dollar since it's what i used in my config, unless i must change that too
config = { extra = { dollar = 1.25}},
loc_vars = function(self, info_queue, card)
return { vars = {self.config.extra.dollar } }
end```
No, it's card.ability.extra.dollar
config = { extra = { dollar = 1.25}},
loc_vars = function(self, info_queue, card)
return { vars = {card.ability.extra.dollar } }
end,
calculate = function(self, card, context)
if context.main_scoring and context.cardarea == G.play then
return {dollars = (G.GAME.dollars+G.GAME.dollar_buffer)*(card.ability.extra.dollar-1), remove_default_message = true, message = 'X'..card.ability.extra.dollar..localize('$'), colour = G.C.MONEY}
end
end,```
same error but i did kept card.ability.extra.dollar and changed it in config
(G.GAME.dollar_buffer or 0)
Also it's return {dollars = (G.GAME.dollars+(G.GAME.dollar_buffer or 0))*(card.ability.extra.dollar-1), dollar_message = {message = 'X'..card.ability.extra.dollar..localize('$'), colour = G.C.MONEY, sound = 'coin3'}}
I did figured i had to replaced the G.Game.dollar_buffer by this, but thanks it works now
i'm sorry for not working on this for long enough (i fell asleep)
local oldgetcurrentpool = get_current_pool
function get_current_pool(_type, _rarity, _legendary, _append)
if _type == 'Joker' and _append == 'sho' then
local poll = pseudorandom('rarity'..G.GAME.round_resets.ante.._append)
if poll < (1/20) then
_legendary = true
end
end
return oldgetcurrentpool(_type, _rarity, _legendary, _append)
end
if next(SMODS.find_card('j_modprefix_key'))
right above return oldgetcurrentpool?
No, in the if
which if?
The first if
oh right under function get_current_pool?
is it possible to override Small Blind object? can I make it where its like the boss blind of being different each ante somehow?
you can change any blind position to any other blind, though changing a non-boss to a boss and vice versa doesnt work very well by default so you need patches to make it work as expected
jimbo works as intended
now i need to fix the issue that is asriel spawning multiple fucking astros
I feel like i should know how to make this check if there's atleast one astro then disable completely.```lua
remove_from_deck = function(self, card)
if not G.CONTROLLER.locks.selling_card then
SMODS.add_card{ key = "j_busterb_astro", edition = 'e_negative', stickers = {'eternal'}, force_stickers = true }
end
end
This should work, right?lua remove_from_deck = function(self, card) local nomoreastros = 0 if not G.CONTROLLER.locks.selling_card and not nomoreastros >= 1 then SMODS.add_card{ key = "j_busterb_astro", edition = 'e_negative', stickers = {'eternal'}, force_stickers = true } nomoreastros = nomoreastros + 1 end end
No, because if it's spawning multiple jokers that means remove_from_deck is being called multiple times.
It happens to trigger whenever something outside of editions or whatever modifies it
This time it’s an update function
currently it's this onelua update = function(self, card, dt) if G.jokers then for _index, _joker in ipairs(G.jokers.cards) do if _joker.config.center.key ~= 'j_busterb_joker' then Blockbuster.manipulate_value(_joker, "jkrvm", card.ability.extra.valuemodification) end end end end,
That would make every joker other than j_busterb_joker have infinite values.
You should ask ice, he’s the one who developed the api
what would be a better way to do this?
No, it's because you're running it every frame so it will increase the values until it reaches infinity.
Actually the values are static, I tried it myself.
You would do it in add_to_deck and context.card_added
Idk how but it is
add_to_deck = function(self, card, from_debuff)
if context.card_added then
if G.jokers then
for _index, _joker in ipairs(G.jokers.cards) do
if _joker.config.center.key ~= 'j_busterb_joker' then
Blockbuster.manipulate_value(_joker, "jkrvm", card.ability.extra.valuemodification)
end
end
end
end
end,```
No, you would do it in add_to_deck and you would also do it in context.card_added in calculate
wait, so i write it in both?
Yes.
add_to_deck does it once to all the cards the player already has upon acquiring this joker, context.card_added does it once to each card the player acquires after this joker
Wait, would Jimbo auto recalibrate other jokers if modified? (X10 Values > +10 Mult, X20 Values > +20 Mult)
acquiring another jimbo does this apparently
i really want to change the way asriel spawns an astro
No.
first time trying to make an edition with a spectral card, and i cant see it in the menu for some reason
You can't see what in what menu?
cant see the spectral card and the edition
Code?
this is extremely primitive
guys how would i make a custom challenge rule that multiplies blindsize by dollars owned?
if context.money_altered then G.GAME.starting_params.ante_scaling = G.GAME.starting_params.ante_scaling + context.amount end
this multiplies or adds?
It multiplies.
like this it crashes
it needs to be in a calculate function
still crashes
attempt to index local 'context' a nil value
for challenges, the calculate function is just function(self, context)
how do people even make shaders
math and coding
they look so hard to comprehend
they're written in GLSL, the opengl shader language. there are some good resources out on the internet for how it works
the example shaders in the smods examples repository can also be helpful (one of them is particularly documented with comments, ionized.fs iirc)
I made an enhancement that gains Xchips or Xmult when held in hand.
The problem is that when I create said enhancement it starts endlessly gaining said amounts even if a hand hasn't been played.
How can I fix this?
(maybe by putting another context in the first if but I don't remember which one it was...)
yea you need another context
probably context.before, context.main_scoring, or context.after, depending on the timing you want
(context.before upgrades it before any scoring, context.main_scoring upgrades it when a steel card would score, and context.after upgrades it after all the scoring is done)
aight, thx!
also do you know a better a better description for this joker I made?
does the poker hand cycle or is it always high card? i assume the latter
it's always high card
Yes, it would be lose the run immediately not lose immediately the run
ok
Level up played [2;33mHigh Cards[0m and [2;33mretrigger[0m
all played cards [2;33m4[0m times.
[2;36m1 in 20[0m chance to set money to be negative
or [2;31mimmediately lose the run[0m
many thanks you both!
any reason why this doesn't work at all?
if context.setting_blind and (context.blind == "bl_small" or context.blind == "bl_big") then
return {
dollars = -card.ability.extra.dollars1,
colour = G.C.RED
}
end
context.blind isnt a thing afaik
oh i'm dumb
or if it is its probably a table
and not a key
just check G.GAME.blind.config.blind.key
iirc
so just replace the context.blinds with that?
yes
ok thank you
what
are you like adding new types of blinds or something
only seems to work on small blinds for some reason
(context.blind.key == 'bl_small' or context.blind.key == 'bl_big')
context.blind:get_type() ~= "Boss", even
gifs are blocked >:(
No, it would be not context.blind.boss
context.blind is not a blind, it is the center.
G.GAME.blind.config.blind.key gives you the key doesnt it
config = { extra = { mult = 0, dollars = 0, mult_mod = 2, dollars_mod = 1, odds = 4 } },
loc_vars = function(self, info_queue, card)
info_queue[#info_queue + 1] = G.P_CENTERS.m_lucky
local lucky_tally = 0
if G.playing_cards then
for _, playing_card in ipairs(G.playing_cards) do
if SMODS.has_enhancement(playing_card, "m_lucky") then
lucky_tally = lucky_tally + 1
end
end
end
local numerator, denominator = SMODS.get_probability_vars(card, 1, card.ability.extra.odds)
return {vars = { card.ability.extra.mult_mod * lucky_tally, card.ability.extra.dollars_mod * lucky_tally, numerator, denominator } }
end,
i cant get the chance to appear accurately
"has a {C:green}#3# in #4#{} chance to become a lucky card",
i have this and it just doesnt work idk why( it says 1 in 4 accurately but obtaining an oops all sixes doesnt make it go to 2 in 4)
it looks correct to me, are you sure you saved the file
does oops work with other jokers that have probabilities
wait yeah my file doesnt update
i just put a test in there and it doesnt work
maybe you're writing in the wrong file
another issue
if suit_card:is_suit('Diamonds') then
local dollars = (G.GAME.dollars or 0) + (G.GAME.dollar_buffer or 0)
local xmult_factor = math.floor(dollars / card.ability.extra.dollars)
result.Xmult = xmult_factor > 0 and (card.ability.extra.Xmult_mod * xmult_factor + 1) or 1
result.message = "earth"
result.colour = G.C.SUITS.Diamonds
elseif suit_card:is_suit('Spades') then
result.mult = card.ability.extra.mult
result.message = "Air"
result.colour = G.C.WHITE
elseif suit_card:is_suit('Clubs') then
result.chips = card.ability.extra.chips
result.message = "Water"
result.colour = G.C.CHIPS
end
return result
when i have smeared and play spades and clubs only the spades apply, how do i make that work?
using elseif means it will only enter through one of those conditions
so how do i make it go through all?
Make them separate conditions
well you can do 3 different if statements, but what do you even want it to do when you play a wild card for example
cus if you just make it separate conditions rn only the last one met will actually matter
okay so for example
playing smeared would trigger diamonds and hearts(hearts is before round so doesnt matter) or spades and clubs
wild cards would trigger all 4
I think that's quite a bit more complicated then if you want it to show multiple messages
maybe
I think you want something like this
local effects = {}
if is diamonds then
effects[#effects + 1] = {
Xmult = something,
message = "Earth",
colour = something
}
end
-- the rest of the if statements the same as above
return SMODS.merge_effects(effects)
local effects = {}
if suit_card:is_suit('Diamonds') then
local result = {}
local dollars = (G.GAME.dollars or 0) + (G.GAME.dollar_buffer or 0)
local xmult_factor = math.floor(dollars / card.ability.extra.dollars)
result.Xmult = xmult_factor > 0 and (card.ability.extra.Xmult_mod * xmult_factor + 1) or 1
result.message = "earth"
result.colour = G.C.SUITS.Diamonds
table.insert(effects, result)
end
if suit_card:is_suit('Spades') then
local result = {}
result.mult = card.ability.extra.mult
result.message = "Air"
result.colour = G.C.WHITE
table.insert(effects, result)
end
if suit_card:is_suit('Clubs') then
local result = {}
result.chips = card.ability.extra.chips
result.message = "Water"
result.colour = G.C.CHIPS
table.insert(effects, result)
end
return SMODS.merge_effects(effects)
that gives this
wait a sec
Code?
Is it possible to check if a mod of higher priority is loaded? afaik SMODS.can_load only checks priorities under ours
what would be the goal
creating a joker compatible with multiplayer, but multiplayer has a crazy high priority
you can just make the number even higher
Yes, SMODS.find_mod
thx
can't seem to make the message transmission properly work anyway
one game does send the message but the other seems to never receive it
is there a possiblity that the multiplayer servers filter messages that aren't from the base mod
tryna copy trib and sock at the same time but only the one on the left gets triggered
local my_pos, effects = 0, {}
for k, v in pairs(G.jokers.cards) do
if v == card then my_pos = k end
end
for i, v in ipairs({-1, 1}) do
if G.jokers.cards[my_pos+v] then
table.insert(effects, SMODS.blueprint_effect(card, G.jokers.cards[my_pos+v]))
end
end
return SMODS.merge_effects(effects)
I wanna see if its possible to basically overhaul the playing cards into something else is that possible?
wdym
like something similar to https://discord.com/channels/1116389027176787968/1433445606071734374 ?
I guess like that posts sent similar to this
so like blindside essentially?
yes its possible
you need enhancements that dont show rank or suit
i see thats a cool way to do it I just was curious the implentations with playing cards and if it could be adjusted
not like mod send excactly just how it changed playing cards but i get what you mean
Yea exactly like this just to test some stuff I wanted to try out implenting how was this done any code or git made?
Yea it's got code and stuff though I'm not sure if it's publicly available, i'd ask the post's creator.
This thing's effect doesn't apply retroactively. Any pointers?
[[patches]]
[patches.pattern]
target = "card.lua"
pattern = "self.sell_cost = math.max(1, math.floor(self.cost/2)) + (self.ability.extra_value or 0)"
position = "at"
payload = '''
local results = SMODS.find_card('j_lapsems_refund')
if (#results > 0) then
self.sell_cost = math.max(1, math.floor(self.cost * results[1].ability.extra.sale_increase)) + (self.ability.extra_value or 0)
else
self.sell_cost = math.max(1, math.floor(self.cost/2)) + (self.ability.extra_value or 0)
end
'''
match_indent = true
# Also, the card's `sale_increase` is set to 1.
a theme update might be "store credit"
you should probably just hook Card:set_cost
and then set the cost of all owned jokers in add_to_deck
and remove
like when i buy old video games and home media usually unless it doesn't work you can only just like exchange it out for another thing or get store credit
The line of code that I'm hooking comes from Card:set_cost()!
also usually at least the mom and pop stores you go to its usually better to get the store credit instead of a cash refund as you get more and usually you are already there to get something if that makes sense
oh fuck :mister bones:
i would fuck mister bones
ok
oh fuck! i want to get off mr bones wild (card) ride
what about ascensio mr bones
hell no
good
Getting back on topic, I patched rather than hook 'cause I wanted to override the game's code of halving buy price to produce sell price under all other circumstances.
And would I need to add add_to_deck() and remove_from_deck() functions too?
a hook can do that too though
well you need to reset the cost of all cards in add/remove from deck anyway
wait no
uhhh
fuck
nvm
Yeah, that could specify something that was bought for $5 instead sell for $4.
Also, is your profile image a Dalek?
okay well the patch might be the only clean option
D'you think I could combine a hook and a patch?
no reaosn i think
but you should still loop over G.I.CARD and set the cost of everything when the card is added or removed
to make it apply retroactively
and also go away when you get rid of it
Within a hook, yes?
In add_to_deck()?
yes
And remove_from_deck() too?
yes
One more thing for now: is there any significance to the patch files' names, or can I name them whatever I please?
as long as they are in a folder named lovely the name doesnt matter
Does remove_from_deck() get called after the relevant card is removed? I want to check first thing that #SMODS.find_card('j_lapsems_refund') <= 0, so that the card's ability is binary, like Showman and Shortcut.
it gets called after its removed
you shouldnt need to check if there is another copy since thats already checked in the patch
Any pointers, @clear ocean?
Another day of hotfixes
what
He would
what's not clear
hey guys
how do i make it so that a joker gives +mult everytime a stone card is scored?
vanillaremade is a great resource
check e.g. any of the jokers that give +mult every time a [suit] card is scored, and then swap the suit condition with checking for if the currently scored card is stone
if context.individual and context.cardarea == G.play and SMODS.has_enhancement(context.other_card, 'm_stone') then return {mult = number} end
what is my balatro doing...... (guys I dont think 'not' and '==' are arithmetic 😭) The error is coming from the variable named showdown
Log?
What does get_new_boss look like in the lovely dump?
That means the boss that it has chosen is not a valid blind key.
huh, I must've removed a check for that by mistake lol
alr I fixed it :D (twas one line of code 😭)
yippie my balatro is balatroing again
OH MY GOD
the imposing wall
evil ass wall
oh my god this isn’t modding chat
Having issues with trying to make a joker that works if you discard five cards of a required suit
Core logic happens in here
Am I misinterpreting how G.GAME.current_round.discards_left works
Here is the crash if this adds any additional context
should be :is_suit not .is_suit
Ur right but somehow that wasn't the only issue
send the whole crash
ctrl c ctrl v here
It stopped crashing, it just doesn't work logically now
There's this too, maybe something is wrong here
might just be from the bad naming, trash_suit and trash_suits are different
at the start it sets it to a table if its nil
also in the loop it checks for trash_card
I think I see what you mean
Basically its supposed to create a spectral card if you discard 5 of the right suit
Nothing is breaking anymore, but it isnt giving the spectral card when meeting the requirements
Looks like this now
still checks trash_card and therefore duplicate suits can be pulled twice in a row

