#💻・modding-dev
1 messages · Page 697 of 1
It's made by a different person
I found this in the googology discord
Which I just found out exists
Anyways I expect this in amulet in 3 seconds thanks /j
Do you know what f_ε₀(9e15) is because I most certainly don't
No
when is this coming out? or is this already out?
Also, is there any timeframe for support for custom Small/Big Blinds?
is there a way to make it so when you use a consumable, it isnt used up
there's not really a timeframe
most likely the next release
keep_on_use
it's in the docs
ah whoops that's what I get for relying on my memory
what could be potentially causing this error within the hook?
-- card_removed, fires when a card is removed for any reason
local remove_card_ref = CardArea.remove_card
function CardArea:remove_card(card, discarded_only)
remove_card_ref(self, card, discarded_only)
SMODS.calculate_context({
card_removed = true,
other_card = card,
cardarea = card.area
})
end```
you didn't return the original return
idk whether that function normally returns something but it's good practice even when it doesn't
This has probably been asked a million times but I can't find anything via Discord search;
How do I update the "Choose your next Blind" UI?
What are your goals?
yea i think i forgot to return card, oops
yea that was it
For my sake? I just need the Score-Numbers to update 
It’s something like create_blind_select from memory
I'll check for it, thanks 
so i have my music working.. now i just need to make sure it only plays if i have a certain card.. lemme try smth first
hmmmmm yea no im gonna need some help
something like this
i got the music working for the music playing on blind but i want the music to play if like you have a certain card
i do have smods.find_card
can i see the code
yeah you can also do #... > 0 if you want it would be the same as next()
yea i remember now.. i didnt even need the if variable if the thing was true anyway
ah a better check than string.len(G.GAME.bind.name) > 0 is G.GAME.blind.in_blind
so like how do i check how much cards with a certain pool exist
like i can convert to number but like whats the SMODS.find_card version
you would need to loop through G.jokers.cards and check each one
bump
-# Just for completions sake:
It's "G:update_blind_select(dt)"
A complete reset (without animations) looks like this:lua stop_use() G.blind_prompt_box:remove() G.blind_select:remove() G.blind_select = nil G.STATE_COMPLETE = false G:update_blind_select(0)
also where am i missing my comma
saving this
If you want all the Animations, just search for the select Blind code 
-> G.FUNCS.select_blind = function(e)
-# And remove all the "selecting blind stuff" ig x3
someone actually please help me with this.. it would crash the game and like i need to know how to do this without balatro lagging
not on this image
w8 wut
I see no missing comma on this image
what's the crash and what's around this lines it points to
nvm i removed it
remind me what causes this again
game.lua:2832: bad argument #1 to 'push' (boolean, number, string, love type, or table expected)
Additional Context:
Balatro Version: 1.0.1o-FULL
Modded Version: 1.0.0~BETA-1620a-STEAMODDED
LÖVE Version: 11.5.0
Lovely Version: 0.9.0
Platform: Windows
Steamodded Mods:
1: CirnoTV & Friends by DaemonTsun, NopeTooFast [ID: CTVaF, Priority: 999, Version: 1.003.126, Uses Lovely]
2: Malverk by Eremel [ID: malverk, Priority: -999999, Version: 1.1.3a, Uses Lovely]
Lovely Mods:
Stack Traceback
===============
(3) method C function 'push'
(4) Lua upvalue 'gameUpdateRef' at file 'game.lua:2832'
Local variables:
self = table: 0x03bb3dd8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:false, HUD_tags:table: 0x04d4b220, F_ENGLISH_ONLY:false, viewed_stake:1, HUD:table: 0x18d31c78 (more...)}
dt = number: 0.0166613
(5) Lua method 'update' at Steamodded file 'src/ui.lua:456'
Local variables:
self = table: 0x03bb3dd8 {F_GUIDE:false, F_CRASH_REPORTS:false, F_QUIT_BUTTON:false, HUD_tags:table: 0x04d4b220, F_ENGLISH_ONLY:false, viewed_stake:1, HUD:table: 0x18d31c78 (more...)}
dt = number: 0.0166613
(6) Lua field 'update' at file 'main.lua:1024'
Local variables:
dt = number: 0.0166613
(7) Lua function '?' at file 'main.lua:962' (best guess)
(8) global C function 'xpcall'
(9) LÖVE function at file 'boot.lua:377' (best guess)
Local variables:
func = Lua function '?' (defined at line 933 of chunk main.lua)
inerror = boolean: true
deferErrhand = Lua function '(LÖVE Function)' (defined at line 348 of chunk [love "boot.lua"])
earlyinit = Lua function '(LÖVE Function)' (defined at line 355 of chunk [love "boot.lua"])```
trying to save a function
my culprit is here, but i'm not sure where
wait what
this crash is occurring when winning (on ante 8 beaten), though
you're probably saving a function to the profile
and functions can't be serialized
i dont see it there tho
oh i see what it could be
you're using a table as a table key
selected_back_key is a table despite the name
how does one mark a consumable as being unable to be perkeod
take ownership or patch perkeo's effect
i see
anyone know why the card scaling is being retriggered despite being in a not context.joker_retrigger check?
before anyone suggests it, this isn't blueprint retriggering
I think it's context.retrigger_joker, not context.joker_retrigger !
np! 
My booster packs arent showing their description and idk why
here's some relevant files
you have your booster descriptions in misc.Other, which doesn't mean anything
pretty sure there's supposed to go in descriptions.Booster
but for Other it would be in descriptions too, and not misc
do you know if theres a page on the SMODS wiki that has any info on stuff like this, im trying to find it and failing
patching or take ownership
its descriptions.Other for boosters too
descriptions.Booster doesnt exist
i managed to find takinng ownership so i should be good hohpefuly
fun. might have to make that clearer on the wiki
Any word on when that's coming? My mod has a few such Blinds and I want to wait until this Steamodded release to release it.
no promises or fixed timelines, but I'd say it's likely to be next week
Oh, it won't be done before then. I've got to have some guest artists illustrate the non-Blind things.
is there a way to find out what cards held in hand will trigger a held in hand effect, and what cards wont, like a context or something?
if context.cardarea == G.hand and context.main_scoring then
--
end
SMODS.Atlas {
key = 'hector',
path = 'hector.png',
px = 71,
py = 95
}
SMODS.Sound {
key = 'bell',
path = 'bell.ogg',
}
SMODS.Joker {
key = 'hector',
loc_txt = {
name = "Jimbo Salamanca",
text = {
"Plays a {C:gold}bell sound{} every {C:attention}click{}",
"If {C:attention}CPS{} is {C:attention}10+{}, {C:red}explode{}",
"{C:inactive}({}{C:red}Explode:{} {C:inactive}destroy self and adjacent {}{C:attention}Jokers,{} {C:red}ignore{} {C:enhanced}Eternal{}{C:inactive}){}"
}
},
atlas = 'hector',
pos = { x = 0, y = 0 },
rarity = 2,
cost = 4,
blueprint_compat = false,
eternal_compat = true,
perishable_compat = true,
unlocked = true,
discovered = true,
calculate = function(self, card, context)
if context.sink_press then
G.E_MANAGER:add_event(Event({
func = function()
print('skbidi toielt')
play_sound('sink_bell')
return true
end
}))
end
end
}
return {
init = function()
local lcpref = Controller.L_cursor_press
function Controller:L_cursor_press(x, y)
lcpref(self, x, y)
if G and G.jokers and G.jokers.cards and not G.SETTINGS.paused then
SMODS.calculate_context({ sink_press = true })
end
end
end,
}```
heres joker lua
any other file u needed to see?
do you run this init function somewhere
seems like a badly copied thing from cryptid to me
You would have to hook eval_card
how would i do that?
local oldevalcard = eval_card
function eval_card(card, context)
if not card then return end
local g, post = oldevalcard(card, context)
if not card:can_calculate(context.ignore_debuff, context.remove_playing_cards or context.joker_type_destroyed) then return g, post end
if context.main_scoring and context.cardarea == G.hand and next(g) then
card.modprefix_trigger_held_in_hand_effect = true
else
card.modprefix_trigger_held_in_hand_effect = nil
end
return g, post
end
it is 😭
thank you very much twin
fuck
wrong arguments
SMODS.Joker:take_ownership("perkeo", {
calculate = function(self, card, context)
if context.ending_shop then
local pool = {}
for _, c in ipairs(G.consumeables.cards) do
if c.set ~= "astrological" then
pool[#pool + 1] = c
end
end
if #pool > 0 then
local chosen = pseudorandom_element(pool, pseudoseed("perkeo"))
local copy = copy_card(chosen)
copy:set_edition("e_negative")
copy:add_to_deck()
G.consumeables:emplace(copy)
end
return true
end
return nil
end
})
something about this isnt working, its not ignoring the set
It should be c.ability.set
Also it should be return nil, true instead of return true
You spelled ability wrong.
return{
card.ability.extra.payphonemult == card.ability.extra.payphonemult - card.ability.extra.payphonemult_minus
}```
why is it not subtracting cuh
...why are you return-ing that?
can i not return that
just card.ability.extra.payphonemult == card.ability.extra.payphonemult - card.ability.extra.payphonemult_cost
the full thing is
if context.blind_defeated then
return{
card.ability.extra.payphonemult == card.ability.extra.payphonemult - card.ability.extra.payphonemult_minus
}
end```
It should be card.ability.extra.payphonemult = card.ability.extra.payphonemult - card.ability.extra.payphonemult_minus outside of the return
if condition then
value = value - subtractvalue
end
thanks guys
question
how do yall make those messages that appear below jokers
for instance
when a round is over
a joker displays a "(amount of mult left) Mult"
how can you do that
return {message = 'message'}
amazing
time for even more testing
damn, most of info queue is full custom huh
makes sense
Fortunately I made some sort of api to deal with this
after I made vanilla work properly of course xd
Is there a setAbility equivalent for seals? I had working enhancements but I had to convert my code to seals for art/balance purposes and I can't get the right functions going
Remove the localize()
You mean you want to do something when the seal is set on a card?
and if setAbility does work with seals then I'm unsure as to why its never being called regardless of me putting seals onto stuff, it also crashes my Calculate functions
SMODS.Seal({
key = 'cup_seal',
atlas = 'Enhancers',
pos = { x = 2, y = 0 },
badge_colour = G.C.GREEN,
config = { extra = { chips = 5, rank = 'Rank', rankInt = 0 } },
loc_vars = function(self, info_queue, card)
return { vars = { self.config.extra.chips, self.config.extra.rank, self.config.extra.chips * countRanks(card) }, key = self.key }
end,
set_ability = function(self, card, initial, delay_sprites)
setRank(self, card)
end,
calculate = function(self, card, context)
if context.main_scoring and context.cardarea == G.hand then
local count = countRanks(self, card)
return { chips = card.ability.extra.chips * count }
end
end,
draw = function(self, card, layer)
draw(card, layer)
end
})
You would have to hook Card:set_seal
i don't know how i didn't notice that 😭
damn so there's something for enhancements but not for seals
I'm a little worried that it wont work the way I do it but I'll try 😭
i've prob asked this before, but if i have an integer value from 2-14, what's the easiest way to turn that integer into a corresponding rank string?
local rank = nil
for k, v in pairs(SMODS.Ranks) do
if v.id == id then
rank = v.key
end
end
ty!
Better you should put that in a function call so you don't have to constantly rewrite the code.
is there a reason that it's saying my function is unused?
Yes, because you're using it before you define it, so the LSP thinks that it doesn't exist and you aren't using it.
should i just move the function above that code then?
Yes.
local jokers = {}
for k, v in pairs(get_current_pool('Joker')) do
if G.P_CENTERS[v] then
if G.P_CENTERS[v].set == 'Joker' and G.P_CENTERS[v].original_mod then
table.insert(jokers, G.P_CENTERS[v].key)
end
end
end
local key = pseudorandom_element(jokers, 'seed')
SMODS.create_card({set = 'Joker', key = key})
Yes, but not weights.
how do you add custom sounds
yea
my mod has modname/assets/gun.ogg
atlas looks like this SMODS.Sound({ key = "gun", path = "gun.ogg" })
modname/assets/sounds/gun.ogg
oh yeah thats what i meant
what's the problem then
how does it crash
Are you adding the mod prefix to the key when you are using it?
send the code
its supposed to be assets/sounds/thingamabob.ogg right
thats what im guessing is wrong
play_sound('modprefix_soundkey')
is the crash could not find sound gun
lemme take a look at the crash log
did you add the prefix like this
says it dont exist
what doesn't exist
the gun.ogg file
let me check one sec
that's bc it's looking in the vanilla directory
add the mod prefix like all 3 of us have said
you didn't add the prefix
ok
yall fw angry birds
welp it crashed again
SMODS.Sound({ key = "add_sus", path = "sounds/sus.ogg" }) SMODS.Sound({ key = "add_gun", path = "sounds/gun.ogg" })
sorry if i am being frustrating i am amateur at the lua language
@dapper sun thank you it worked
yw

not what i expected by it being incompatible with weights
What is that line in common_events.lua?
also why aren't we just checking for the center having a mod entry
i'm not wanting all mods equally i just want modded jokers
okay i cut the code down to this
local jokers = {}
for k, v in pairs(get_current_pool('Joker')) do
if G.P_CENTERS[v] then
if G.P_CENTERS[v].set == 'Joker' and G.P_CENTERS[v].mod then
table.insert(jokers, G.P_CENTERS[v].key)
end
end
end
local key = pseudorandom_element(jokers, 'elle_becca_shop_modded_j')```and now it only crashed when i rerolled (this is for a custom shop)
okay i tried on a new run
it seems to just happen a lot of the time
No, you should be checking for G.P_CENTERS[v].original_mod
I also edited the code to fix it.
Yes.
okay now it's spawning vanilla jokers just fine
local mod_txt = 'elle_rebecca_modifier_'..G.GAME.elle_popup_shops.rebecca.modifier
local modifier = ellejokers.rebecca_modifiers[G.GAME.elle_popup_shops.rebecca.modifier]
local modifier_lines = {}
localize({set='Other', key=mod_txt, type='descriptions', vars=modifier.loc_vars and modifier:loc_vars() or nil, nodes = modifier_lines,default_col=G.C.UI.TEXT_LIGHT})```for some reason this makes the game freeze up and overflow crash
(no crash screen given)
if you're on zeebee or higher and you have object weights on you can pass a filter function which filters the pool to add_card
oh that's so much easier
how do i use that
my mod enables weights so i can just use that
like you just pass filter = function(pool) [do stuff] return pool, in the table passed to add_card
SMODS.create_card({set = 'Joker', attributes = {}, filter = function(pool)
local new_pool = {}
for k, v in pairs(pool) do
if v.type == 'Joker' and G.P_CENTERS[v.key].original_mod then
table.insert(new_pool, v)
end
end
return new_pool
end})
okay yeah it does check for the attributes table for some reasoni just checked
odd
ill push so you can look
SMODS.add_card {
set = "Joker",
attributes = { "Joker" },
filter = function ( pool )
local new_pool = {}
for k, v in pairs(pool) do
if G.P_CENTERS[v.key].original_mod then
table.insert(new_pool, v)
end
end
return new_pool
end,
}
this works for me
oh you need set = joker and attributes = joker
i added both of those
okay ill take a look
Did you copy the code before I added the return new_pool?
is whats on github what you have rn
apart from the return
you need set = "Joker" and attributes = {"Joker"}
this
i'm setting the attrubutes to joker here
and i'm setting the set here
tyy
okay it works for me wtf ? ???
weird
No, it works without that.
what smods ver
ohhh you have no commons
oh
except jess pin
yeah lol
this-
oh 😭
How can this be fixed to fit the description of "all cards debuffed if a card is sold, used, or destroyed"
calculate = function(self, blind, context)
if context.selling_card or context.using_consumeable or context.joker_type_destroyed then
for k, v in pairs(G.playing_cards) do
SMODS.debuff_card(v, true, self.key)
end
end
end,
disable = function(self)
for k, v in pairs(G.playing_cards) do
SMODS.debuff_card(v, false, self.key)
end
end,
defeat = function(self)
for k, v in pairs(G.playing_cards) do
SMODS.debuff_card(v, false, self.key)
end
end,
o oke
is it possible to spawn in cards that have in_pool as false with add_card?
if not is there a workaround to take ownership before and after adding the card because i tried that and it just popped up a bunch of messages about tracking the jokers
Yes.
is there a flag that i have to set for that because currently it's not spawning in any cards that aren't in the pool so im wondering if that is the issue or if there's a different issue
local pool = {}
for k, v in pairs(G.P_CENTER_POOLS.poolkey) do
table.insert(pool, v.key)
end
local key = pseudorandom_element(pool, 'seed')
SMODS.add_card({key = key})
solution? add a fallback jimbo if the pool is empty
is it possible to make a rank use different sprites if it has a certain enhancement?
Yes, you would call card:set_sprites(card.config.center, card.config.card) when it's added and removed and you would hook or patch Card:set_sprites and you would change the sprite there.
thanks
does this actually change the condition of any specific achievement or any achievements at all?
local unlockconditionref = SMODS.Achievement.unlock_condition;
function SMODS.Achievement:unlock_condition(args)
if args.type = "siuwa"
return true
end
end;
you are hooking the default unlock condition, this will only affect achievements without a condition (none of them)
how do I that to each achievement? or a specific set of achievement without repeating it for each achievement
whatever = SMODS.Achievement:extend{
unlock_condition = function(self, args)
--...
end
}
then use the defined whatever instead of SMODS.Achievement for said set of achievements
I also recommend putting said whatever in a table for your mod or prefixing it with your mod prefix
is there a way to have a joker apply showman like effects for a single consumable type
hook SMODS.showman(card_key)
card_key is the key of the card in the pool, you would need to check if it's from that consumable type
why are there so many braces
gave me error without them
for some reason
something like "missing symbol } at line 56"
What are you using to edit your code?
notepad
You should not do that
ok hold on,
notepad notepad or notepad++
notepad notepad
important distinction
ew
I’d recommend using something that will show you bracket pairs
ok yeah don't use notepad notepad
sometimes whatever idea my friend suggest to me, i cant find a way to implement it as a joker
like one time he said "make a joker that gains mult every second" and i just cant figure out a way to implement that.
eremel am I allowed to ask questions about generate_card_ui shit to you?
Because I have one
Sure
i wouldve use visual studio but it wont let me open the lua file
Here's a deal.
I'm generating card's description just like LocalThunk intented:
local new_card = copy_card(card, nil, 1, nil, nil)
main_card_area:emplace(new_card)
new_card.ability_UIBox_table = new_card:generate_UIBox_ability_table()
local popup = G.UIDEF.card_h_popup(new_card)
new_card.no_ui = true
Then I'm using result and render it. It works for most cards just fine, but I have problem when it's about stickers. Specifically, their display in collection.
For some reason, UI and info_queue I'm gettings does not match what I expect to get. I expect get thing on right, but I got what on bottom
And since stickers is insane junk I'm not sure what to do
you can use the update function to increment the value in real time using G.real_dt or G.TIMERS.REAL
as copy_card I use card from stickers collection, eternal sticker for example
If you need mod where I'm doing things I can add it to git
pinned "sticker" works just fine btw
Sounds like the input is wrong
hm, maybe I'm indeed doing it not properly somehow, because if I call card:hover() info_queue is correct
return a sound with a message in calculate or use play_sound()
can i see a list of all the sounds
it's prob out there somewhere in the smods wiki
omg I figured this out
card uses sticker's info_queue to build own description 
that's crazy
I might say that's insane actually
and how I'm supposed to deal with it
managed to get it to work on visual studio, now for some reason its telling me i need a bracket inside the display ranks string???
i don't think there's one
maybe searching here
missing comma after 'Ace'
it thinks you need one to close the table before King because of the missing comma
also I don't recommend VS
oh is this regular visual studio
Okay I did it
Visual Studio isn't built for anything outside C++/C# and other Microsoft-related programming languages
sure, you can do code in it, but it takes way more work to debug since there's no linting at all for lua
question what's the sound effect for when you get money
How do I get ease_background_colour_blind() to actually use the colors correctly rather than just making it black?
This is with
ease_background_colour = function(self)
ease_background_colour_blind(HEX('00FF00'),
HEX('00FF00'))
end,
```(as a test), but when I did
```lua
ease_background_colour = function(self)
ease_background_colour_blind(SMODS.ConsumableTypes['Mannpower'].primary_colour,
SMODS.ConsumableTypes['Mannpower'].secondary_colour)
end,
```, I got the same result.
look at the definition of the function, it doesnt take colours it is hardcoded to certain states
???
im saying to go read ease_background_colour_blind
that will also tell you what you need to do
Which is defined where?
Is there a list of Tag-Contexts?
not that i know but they are all used by the vanilla tags
Alrighty ^w^
I can't find that in the lovely repository
Mods/lovely/dump
That's inconvenient
I realized don't actually understand this thing. Is whatever like... a subclass of SMODS.Achievement with an overriden unlock_condition?
If I want to change a bunch (let's say every) achievement, to this new condition, am I supposed to use it by traversing the table of achievements and say "key now use whatever for key.unlockcondition()"?
what
do you want to change vanilla achievements
what eris said is just to make it easier to make your own without having to repeat the condition
I think I want to
what's the goal
I want to change conditions of achievements to something really easy like args.type = "siuwa" and then unlock them by something like check_for_unlock(type = "siuwa")
for k, v in pairs(G.ACHIEVEMENTS) do
unlock_achievement(k)
end
this will direct unlock it without ever messing with any objects yes?
yes
for now I'll use that, thanks
I know this is a stupod need but one day I'll have a problem worth doing what I thought I need to
(also thanks to eris but I don't want to ping)
Also where can I learn more about the Game class? I know smods/wiki/G has a list of stuff that isn't comprehensive
I'm definitely cooking
key = 'hector',
loc_txt = {
name = "Jimbo Salamanca",
text = {
"Plays a {C:gold}bell sound{} every {C:attention}click{}",
"If player clicks 44 times, {C:red}explode{}",
"{C:inactive}({}{C:red}Explode:{} {C:inactive}destroy self and adjacent {}{C:attention}Jokers,{} {C:red}ignore{} {C:enhanced}Eternal{}{C:inactive}){}",
"{C:inactive}(Currently {}{C:attention}#2#{}{C:inactive} clicks left){}"
}
},
atlas = 'hector',
pos = { x = 0, y = 0 },
rarity = 2,
cost = 4,
blueprint_compat = false,
eternal_compat = true,
perishable_compat = true,
unlocked = true,
discovered = true,
config = { extra = { bellclicks = 0, }, { bellclicksleft = 44, } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.bellclicks }, { card.ability.extra.bellclicksleft } }
end,
calculate = function(self, card, context)
if context.add_to_deck then
card.ability.extra.bellclicks = (card.ability.extra.bellclicks) == 0
card.ability.extra.bellclicksleft = (card.ability.extra.bellclicksleft) == 44
end
if context.remove_from_deck then
card.ability.extra.bellclicks = (card.ability.extra.bellclicks) == 0
card.ability.extra.bellclicksleft = (card.ability.extra.bellclicksleft) == 44
end
if context.sink_press then
if to_big((card.ability.extra.bellclicks or 0)) == to_big(43) then
return {
message = "bemusement"
}
else
card.ability.extra.bellclicks = (card.ability.extra.bellclicks) + 1
card.ability.extra.bellclicksleft = (card.ability.extra.bellclicksleft) - 1
G.E_MANAGER:add_event(Event({
func = function()
print('skbidi toielt')
play_sound('sink_bell')
return true
end
}))
return {
message = "Ding!"
}
end
end
end
}```
sorry for wall of code
damn, my showcase was interrupted immediately
config = { extra = { bellclicks = 0, bellclicksleft = 44, } },
if context.add_to_deck then
card.ability.extra.bellclicks = (card.ability.extra.bellclicks) == 0
card.ability.extra.bellclicksleft = (card.ability.extra.bellclicksleft) == 44
end
if context.remove_from_deck then
card.ability.extra.bellclicks = (card.ability.extra.bellclicks) == 0
card.ability.extra.bellclicksleft = (card.ability.extra.bellclicksleft) == 44
end
if context.sink_press then
if to_big((card.ability.extra.bellclicks or 0)) == to_big(43) then
card.ability.extra.bellclicksleft = (card.ability.extra.bellclicksleft) == 0
for i = 1, #G.jokers.cards do
if G.jokers.cards[i] == card then
if i > 1 then
local left = G.jokers.cards[i - 1]
left:start_dissolve({ HEX("57ecab") }, nil, 1.6)
end
if i < #G.jokers.cards then
local right = G.jokers.cards[i + 1]
right:start_dissolve({ HEX("57ecab") }, nil, 1.6)
end
self:start_dissolve({ HEX("57ecab") }, nil, 1.6)
end
end
else
card.ability.extra.bellclicks = (card.ability.extra.bellclicks) + 1
card.ability.extra.bellclicksleft = (card.ability.extra.bellclicksleft) - 1
G.E_MANAGER:add_event(Event({
func = function()
print('skbidi toielt')
play_sound('sink_bell')
return true
end
}))
return {
message = "Ding!"
}
end
end
end```
theres an error in here when i reach bellclicks == 43
it didn't work
I changed it to for k in pairs and it worked
thats literally the same lol
It should be
the only different is that now you're calling unlock_achievement with 2 arguments, but it doesnt use the second one
what are those add and remove contexts supposed to do
reset the counters
well what it does is change them to booleans indicating whether they were at their base value at that time
if you want to assign, you just do variable = value
variable == value is a comparison, it's asking whether they're already equal
Is this your glossary thing?
How do I get the speed of the mouse cursor?
get the mouse position like this https://github.com/wingedcatgirl/Menthol/blob/main/jokers/neko.lua#L122
then do it again, calculate the distance, and divide by the time
there might be a simpler way but i don't know it if so
also i think i deliberately made that less precise than it could be, you may want to remove that part
speed in pixels or balala units
since when does joker poker have distance units
always
what's the balala-unit to hammerunit conversion rate
that's what neko there is measuring in, yeah
UI uses it heavily
oh G.CURSOR is a thing that's cool
im assuming that's in balala units then
How would I get the position from like a second or two ago?
get the position now
wait a second
woah its a second aho
ago
but wouldn't the update function override it before the next second
store it
does update run 60 times per second?
every frame, yeah
lag may reduce this below the intended 60hz
uh how to make a joker multiply mult by 10?
how large is a balala unit in pixels?
return {xmult = 10}
oh thx
update = function(self, card, dt)
local positions_x = {}
local positions_y = {}
local speeds = {}
local piss = 0
local mouse_vel = {}
local timer = (timer or 0)
local oldtimer = timer
timer = (timer or 0) + dt
local mousepos = {}
mousepos.x, mousepos.y = math.floor(G.CURSOR.T.x), math.floor(G.CURSOR.T.y)
local oldpos = {}
table.insert(positions_x, {mousepos.x})
table.insert(positions_y, {mousepos.y})
if #positions_x >= 60 then
oldpos.x = positions_x[1]
table.remove(positions_x, 1)
end
if #positions_y >= 60 then
oldpos.y = positions_y[1]
table.remove(positions_y, 1)
end
local speed = 0
speed = sqrt(((mousepos.x-oldpos.x)/(#positions_x + 1))^2 + ((mousepos.y-oldpos.y)/(#positions_y + 1))^2)
end,
I'm probably doing this way wrong
can someone help plz?
you can't do an if check inside a return, you have to do it outside
also G.GAME.blind.chips is the number, if you need the text it's G.GAME.blind.chip_text iirc
oh
but its probably better to check for the number breakpoint for the e formatting
broadly, you can't do things in general inside a return
instead of return if... then value do if... then return value
so like this?
that should work
youre missing an end
so this?
config = { extra = { timer = 0, positions_x = {}, positions_y = {}, speeds = {}, speed = 0, mult = 0, mult_mod = 1 } },
update = function(self, card, dt)
local piss = 0
local mouse_vel = {}
card.ability.extra.timer = (card.ability.extra.timer or 0) + dt
local mousepos = {}
mousepos.x, mousepos.y = math.floor(G.CURSOR.T.x), math.floor(G.CURSOR.T.y)
local oldpos = {}
table.insert(card.ability.extra.positions_x, {mousepos.x})
table.insert(card.ability.extra.positions_y, {mousepos.y})
if #card.ability.extra.positions_x >= 60 then
oldpos.x = card.ability.extra.positions_x[1]
table.remove(card.ability.extra.positions_x, 1)
end
if #card.ability.extra.positions_y >= 60 then
oldpos.y = card.ability.extra.positions_y[1]
table.remove(card.ability.extra.positions_y, 1)
end
card.ability.extra.speed = sqrt(((mousepos.x-oldpos.x)/(#card.ability.extra.positions_x + 1))^2 + ((mousepos.y-oldpos.y)/(#card.ability.extra.positions_y + 1))^2)
end,
well, unless there's some syntax error like that :v
i don't see anything wrong with that on a quick skim
put in some debug prints and test to see if it's doing what you think it's doing
cheated in a lot of jokers to make testing the one i added easier, and i ended up getting another one of them avalible in the shop without showman, is this norma;?
Yes it is
tweaked it a bit to
config = { extra = { timer = 0, positions_x = {}, positions_y = {}, speeds = {}, speed = 0, mult = 0, mult_mod = 1 } },
update = function(self, card, dt)
local piss = 0
local mouse_vel = {}
card.ability.extra.timer = (card.ability.extra.timer or 0) + dt
local mousepos = {}
mousepos.x, mousepos.y = math.floor(G.CURSOR.T.x), math.floor(G.CURSOR.T.y)
local oldpos = {}
table.insert(card.ability.extra.positions_x, { mousepos.x })
table.insert(card.ability.extra.positions_y, { mousepos.y })
oldpos.x = card.ability.extra.positions_x[1]
if #card.ability.extra.positions_x >= 30 then
table.remove(card.ability.extra.positions_x, 1)
end
oldpos.y = card.ability.extra.positions_y[1]
if #card.ability.extra.positions_y >= 30 then
table.remove(card.ability.extra.positions_y, 1)
end
--[[ if #card.ability.extra.positions_x >= 61 then
oldpos.x = card.ability.extra.positions_x[1]
table.remove(card.ability.extra.positions_x, 1)
end
if #card.ability.extra.positions_y >= 61 then
oldpos.y = card.ability.extra.positions_y[1]
table.remove(card.ability.extra.positions_y, 1)
end]]
card.ability.extra.speed = sqrt(((mousepos.x - oldpos.x) / ((#card.ability.extra.positions_x or 60) - 1)) ^ 2 +
((mousepos.y - oldpos.y) / ((#card.ability.extra.positions_y or 60) - 1)) ^ 2)
table.insert(card.ability.extra.speeds, { card.ability.extra.speed })
if #card.ability.extra.speeds >= 61 then
table.remove(card.ability.extra.speeds, 1)
end
print("pos_X = " .. math.floor(G.CURSOR.T.x) .. ", pos_Y = " .. math.floor(G.CURSOR.T.y))
print("v_X = " ..
math.floor((mousepos.x - oldpos.x) / ((#card.ability.extra.positions_x or 60) - 1) * 100) / 100 ..
", v_Y = " .. math.floor((mousepos.y - oldpos.y) / ((#card.ability.extra.positions_y or 60) - 1) * 100) / 100)
print("speed = " .. math.floor(card.ability.extra.speed))
end,
and it gave this crash when viewing it in the collection
(goes to the card.ability.extra.speed = sqrt line)
added an or 0 to that line
still crashes damn it
mousepos.x, mousepos.y = math.floor(G.CURSOR.T.x), math.floor(G.CURSOR.T.y)
local oldpos = {}
table.insert(card.ability.extra.positions_x, { mousepos.x })
table.insert(card.ability.extra.positions_y, { mousepos.y })
--...
if #card.ability.extra.positions_x >= 30 then
table.remove(card.ability.extra.positions_x, 1)
end
oldpos.y = card.ability.extra.positions_y[1]
if #card.ability.extra.positions_y >= 30 then
table.remove(card.ability.extra.positions_y, 1)
end
why are you appending the current position to the end of this table and then checking the table's length?
So the table doesn't become infinite in length?
why do you need a table of the last n positions? you only need two points and a time to calculate velocity
So I can keep the points and, thus, speed, updated?
you seem to be tracking 30 points
do you need that many?
I'm trying to track the average speed over the last half a second and keep it up-to-date?
i see
card.ability.extra.speed = sqrt(((mousepos.x - oldpos.x) / ((#card.ability.extra.positions_x or 60) - 1)) ^ 2 + is this the line that crashes?
yes, even after coating all the positions in ([...] or 0)s because now I'm getting hit with the
well yeah, table or 0 results in table, because tables are truthy
or doesn't check contextual validity, just truthiness
put print(mousepos.x, oldpos.x) above that line
So I need to set another value to = #card.ability.extra.positions_x?
those are supposed to be numbers, but the crash indicates that one or both of them is a table, so let's find out which one
Okay well it's still crashing and I can't tell where the print result is
i imagine you have debugplus active, you can press / to bring up the log
it should be right before the crash
(logs are also stored in /mods/lovely/logs)
looks like it's oldpos.x that's a table
table.insert(card.ability.extra.positions_x, { mousepos.x })
table.insert(card.ability.extra.positions_y, { mousepos.y })
oldpos.x = card.ability.extra.positions_x[1]
oh, i see what's happening
you're putting a table containing the number into oldpos, when you want to be putting just the number
so I just lather that shit in tonumber()?
Oh right from before I seperated the tables
Okay that is a much smaller scale than I imagined
(with my mouse in the bottom-right corner)
that might not be accurate
iirc dt doesn't get passed to cards in the collection
or something like that, i forget the details, but i couldn't make neko do things in the collection, its timer never updated
yes, using ctrl c or 3 to add jokers doesnt count as obtaining them
@red flower since glossary development is happening in both sides looks like, what kind of tools you may want to have out of the box?
I already have some API to filter info_queue and add own things in it, but I can prepare smth more advanced if needed
I seen you're working on terminology, I can setup some sort of parser which will convert text to actual entries
idk i already have mine set up but it's very custom to my mod
I want it make more like api
Right now I have API to make custom sections in which you can insert any stuff you need
And then, you setup filters to define when to display, what and where
Basically all this terms page you have, already can be made pretty easily
it's like 1 section and 1 filter
seals suck tho
yeah i can probably use my stuff to set up compat in the future
I'm planning to add pokermon compat by myself
as proof of concept kinda
then polish more ui bla bla bla
right now that menu is set up by this + some stuff that gets automatically added
yea this one like ideal to work with
Also I'll include PPU credits
Would be nice to see card creator's cards from credits in this page
And that's kind of idea Doc mentioned
He wanted page where I can visually see credits for a card
I need implement pages tho
I'll let you know when I will have something decent to show
(happen probably after pokermon shenanigans)
man maybe I should stop creating small lib mods or smth which I will not support afterwards ⚗️
I have smth like 4-5 of them
also I'll do it for hotpot, especially because it has shit ton of stickers
and wacky jonklers which, for example, adds info_queue for all jokers you seen in a run
perfect mod to test stuff actually
- has credits
Does stocking stuffer uses PPU for credits?
im pretty sure
good, easier for me
you what also would be very cool? PPU have function which creates a card from member
Because if I want make a card with all funny things other teams did as shaders, sounds, click interactions, woule be nice to keep all of that
but I guess that's big ask
what would i have to do in order to get formatting reminiscent to joker desc formatting via DynaText
since apparently it doesnt seem to react to {f:}
im using an emoji font that i want to use for a credits ui
https://github.com/Steamodded/smods/wiki/Localization#localize
this recent wiki addition might be helpful if what your doing is outside of a localization file but uses content from within it
font = SMODS.Fonts.modprefix_key should work
alright
cus im going off of the assumption that dynatext works with the formatting system
so yea
yeah we need to add dynatext to the wiki its got some smods exclusive features ;-;
yea...
I have this, but for some reason, it's acting like this?
Is something wrong with my code for the max speed?
namely shader support and conditionals
alright...
it doesn't
replace talisman with amulet, but this isn't the core issue
the formatting system makes dynatext but dynatext doesn't support it out of the gate
could be up for debate
?
some function that natively supports the formatting system, but its a personal take
unless it already exists and im just uninformed
i dont undestand what youre saying, there are functions that do
the easiest way to get formatted ui is to SMODS.localize_box(loc_parse_string("my formatted {C:attention}string"))
there is an example in the SMODS.localize_box docs iirc
yea sorry about that, not the best at wording
also i was gonna ask does that work with object nodes
that function returns ui nodes, you can create a UIBox with them but it's easier to just plug the ui directly
Issue says that incorrect font was passed
Also if you think about it, joker names are all Dynatext and supports formatting
So maybe, there's some magic to make it work, or imitate it
local loc_text = SMODS.localize_box(loc_parse_string("{C:attention}My{} formatted line"), {
default_col = G.C.UI.TEXT_LIGHT,
vars = {}
})
local line = { n = G.UIT.R, nodes = loc_text }
alr
yeah copying localize
hey i made a custom deck skin and it was working but then randomly stopped working and i have no clue why
:(
how do i freeze the game for a specific period of time with a joker
delay(seconds)
that will still allow the player to press buttons and stuff tho but the game wont advance
Lua newbie here
So basically I'm trying to code 2 new suits for a mod I'm making, they mostly work as they load in correctly and get detected by jokers but, for some reason, instead of displaying their name id thingy correctly it gets replaced by "ERROR", I'm really stuck as everything else works and everything should be defined
Set up localization for your suit
I think there should be details on SMODS.Suit documentation
(Can't check rn, afk)
Like I said; There should be details for that on SMODS.Suit documentation on the Steamodded wiki
yeah you can add cards when you create the pool
im not sure if the other mod has to load first
what context should i use if i want to modify a scored card of a hand that just beat a blind? context.end_of_round is too late and context.after runs each hand played
key = 'hector',
loc_txt = {
name = "Jimbo Salamanca",
text = {
"Plays a {C:gold}bell sound{} every {C:attention}click{}",
"If player clicks 44 times, {C:red}explode{}",
"{C:inactive}({}{C:red}Explode:{} {C:inactive}destroy self and adjacent {}{C:attention}Jokers,{} {C:red}ignore{} {C:enhanced}Eternal{}{C:inactive}){}",
"{C:inactive}(Currently {}{C:attention}#2#{}{C:inactive} clicks left){}"
}
},
atlas = 'hector',
pos = { x = 0, y = 0 },
rarity = 2,
cost = 4,
blueprint_compat = false,
eternal_compat = true,
perishable_compat = true,
unlocked = true,
discovered = true,
config = { extra = { bellclicks = 0, bellclicksleft = 44, } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.bellclicks, card.ability.extra.bellclicksleft } }
end,
calculate = function(self, card, context)
if context.add_to_deck then
card.ability.extra.bellclicks = (card.ability.extra.bellclicks) = 0
card.ability.extra.bellclicksleft = (card.ability.extra.bellclicksleft) = 44
end
if context.remove_from_deck then
card.ability.extra.bellclicks = (card.ability.extra.bellclicks) = 0
card.ability.extra.bellclicksleft = (card.ability.extra.bellclicksleft) = 44
end
if context.sink_press then
if to_big((card.ability.extra.bellclicks or 0)) == to_big(43) then
card.ability.extra.bellclicksleft = (card.ability.extra.bellclicksleft) = 0
for i = 1, #G.jokers.cards do
if G.jokers.cards[i] == card then
if i > 1 then
local left = G.jokers.cards[i - 1]
left:start_dissolve({ HEX("57ecab") }, nil, 1.6)
end
if i < #G.jokers.cards then
local right = G.jokers.cards[i + 1]
right:start_dissolve({ HEX("57ecab") }, nil, 1.6)
end
self:start_dissolve({ HEX("57ecab") }, nil, 1.6)
end
end
else
card.ability.extra.bellclicks = (card.ability.extra.bellclicks) + 1
card.ability.extra.bellclicksleft = (card.ability.extra.bellclicksleft) - 1
G.E_MANAGER:add_event(Event({
func = function()
print('skbidi toielt')
play_sound('sink_bell')
return true
end
}))
return {
message = "Ding!"
}
end
end
end
}```
sorry for wall of code
nvm im an idiot
key = 'hector',
loc_txt = {
name = "Jimbo Salamanca",
text = {
"Plays a {C:gold}bell sound{} every {C:attention}click{}",
"If player clicks 44 times, {C:red}explode{}",
"{C:inactive}({}{C:red}Explode:{} {C:inactive}destroy self and adjacent {}{C:attention}Jokers,{} {C:red}ignore{} {C:enhanced}Eternal{}{C:inactive}){}",
"{C:inactive}(Currently {}{C:attention}#2#{}{C:inactive} clicks left){}"
}
},
atlas = 'hector',
pos = { x = 0, y = 0 },
rarity = 2,
cost = 4,
blueprint_compat = false,
eternal_compat = true,
perishable_compat = true,
unlocked = true,
discovered = true,
config = { extra = { bellclicks = 0, bellclicksleft = 44, } },
loc_vars = function(self, info_queue, card)
return { vars = { card.ability.extra.bellclicks, card.ability.extra.bellclicksleft } }
end,
calculate = function(self, card, context)
if context.add_to_deck then
card.ability.extra.bellclicks = (card.ability.extra.bellclicks) == 0
card.ability.extra.bellclicksleft = (card.ability.extra.bellclicksleft) == 44
end
if context.remove_from_deck then
card.ability.extra.bellclicks = (card.ability.extra.bellclicks) == 0
card.ability.extra.bellclicksleft = (card.ability.extra.bellclicksleft) == 44
end
if context.sink_press then
if to_big((card.ability.extra.bellclicks or 0)) == to_big(43) then
card.ability.extra.bellclicksleft = (card.ability.extra.bellclicksleft) == 0
for i = 1, #G.jokers.cards do
if G.jokers.cards[i] == card then
if i > 1 then
local left = G.jokers.cards[i - 1]
left:start_dissolve({ HEX("57ecab") }, nil, 1.6)
end
if i < #G.jokers.cards then
local right = G.jokers.cards[i + 1]
right:start_dissolve({ HEX("57ecab") }, nil, 1.6)
end
self:start_dissolve({ HEX("57ecab") }, nil, 1.6)
end
end
else
card.ability.extra.bellclicks = (card.ability.extra.bellclicks) + 1
card.ability.extra.bellclicksleft = (card.ability.extra.bellclicksleft) - 1
G.E_MANAGER:add_event(Event({
func = function()
print('skbidi toielt')
play_sound('sink_bell')
return true
end
}))
return {
message = "Ding!"
}
end
end
end
}```
nvm again i have a different issue now
update: end_of_round works, but you have to look in your deck to see the modification
so https://github.com/Steamodded/smods/wiki/Text-Styling#text-button-modifier-button how does this work if i cant hover my mouse over the description because it dissapears
it's for text that you can hover over like deck descriptions or mod descriptions
same with {T:}
ahhhh
bump
It's card:start_dissolve not self:start_dissolve
Darn, I guess something is broken with stencil
is there a way to make a joker animate once? like its usually one sprite, but when i say enter a blind, it goes through a couple sprites, then ends back on its normal sprite?
you can use card.children.center:set_sprite_pos({x = num, y = num}) to change the sprite
with that you can animate manually
but if the joker goes through multiple sprites, the game just changes it to the last sprite, so it doesnt look like anything happens
Events.
Ok so i'm making Misprint Consumables, and want them to appear both in their respective normal sets (like hidden = true, soul_set = "Set") and in their own respective misprint Vouchers
right now i can only have one or the other
Do i have to take ownership or patch the booster packs?
MB
im so mart
like i just go through the sprites in an event? or i make each sprite change an event?
make each change an event with delays yeah
Okay, something in hotpot breaks stencil
this... sucks
bruh
at the same time understandable, this kind of technology was not invented during hotpot
I was worried that something in smods fucked up stencil completely
if i do this, the base card sprite changes, but the soul sprite does not, why is that?
thats a lot of things
what the heck 💀
how do you do something when either a joker first appears or the run gets reloaded
i need to set which sprite a joker uses in the altas dynamically, but if you reload it currently just resets to the base one set as the pos when you reload
set_sprites function in the joker definition
it'll run every time the joker is generated or loaded into the game
thank you
but it runs pretty early in the process of (re)creating the joker, so if you need access to variables in card.ability.whatever, you'll need to put all the relevant code in an event, because at the time of running set_sprites, the ability table isn't even set up yet
also, i want to change the sprite at the exact same time as returning a message
how would i do that
im not too good with the timings of events
in a calculate return table, you can do this, and i think it'll give you the exact timing you want
return {
...
func = function()
-- run any code you want in this function, and it will
-- be timed to happen when the joker visually triggers
end
}
you shouldn't even need an event for it
alr
function setSprite()
local c = card.ability.extra
local pos = math.ceil(9*(c.payout/c.resetValue))
card.children.center:set_sprite_pos({x = pos, y = 0})
end
if reset then
SMODS.calculate_effect({message=localize("k_reset"),colour = G.C.FILTER,func = setSprite()}, card)
else
SMODS.calculate_effect({message=localize("k_upgrade_ex"),colour = G.C.FILTER, func = setSprite()}, card)
end
so i could do something like this
yep that should work great (as long as that function is defined within the calculate function)
bump
SMODS.PokerHand{
key = "flushsix",
chips = 120,
mult = 15,
level = 1,
l_chips = 30,
l_mult = 3,
loc_txt = {
name = "Flush Six",
description = {
"Six cards of the same rank and suit"
}
},
visible = true,
order = 100,
example = {
{ 'S_A', true },
{ 'S_A', true },
{ 'S_A', true },
{ 'S_A', true },
{ 'S_A', true },
{ 'S_A', true }
},
evaluate = function(self, parts, hand)
if parts._flush and #hand == 6 then
local first_rank = hand[0] and hand[0].rank
local same_rank = true
for i = 0, #hand - 1 do
if hand[i].rank ~= first_rank then
same_rank = false
break
end
end
if same_rank then
return hand
end
end
return {}
end,
}
my poker hand is not poker handing
lua is 1-indexed, not 0-indexed
whoops
local possible_cards = {}
for _, scoring_card in ipairs(context.scoring_hand) do
if scoring_card.edition == nil then
table.insert(possible_cards, scoring_card)
end
end
if possible_cards ~= nil then
local chosen_card = pseudorandom_element(possible_cards, 'bgn_cardczar')
local random_edition = SMODS.poll_edition { key = "modprefix_seed", guaranteed = true, no_negative = true }
if chosen_card ~= nil then
chosen_card:set_edition(random_edition)
end
end
end```
this is what i have right now. is there a better context to use? i want the player to see the card change edition
Try if context.after and SMODS.calculate_round_score() + G.GAME.chips > G.GAME.blind.chips?
that works, but it visually puts the edition on the card before the cards even score. lemme try wrapping this in an event and see if that helps
yep, that works
thanks for the help!
i don't understand how this could be returning a nil value when that line of code should only run if the value isn't nil
It's G.jokers not G.joker
```pseudorandom_element(SMODS.Ranks, pseudoseed('giga_idk'))````is it the right way to get a random rank
cause it return the whole table right now
it returns the rank object table, you should get the key from that
Why does this start out on 0 blind size
yeah I figured out
context.other_card:get_rank() and is there something like that
It's also supposed to debuff cards if a card is sold, used, or destroyed but it doesn't do it when one is sold
cause like im using get_id but the table return Jack and not 11
You would get .id instead of .key from the pseudorandom_element
oh yeah and I just convert for the loc_vars
if you need then i can include some extra properties on the center i extended
I found workaround so not really
Is there a way to have context.buying_self working for when the joker is generated
For now, it only applies when bought from the shop, not when picked in a booster pack, or created by a tarot or joker
No, you would use the add_to_deck function.
Oh right, thanks !
wondering, is there a way to specifically lower jokers price?
Hook Card:set_cost_value
card.lua in the lovely dump.
What SMODS version do you have?
smods-1.0.0-beta-1503a
Update SMODS
updated to smods-1.0.0-beta-1620a, still doesn't seem to find it
Code?
wdym code?
i dont have code for what im looking to do yet, im just trying to understand where'd the hook be
Did you open the game with the updated SMODS?
yes
how would i create a playing card with specific suit and random rank?
the code a friend of mine gave me doesnt seem to work as intended
SMODS.add_card({set = 'Base', suit = 'modprefix_key'})
why is it like this
trying to make a combination of even steven and misprint, whats wrong with this code causing it to crash?
calculate = function(self, card, context)
if context.joker_main then
local temp_Mult = pseudorandom('misprint', self.ability.extra.min, self.ability.extra.max)
context.other_card:get_id() <= 10 and context.other_card:get_id() >= 0 and context.other_card:get_id()%2 == 0 then
return {
mult = temp_Mult,
card = self
}
end
end
you're missing an if?
oh
also, do you know how to make the description have the weird random description that misprint has?
are you looking at the vanilla code for reference?
yeah
look here instead https://github.com/nh6574/VanillaRemade/blob/main/src/jokers.lua
it has misprint too
oh, thanks!
if context.individual and context.cardarea == G.play and context.other_card:get_id() <= 10 and context.other_card:get_id() >= 0 and context.other_card:get_id() % 2 == 0 then
return {mult = pseudorandom('seed', card.ability.extra.min, card.ability.extra.max)}
end
No, you're supposed to replace your entire calculate function with that.
question
how can i make a boss blind that disables a specific joker
wait let me check boss blinds rq
I'd look in the Yahimod for the blind that disables all Yahimod jokers to see how it does that.
ig i'm using crimson heart as my template
how do i make it disable a joker in a specific position tho
i dont really understand what causes that (edit after the edit: oh)
does SMODS.add_card now also take a filter argument just like SMODS.poll_object?
Yes, but attributes has to exist in the table as well.
thx! now i have 3 jokers for my mod.
uh
tried the misprinted steven joker out and the game crashed when i played a hand
You need to define config
so, in the function but or somewhere else?
Did you forget to define min and max as extra
oh
It should be inside the SMODS.Joker but not in the calculate
can attributes be empty?
So it would be like config = { extra = { min = 0, max = 22}}
oh
Yes.
If there are more lines past config, append a comma at the end of that line
Keep in mind that you will need to make a new copy of that joker because config variables aren't updated on existing cards
why does this crash?
how exactly is pool defined
You need to return a pool in the filter function.
Yeah
right
well the pool is created but the issue is not returning it
fixed the crash but the pool still seems to always only contain the default Joker, even after putting everything in an event
if attribute is empty it might get nothing im not sure
fuckkk
you can just do poll_object separately
i suppose that is true
new smods function usage found : )
i could probably do this directly with add_card but whos checking
SMODS.emplace when
that SMODS.add_to_deck
there's difference between emplacing and adding to deck
it does both
why does this say im not using a pool source
oh wait
nvm
okay well
the pool is still just the default joker
even without the empty attributes
W floating point error
why does this happen when this Joker is undiscovered
it has multiple sprites, and its the only one that has multiple sprites, and its the only one that has this half-Jimbo half-Undiscovered sprite
so i assume its caused by having multiple sprites in some way
if you manually set eternal to the cards yes
though they dont work
idk if perishable or rental work but nothing in vanilla checks for eternal on playing cards so that wont work
has spectrallib integrated the stickers on playing cards patches yet idk
perishable and rental both need a bit of work to stop it from triggering twice if it's on a playing card, but otherwise they're pretty much fine
i'm looking at the context.stay_flipped right now. is it possible to detect whether a played card is currently flipped or unflipped?
actually i think i may have found it
Are you using draw or set_sprite functions for this joker?
If so, you need to check if a card is discovered before running your custom draw code
art = { "sinkhole" },
code = { "sinkhole" },
idea = { "sinkhole, rocket, Jerry J. Jerry XXIII" }
},```
crashed when i hovered over my joker i tested it on
does anyone know how to get fs files?
what for?
joker editions and stuff
all of vanilla's files can be gotten by opening the .exe like a .zip
including the shaders
yeah but i mean for custom joker editions
yea
i'd recommend copying and modifying a simple shader like resources/shaders/negative.fs
you only need to modify the effect function
if context.card:has_attribute(food) then
card.ability.extra.Xmult = card.ability.extra.Xmult + card.ability.extra.Xmult_gain
end
end```
how does the :has_attribute thing work? i thought i did it right here but my joker isn't working
the argument needs to be a string, so "food" with the quote marks
it doesn't crash because lua assumes any uninitialized variable is just nil
ah gotcha
bumping this again bc idk how to fix the max speed not working right.
set_sprites
how would i check if a joker is discovered
card.config.center.discovered iirc
tried to get this joker to work in 2 different ways, but neither of them have proved successful. checking to see if a card is face down has proved harder than expected and i'm not sure if i'm over complicating things here :/
I can't see the code rn (on mobile) but can't you just check if card.facing == "back"
that's what i did, but i think that when i'm checking them, they already switch to being face up
thank you
why does this draw on front sprites of the card on the loading screen instead of like anything i want it to draw on
ah, I see. yea context.individual is at the time of scoring, so they're already flipped
you'll have to check all the cards in G.hand.highlighted during context.press_play, save the face down ones somehow, and then check against that saved info again during context.individual
the loading screen card shouldnt even have an area defined
G.hnds_circus_joker is probably nil upon booting the game
okay but
G.hand.highlighted was the context i was looking for! thanks!
happy to help, both of you
though it didnt work to begin with even when i was nil checking that
not sure what exactly the issue would be for getting it to work in the intended situation, would need to see more info about that cardarea I think
hrm
not too sure, sorry. I'm kinda handicapped at the moment by being on phone anyway
if context.press_play then
for _, card in ipairs(G.hand.highlighted) do
if card.edition == nil and card.facing == "back" then
table.insert(possible_cards, card)
end
end
end
if context.before and context.cardarea == G.play then
for _, card in ipairs(context.scoring_hand) do
for _, flipped_card in pairs(possible_cards) do
if flipped_card == card then
local random_edition = SMODS.poll_edition { key = "bgn_memory", guaranteed = true, no_negative = true }
G.E_MANAGER:add_event(Event({
func = function()
if chosen_card ~= nil then
chosen_card:set_edition(random_edition)
chosen_card:juice_up()
end
return true
end,
}))
end
end
end
end```
i've got this so far, but i'm still not getting any action unfortunately
Because the Speed is correct, but the Max Speed isn't somehow???
you're overwriting possible_cards with an empty table every time the joker calculates, including between context.press_play and context.before
And that's before the concern of it possibly not even scoring for some reason and how the
loc_vars = function(self, info_queue, card)
local chips = card.ability.extra.mult * card.ability.extra.max_speed
local fastness = math.floor(card.ability.extra.max_speed * 100) / 100
if not fastness or not chips then
return { vars = { "Recalibrating...", "Recalibrating..." } }
else
return { vars = { chips, fastness } }
end
end,
just doesn't fucking work at adding the Recalibrating text
not quite, just put it somewhere like card.ability.extra or even just a local table outside the joker itself so you don't overwrite it at the start of the calculate function
(and then clear it out before you add all the cards in context.press_play)
Is there a way to make just the first playing card get counted as a face card?
I tried
if context.before and #context.full_hand then
local first_card = context.full_hand[1]
first_card.is_face()
end
But this causes an "attempt to index local 'self' [a nil value]" when I play a card. (I couldn't find any information about is_face on the vanilla remade of smods wikis, so if there is any please link me)
this is not how you make a card count as a face card, check the implementation of pareidolia on vanillaremade
currently this is only running a face check on a card without passing an actual card object
you'd have to hook Card:is_face() to do your effect
Already checked Paredolia's code. And I think I have hooked Card:is_face() already.
then that's it
you should run your checks in the hook
...But I guess what that means is I should be adding the code into the hook?
yes that's the point of hooking
Thank you.
how do i make the badges with the text that cycles through different entires
does anyone know why the hologram shader isn't working?
Needs to be slightly transparent iirc
How would I check the type of the most recently opened booster pack as a G value?
bump?
https://github.com/borb43/Hypernova/blob/main/lib/hooks.lua i use this, you can change how strings is popular at your leisure pretty much, as long as you correctly change what value youre checking to exist
what matters most is the check for actually applying the badge
Im having isses with colection order, i have each joker in its own file in a folder. "Order" seems to be getting ignored and the fallback is alphabetical, any work around?
what are you using to load your jokers in order?
did i type it in right?
SMODS.NFS.getDirectoryItems
above is the tutorial video
are you doing anything to get a specific order with the file structure/loading system? by default this gets the file names listed in alphabetical order so that will also be the order the files are loaded in
Oh, i have order = x on each file. Thats all though. I assumed that load order and collection order would be independent.
the order value on jokers doesnt actually mean anything by default, im assuming youre looking at cryptid which gives that value functionality elsewhere
Im looking at source code for this, but i also notice that they are all listed in the collection order here too so i can see how it could be redundant
load order and collection order are tied to each other as the order value is overridden to be whatever the next order value in the collection would be at injection
bump2
a simple way to get the desired load order is to prefix files in the folder with a 3-digit number (or 4 digits if you think that would be necessary) corresponding to their load order
Is it tricky to tie in my own order with the loading function?
shouldnt be all that hard
failing to understand why this doesnt load
only sending the zip because i dont know the culprit file
How do I get specifically the type of item typically spawned by a booster pack, given the booster's key? (Given how some have different kind names compared to their consumables' types)
Never mind, using the 001, 002 system is actually a lot easier then i thought. I dont have to change anything except the file names. Thanks
bump3
i gave you a link already with my solution
is this the correct file format for a mod or am i missing something
desc is leftovers from vremade
version is not a valid version string
it should be in the format <major>.<minor>.<patch><revision>
major, minor and patch should be numbers
e.g. 0.5.0b
and a revision starting with a ~ indicates a beta
it keeps crashing, what do i do
How do I make an info_queue without using another item?
mb gng 😭
if i reference SMODS.last_hand in a calculate function, is it going to return info about the CURRENT HAND or the PREVIOUS HAND?
this confuses me, is there a way to put it simpler?
you shouldnt need to edit anything besides where the list of strings are created
but this is already pretty much the minimum for this i think
custom suit wants to render as hearts and idk why
As in, I want to have an info_queue box to the side, as if for a Joker or something, but without needing one to actually exist.
because my current alternative is making a not-in-pool Joker that still runs the risk of being found by another mod or something
you can do info_queue[#info_queue+1] = { key = X, set = Y, vars = { --[[text variables if needed]] } } to add a tooltip for the entry in decriptions[set][key]
also it wants to appear in normal deck
so i put this into my joker
{ key = "credits_code", vars = {"sinkhole"} },
{ key = "credits_art", vars = {"sinkhole" }},
{ key = "credits_idea", vars = {"sinkhole + rocket + Jerry J. Jerry" }},
},```
and i put this in my hooks.lua
```local smcmb = SMODS.create_mod_badges
function SMODS.create_mod_badges(obj, badges)
smcmb(obj, badges)
if not SMODS.config.no_mod_badges and obj and type(obj.inv_badge_info) == "table" then
local function calc_scale_fac(text)
local size = 0.9
local font = G.LANG.font
local max_text_width = 2 - 2 * 0.05 - 4 * 0.03 * size - 2 * 0.03
local calced_text_width = 0
-- Math reproduced from DynaText:update_text
for _, c in utf8.chars(text) do
local tx = font.FONT:getWidth(c) * (0.33 * size) * G.TILESCALE * font.FONTSCALE
+ 2.7 * 1 * G.TILESCALE * font.FONTSCALE
calced_text_width = calced_text_width + tx / (G.TILESIZE * G.TILESCALE)
end
local scale_fac = calced_text_width > max_text_width and max_text_width / calced_text_width or 1
return scale_fac
end
if next(obj.inv_badge_info) then
local scale_fac = {}
local min_scale_fac = 1
local strings = { INV.display_name }
for _, v in ipairs(obj.inv_badge_info) do
if v.key and v.vars then
local str = localize({ type = "variable", key = v.key, vars = v.vars })
strings[#strings + 1] = (type(str) == "table" and str[1]) or str
end
end
for i = 1, #strings do
scale_fac[i] = calc_scale_fac(strings[i])
min_scale_fac = math.min(min_scale_fac, scale_fac[i])
end
local ct = {}
for i = 1, #strings do
ct[i] = {
string = strings[i],
}
end
local inv_badge = {
n = G.UIT.R,
config = { align = "cm" },
nodes = {
{
n = G.UIT.R,
config = {
align = "cm",
colour = INV.badge_colour,
r = 0.1,
minw = 2 / min_scale_fac,
minh = 0.36,
emboss = 0.05,
padding = 0.03 * 0.9,
},
nodes = {
{ n = G.UIT.B, config = { h = 0.1, w = 0.03 } },
{
n = G.UIT.O,
config = {
object = DynaText({
string = ct or "ERROR",
colours = { G.C.WHITE },
silent = true,
float = true,
shadow = true,
offset_y = -0.03,
spacing = 1,
scale = 0.33 * 0.9,
}),
},
},
{ n = G.UIT.B, config = { h = 0.1, w = 0.03 } },
},
},
},
}
for i = 1, #badges do
if badges[i].nodes[1].config.colour == INV.badge_colour then
badges[i].nodes[1].nodes[2].config.object:remove()
badges[i] = inv_badge
break
end
end
end
end
end```
but im not seeing any changes and its not crashing
HOLY wall of code
is INV a reference to your mod object's table? (as in, you did INV = SMODS.current_mod somewhere)
i think so
i might have deleted it lemme check
i did delte it
when did
whatever
that probably means it is defined but not as your mod object then if it isnt crashing
so what and where would i put
hold on
i was using INV because i thought it was meant to detect MOD_ID over PREFIX
ah
if i even have a table i didnt know
well you can just put INV = SMODS.current_mod at the top of your main file then
i did that much
or anything else instead of INV, whatever you want the table to be called
Does the set have to exist elsewhere or can I make up some bs on the spot
and im still not seeing anything
bwump
it does have to be a defined set, not everything in localization is loaded by default
i recommend using Other
And does the item key append the mod key?
probably put some prints around to see what checks are failing
mmk
it gave me every print i put in
when i hovered over the joker
i see
am i missing something in my loc_vars?
loc_vars shouldnt matter here
ight nvm
did you put a print right after the if badges[i].nodes[1].config.colour == INV.badge_colour then check
since thats pretty much what matters
How do I get a joker to re-trigger a scored card with a specific enhancement
if context.repetition and context.cardarea == G.play and SMODS.has_enhancement(context.other_card, 'm_modprefix_key') then
return {repetitions = 1}
end
did u figure it out
no
darn
Thank you
Also I added it to where the joker gives 30 chips before the re-trigger
bump2
I am trying to make a joker that makes stone cards score additional plus mult equal to their chip value, and this is what i have so far. unfortunately, all stone cards score the chip value of the first stone card as mult. how can i make it so the stone cards score their chip value as mult, rather than the first played stone? (i have a tarot that scales stone cards chips, so +50 mult when scored stone doesnt work)
dont do a for loop
just return{ mult = context.other_card:get_chip_bonus() }
localization error, the key you put in probably isnt defined in your localization file
but why did it only work when i put the badges in manually 😭
idfk
idk either 😭
how would i get a bonus and mult in an enhancement to add to the "+X extra chips" or "+X mult" text on a card
like how bonus card does
the bonus value gets added by default, mult cards display their mult via the description
the bonus value doesn't show on my card
oh
the +15 Chips is from the desc
what is the description for your enhancement?
descriptions = {
Other = {
inv_oozing = {
name = "Oozing Card",
text = {
"{C:edition}+1{} Hand Size"
},
},
credits_idea = "Idea: #1#",
credits_art = "Art: #1#",
credits_code = "Code: #1#",
credits_shader = "Shader: #1#",
credits_music = "Music: #1#", --this is only really useful for packs but whatever
credits_origin = "Origin: #1#",
},
},
}```
am i an idiot???
i assume that removing the +15 Chips text wouldn't just add +15 extra Chips to the desc
yes, you should have those entries under misc.dictionary
okay i guess i was wrong and its just hardcoded for bonus cards like that? since vanillaremade bonus cards do have a description
huh
how can i make a card NOT move up and down when i click on it
yes
SMODS.Enhancement{
key = "Disease",
atlas = "Disease",
pos = {x = 0, y = 0},
config = { bonus = 15,
mult = 2,
extra = {}
},
loc_vars = function(self,info_queue,card)
return {vars = {card.ability.bonus,
card.ability.mult
}}
end,
calculate = function(self,card,context)
end
}
this is the full thing
Do you want it to just not do that or do you not want it to be selected?
how you do define colors (such as G.C.[...])
HEX('HEX')
ideally just doesnt move up and down, it has an on click effect so thats kind of bad
key = 'Vortexes',
card_key = 'V',
lc_atlas = 'CelestSuits',
lc_colour = HEX('788383'),
hc_atlas = 'CelestSuitsHC',
hc_colour = HEX('C3ACCE'),
pos = { y = 0 },
ui_pos = { x = 0, y = 0 },
keep_base_colours = true,
}```
would this be correct
Yes.
i have a strange issue and i dont rly know how to fix it
so i have a stake which increases the ante requirements to ante 10
You mean in the screen that shows up before the main menu?
however, it looks like it resets the scaling effects from purple/gold stake
so like, ante 2 has you complete a 800 chip small blind rather than 1000 chip small blind for instance
here is my stakes.lua file
the one in the animation where he sucks up all the jokers AND the one on top of the logo image in the main menu
for the second one (the "mod.menu_cards" section): https://github.com/Steamodded/smods/wiki/The-Mod-Object#modmenu_cards---table
thank you
is there a way i can remove the other card that pops up?
nvm
[[patches]]
[patches.pattern]
target = "game.lua"
pattern = "SC = Card(G.ROOM.T.w/2 - SC_scale*G.CARD_W/2, 10. + G.ROOM.T.h/2 - SC_scale*G.CARD_H/2, SC_scale*G.CARD_W, SC_scale*G.CARD_H, G.P_CARDS.empty, G.P_CENTERS['j_joker'])"
position = "at"
payload = "SC = Card(G.ROOM.T.w/2 - SC_scale*G.CARD_W/2, 10. + G.ROOM.T.h/2 - SC_scale*G.CARD_H/2, SC_scale*G.CARD_W, SC_scale*G.CARD_H, G.P_CARDS.empty, G.P_CENTERS['j_modprefix_key'])"
match_indent = true
no, menu_cards can handle it by returning remove_original = true
is this for the cutscene one
yeah i already fixed it
Yes.
thank you twin
Oops! The game crashed:
[SMODS _ "src/utils.lua"]:242: Attempted to insert object "j_houserules_hoteljoker" into an empty pool.
what do i do?
it's a lovely patch, read the "Patches" section here
https://github.com/ethangreen-dev/lovely-injector
show code, likely a bad rarity key
