-
Notifications
You must be signed in to change notification settings - Fork 182
0827
This is a large update to the smods framework that adds or modifies a lot of functionality, as well as fixing numerous bugs. This post is designed to detail the changes and document new features - these will be moved across to the wiki in the future. A lot of people have helped contribute to this release, either through writing features, discussing design choices, or by testing them out. I would like to thank them all for their efforts.
Massive credit is due to Aikoyori for the redesigned mod list page. Mods can be clicked on to access their menu, with a shortcut button to their config. The "List of Activated Mods" remains as a button that opens your Mods folder. A reminder that they are sorted by priority (lowest to high) within these categories:
- enabled mods with config
- enabled mods
- disabled mods
I think it looks brilliant, and there are some future plans for further iteration using this design.
Custom Consumable Types can now take an optional text_colour parameter, similar to primary_colour and secondary_colour. This parameter controls the colour of the text in the collection and in badges. If you wish to use this colour elsewhere, it is added as G.C.UI[key].
Building on the foundations from the last release, there have been a few improvements to the probability functions. SMODS.get_probability_vars and SMODS.pseudorandom_probability, now take an optional sixth argument - a boolean, that will make your probability unable to be modified by other effects when true. This allows other effects to still respond to successful and unsuccessful checks, without changing your chance.
The calculation contexts for probabilities have been extended to work for card modifiers too, allowing for enhancements, seals, and editions, to modify probabilities. In combination with a new feature, SMODS.context_stack, you can fine tune the exact effect you want, for example, a seal that guarantees Bloodstone, and only Bloodstone, will be successful.
Challenges have had support added for an apply function to be defined. This will allow you much more control over what changes you make within your challenge.
-- Example usage
apply = function(self)
G.GAME.stake = 8 -- sets the stake to Gold Stake
endThere is also support for challenges to have a dynamic restriction list by using functions. restrictions.banned_cards, restrictions.banned_tags and restrictions.banned_other can now be functions that return a table with the same structure as you would define originally. This lets you perform logic on your banned cards depending on values that are only accessible after mods are loaded.
Decks and Blinds are now able to have values saved within them that persist through a reload. Use G.GAME.blind.effect and G.GAME.selected_back.effect.config to access them.
In addition to this, custom Stickers will now automatically populate their config table when applied. It can be accessed through card.ability[sticker_key][value_key]. I would generally recommend that custom stickers do not redefine the apply function, and that stickers are applied to cards by using Card:add_sticker(sticker_key, bypass_check), in preparation for a future update to Sticker functionality.
Permanent bonuses have had a few new additions in this update.
Firstly, perma_repetitions can be modified to add retriggers to playing cards.
Secondly, two new properties that affect space in card areas have had functionality added. card_limit can be used to increase (or decrease) the card limit of the area that the card is in. extra_slots_used can be used to increase (or decrease) the number of slots that the card takes up. These two properties can also be defined within the config table of any object, and will be automatically handled. There is a more thorough guide to how this interacts with Editions later.
Two new modifiers have been added that allow for finer control over booster packs. By changing G.GAME.modifiers.booster_choice_mod you can modify the number of cards you are allowed to choose from a pack - this number cannot be reduced below 1. Changing G.GAME.modifiers.booster_size_mod will alter the number of cards that are available in a pack. Changing either of these values will also automatically adjust the tooltips of any booster packs.
A new property for text styling has been added - underline. To use this add {u:color} to your text.
A new property has also been added to DynaText. Use marquee = true to allow your text to scroll (can be seen in the new mod menu). This can be customised with hold and scroll_speed to define how long to pause and how fast to scroll.
SMODS.four_fingers(hand_type) can now differentiate between Flushes and Straights, allowing for this type of effect to apply to only one of the hands if required.
SMODS.create_card/SMODS.add_card now has a field allow_duplicates, which will allow duplicate cards to be created.
Added Card:is_rarity(rarity) to check if a Joker is a certain rarity. Accepts a number for vanilla rarities, or a key as a string for modded rarities.
SMODS.destroy_cards now has a fourth argument no_anim that bypasses any animations (used in food jokers in vanilla)
Hidden achievements can now have custom names and descriptions, accessed in the normal tables with '_hidden' added to the key.
There are a lot of updates to calculation within this release.
Firstly, calculations can no longer run outside of an active game, preventing some crashes.
Next, calculation support has been added to the following objects:
- challenges (add in your challenge definition as
calculate = function(self, context)) - stakes (add in your stake definition as
calculate = function(self, context)) - mod objects (add as
SMODS.current_mod.calculate = function(self, context)
A new, global, tracker has been added, SMODS.last_hand_oneshot, that is true when the last played hand scored more than the blind requirement.
The context.main_eval flag that is used for Jokers within context.end_of_round has also been added for Deck and Blind calculations too.
When returning saved = ... when a game is lost, you can now return your message directly rather than a localization key.
SMODS.create_card/SMODS.add_card can now have a force_stickers table that will force the stickers to be applied, bypassing all checks.
A number of new calculation contexts have been added.
This context is used for effects that happen when a tag is added to your tag area.
if context.tag_added thencontext.cardarea
context.tag_added -- the Tag that has been addedThis context is used for effects that happen after a tag is triggered.
if context.tag_triggered thencontext.cardarea
context.tag_triggered -- the Tag that has been triggeredThis context is used to prevent tags from triggering. You can return prevent_trigger = true to stop the tag from triggering.
This context could also be used to modify a tag before it is triggered.
if context.prevent_tag_trigger thencontext.cardarea
context.prevent_tag_triggger -- the Tag that is about to trigger
context.other_context -- the context that has activated the TagThis context is used for effects that happen whenever a card changes either suit or rank. These are technically the same context that adapts depending on which properties change.
if context.change_suit then
--
if context.change_rank thencontext.cardarea,
context.other_card -- the card that has changed
context.change_rank -- boolean value to flag that the rank has changed
context.new_rank -- the id of the rank the card has changed to, only present with change_rank
context.old_rank -- the id of the rank the card has changed from, only present with change_rank
context.rank_increase -- boolean value to flag whether the rank increased, only present with change_rank
context.change_suit -- boolean value to flag that the suit has changed
context.new_suit -- the key of the suit the card has changed to, only present with change_suit
context.old_suit -- the key of the suit the card has changed from, only present with change_suitThis context is used for effects that happen whenever your current money changes. This context also tries to work out where the money comes from, though it is not guaranteed to identify every source.
if context.money_altered thencontext.cardarea,
context.money_altered -- boolean value to flag this context, always TRUE
context.amount -- the change in money
context.from_shop -- boolean value that is true if money is spent in the shop
context.from_consumeable -- boolean value that is true if money changes when using a consumable
context.from_scoring -- boolean value that is true if money changes during scoring evaluationThis context is used to control the amount the ante changes by, before it changes. You can return modify = X to change the amount by X.
if context.modify_ante thencontext.cardarea,
context.modify_ante -- the amount the ante is changing by
context.ante_end -- boolean value that is true when the change is from reaching the end of the anteThis context is used for effects after the ante changes.
if context.ante_change thencontext.cardarea,
context.ante_change -- the amount the ante has changed by
context.ante_end -- boolean value that is true when the change is from reaching the end of the anteThis context is used for effects after a card has had it's ability set. This includes initial spawning of cards, and when they change enhancement.
if context.setting_ability thencontext.cardarea,
context.setting_ability -- boolean value to flag this context, always TRUE
context.other_card -- reference to the card that has changed
context.old -- key of what the card was
context.new -- key of what the card is now
context.unchanged -- boolean value that is true when context.old is equal to context.newJimboQuips are a new feature that allow you to create new pop ups at the end of a run. By default, there are 7 win quips and 10 loss quips, that are selected randomly at the end of a run. Using SMODS.JimboQuip you can define new quips to show up under certain conditions.
The easiest form of a quip simply results in a new message for Jimbo to say. You can set this up using this example.
-- in any of your lua files
SMODS.JimboQuip({
key = 'example_quip',
type = 'win'
})
-- in your localization file
return {
misc = {
quips = {
modprefix_example_quip = {
'This is an',
'example quip',
'when you win'
}
}
}
}This quip will be able to spawn on any run that has been won. Using type = 'loss' would spawn on any lost run.
There may be times where you want to control when your quip can spawn, and the rate at which is can spawn. To do this, you can add a filter function to your quip, as shown below, that returns true when the quip should be added to the spawn pool.
filter = function(self, type)
if next(SMODS.find_card('j_hanging_chad')) then
return true, {weight = 10}
end
endFrom this function, you can also optionally return a table of extra information. weight allows you to control the frequency of your quip being the displayed quip (default value is 1), and override_base_checks can be used to stop other quip filters from removing your quip (more on this later). Advanced usage of this could allow you to have only one quip definition for both win and loss states, and control the output within this function. There is an example showing this later.
Back and Mod objects can also have a quip_filter function defined on them to override the initial filter function from the quip. The override_base_checks value in the args table ignores the results of these quip_filter functions.
quip_filter = function(quip, type)
if quip.mod.id == 'modid' then
return false -- removes the quips from a specific mod from the pool
end
endYou can also control the visuals and sounds of your quip. Adding an extra table allows for changes to specific things, shown below. (extra can also be defined as a function that returns a similar table if you wish)
extra = {
center = 'j_hanging_chad', -- key of card to show
particle_colours = { -- table of up to 3 colours for particles
G.C.GREEN,
G.C.PURPLE,
G.C.GOLD
},
materialize_colours = { -- table of up to 3 colours for materialize effect
G.C.GREEN,
G.C.PURPLE,
G.C.GOLD
},
text_key = 'modprefix_example_quip_newkey', -- key override for the quip
times = 5, -- number of times to play sounds
pitch = 1, -- pitch of sounds
sound = 'voice1', -- string of sound to play, this can also be a table of strings to play simultaneously,
juice = {0.3, 0.7}, -- table of args to pass into card:juice_up
delay = 0.13, -- amount to delay the next loop of sounds
}For more control over sounds, such as playing a sequence of sounds, you can instead define a play_sounds function as below. This will override any sounds defined in the extra table.
play_sounds = function(self, times)
-- call play_sound yourself here
endHere is an example of one quip object appearing in different situations with different messages.
SMODS.JimboQuip({
key = 'black_cat_1',
extra = {
center = 'j_ortalab_black_cat',
particle_colours = {
G.ARGS.LOC_COLOURS.Ortalab,
darken(G.ARGS.LOC_COLOURS.Ortalab, 0.5),
lighten(G.ARGS.LOC_COLOURS.Ortalab, 0.5)
}
},
filter = function(self, type)
if next(SMODS.find_card('j_ortalab_black_cat')) then
if type == 'win' then
self.extra.text_key = self.key..'_win'
return true, { weight = 10 }
elseif type == 'loss' then
self.extra.text_key = self.key..'_loss'
return true, { weight = 10 }
end
end
end
})Scaling values within cards has always been a simple line of code, but the wish of being able to either detect, or manipulate, these events from other cards has been a requested feature for a while. It is now possible, in an entirely opt-in capacity, by using SMODS.scale_card. This function will scale your value and display an automatic message, as well as allow other objects to detect your scaling events, and also manipulate them. The function is entirely customisable so you can tune it to your exact requirements.
This example code will scale the chips value of the card by the change value. It will display a "Upgrade!" message with a G.C.FILTER background. The amount the value changes by could be adjusted by other effects.
SMODS.scale_card(card, {
ref_table = card.ability.extra, -- the table that has the value you are changing in
ref_value = "chips", -- the key to the value in the ref_table
scalar_value = "change", -- the key to the value to scale by, in the ref_table by default
})The config of this joker would be defined as config = {extra = {chips = 5, change = 2}} for example. It is possible to take your scalar_value from a different table, by adding scalar_table = card.ability.other_table for example.
As this function allows for scaling detection effects to work, I would recommend it's use over doing it manually, but I understand the scaling manipulation can be an undesirable effect for some people. Therefore, you can block this from happening by adding block_overrides to your function call.
block_overrides = {
value = true, -- blocks modifications to the ref_value
scalar = true, -- blocks modifications to the scalar_value
message = true -- blocks modifications to the scaling_message
}This would block all modifications from other cards. You can also use a subset of these if you wish.
The basic structure example above is for an additive effect with a "Upgrade!" message, but you might want to display something else.
It is easy to change the message to use any message in G.localization.misc.v_dictionary_parsed. Add message_key = 'a_chips' to change the message to one of these. You can also add message_colour = G.C.RED to change the colour displayed. These messages automatically pass the scalar_value as the variable, apart from when using a_xmult which passes the new total amount, to match vanilla cases. If you don't want any message at all, add no_message = true.
You can also provide your own custom message, much like returning a message from a calculate function.
scaling_message = {
message = "Example message!",
colour = G.C.BLUE
}By default, this function will automatically handle scaling that uses addition, subtraction, and multiplication. You can switch between these by adding an operation to the function call. Valid options are operation = '-' and operation = 'X' to switch to subtraction or multiplication respectively. If you need an entirely custom scaling function, you can set operation to be a function instead. Here is an example of Canio, where face_cards is a number defined before the SMODS.scale_card function.
operation = function(ref_table, ref_value, initial, change)
ref_table[ref_value] = initial + face_cards*change
end,On the other side of this feature, is the ability to detect and manipulate value scaling. This is done by adding a calc_scaling function to your Joker-type card definitions. Within this function you can do any effects you need to do, and return a table of different effects. There is the ability to control timings somewhat with this return which will be explained below.
calc_scaling = function(self, card, other_card, initial_value, scalar_value, args)
if scalar_value > 0 then
return {
message = 'Pre Scale',
post = {
message = 'Post Scale'
}
}
end
endThis example will play a message before the scaling event, and after the scaling event. These tables accept any standard calculation return key. The initial_value and scalar_value values are dynamic, and respect any prior manipulation from other Joker-type cards. The args value is the initial table that was passed to SMODS.scale_card.
Manipulating scaling uses the same function as detection, but requires specific tables to be returned in the table.
return {
override_value = { -- this will override the initial_value
value = X, -- set the initial_value to X
-- other calculation return keys accepted here, timing is before the scaling event
},
override_scalar_value = { -- this will override the scalar_value
value = X, -- set the scalar_value to X
-- other calculation return keys accepted here, timing is before the scaling event
},
override_message = { -- this will override the scaling_message
message = 'override message'
-- other calculation return keys here will be evaluated WITH the message timing
}
}A Scoring Parameter is a value that can be used to calculate a hand's score. The base game provides chips and mult. By using SMODS.Scoring_Parameter you can create your own to use in new Scoring Calculations (see below). I have tried to make the process of creating a Scoring Parameter as user friendly as possible, with the opportunity to tweak it to your exact usage if you are more experienced with how Balatro calculation works.
There is a full example of a Scoring Parameter, and a Scoring Calculation that uses it, at the end of this update.
To create a basic parameter, that will be used in the same way as chips and mult, you can use this example.
SMODS.Scoring_Parameter({
key = 'example_parameter',
default_value = 0,
colour = G.C.GREEN
})This will create a new parameter that can be referenced in Scoring Calculations, that resets to 0 at the end of each played hand. The colour field will automatically colour any UI elements using the helper functions, including the scoring flames.
Chips and mult are able to be modified by returning values from the calculate functions of various objects in the game. By default, new Scoring Parameters are set up to handle modifying themselves in this way. To create your return keys (equivalent to chips, chip_mod, etc.) add calculation_keys = {'example_1', 'example_2'}. I would recommend only using one key, unless you want to define different behaviours in a custom calc_effect function.
If you do want custom behaviours, define calc_effect = function(self, effect, scored_card, key, amount, from_edition) and write your logic. For examples of what this code might look like, take a look at the chips and mult Scoring Parameters in src/game_object.lua, or SMODS.calculate_individual_effect in src/utils.lua.
Be default, each Scoring Parameter comes with a modify(self, amount) function that adds the amount to the current value. By redefining this function, you could add different logic. Do note that this function also updates the UI elements, so if you redefine it you should ensure that you keep this functionality. One such example might be having a Parameter that doesn't reset each hand, as shown here.
modify = function(self, amount)
self.current = self.current + amount -- update the current value, used for final score calculation
self.default_value = self.current -- update the default value
update_hand_text({delay = 0}, {[self.key] = self.current}) -- update the UIScoring Parameters are able to be added to the functionality of hand types and Planet Cards, by defining a hands table. This table will insert values into G.GAME.hands. This means that you can set different default values per hand type, and that when a hand is levelled up, your base values will scale. Here is an example of what this might look like.
-- This parameter is only applied to hands that contain a flush. They all scale the same way
hands = {
["Flush Five"] = {modprefix_example_parameter = 1, l_modprefix_example_parameter = 5, s_modprefix_example_parameter = 1},
["Flush House"] = {modprefix_example_parameter = 1, l_modprefix_example_parameter = 5, s_modprefix_example_parameter = 1},
["Straight Flush"] = {modprefix_example_parameter = 1, l_modprefix_example_parameter = 5, s_modprefix_example_parameter = 1},
["Flush"] = {modprefix_example_parameter = 1, l_modprefix_example_parameter = 5, s_modprefix_example_parameter = 1},
}In this table, you must use the keys shown here. modprefix_example_parameter is the starting value that is updated when levelled up. s_modprefix_example_parameter is the starting value that is used for level up calculations. l_modprefix_example_parameter is the amount gained when levelled up. The basic formula to calculate the amount is value = s_value + (level-1) * l_value.
If you wish, you can redefine the level up effect for your parameter by adding a function level_up_hand to your Scoring Parameter. Here is an example of that.
level_up_hand = function(self, amount, handType)
local k = self.key
hand[k] = hand['s_'..k] * (hand['l_'..k] ^ (hand.level - 1)) -- this multiplies the amount of the parameter by the l_value each level
endCurrently, to access the values of chips and mult mid scoring, we reference hand_chips and mult. These values will still be accurate with this system, but if you are modifying them you should either use mod_chips(hand_chips + X) and mod_mult(mult + X) or SMODS.Scoring_Parameters.chips:modify(X) or SMODS.Scoring_Parameters.mult:modify(X).
Your custom parameters can by accessed by using SMODS.get_scoring_parameter('modprefix_example_key') and changed directly by using SMODS.Scoring_Parameters['modprefix_example_key']:modify(X).
The base game scoring uses the formula chips * mult to calculate the score of your hand. You can use a custom SMODS.Scoring_Calculation to change this formula into something else. Three basic Scoring Calculations are defined already, multiply, add and exponent.
To create a basic Scoring Calculation, that subtracts mult from chips, you can use this example.
SMODS.Scoring_Calculation({
key = 'minus',
func = function(self, chips, mult, flames)
return chips - mult
end,
text = '-', -- controls the UI symbol displayed between the chips and mult box
colour = G.C.BLUE -- sets the UI symbol to be blue
})The func function here is what calculates your score. It is provided with the correct chips and mult values, but if you want to use a custom Scoring Parameter, see Accessing and Changing Parameters Directly.
Note that the flames value is a boolean that is used to control the flames in the scoring UI. It must be passed into any calls to SMODS.get_scoring_parameter as the second argument.
You can optionally add a config table to your Scoring Calculation that will persist throughout an entire game. You can access it by using self.config in the Scoring Calculation's functions, or G.GAME.current_scoring_calculation.config anywhere else.
To avoid unnecessary calculations, each Scoring Calculation will only allow calculate functions to return values for Parameters that are being used. By adding a parameters table to your Scoring Calculation, you can set which Parameters you are using. This defaults to using the chips and mult parameters.
parameters = {'chips', 'mult', 'modprefix_example_parameter'}It is possible to modify the UI further than just the symbol between the two displays. By using replace_ui and update_ui functions, you can create a completely custom display.
replace_ui = function(self)
-- build your UI here
return UINODES
end,
update_ui = function(self, container, chip_display, mult_display, operator)
-- the values passed to this function try to identify the main components of the display,
-- container will always be the outer shell, and can be used solely to control its child elements
-- chip_display and mult_display are the boxes for chips and mult
-- operator is the text between the chips and mult displays
-- modify stuff here
operator.UIBox:recalculate() -- this line actually updates the UI
endTo assist you in this process, there are a number of helper functions that will build components of the scoring UI for you. They can be found in src/ui.lua and have names such as SMODS.GUI.hand_score_display_ui(), SMODS.GUI.hand_chips_container() and SMODS.GUI.score_container(). I do not have time to document these functions, but you can read them and look at examples of their use in an effort to understand them. I am always free for messages if you need further clarification.
To switch to a different Scoring Calculation during a game, use the function SMODS.set_scoring_calculation('modprefix_minus'), for example.
You might currently use hand_chips * mult in your code to see how many chips the hand has scored. This will continue to work for the default Scoring Calculation, but once it has been changed will give a false result. To get around this, use SMODS.calculate_round_score(), which will give you an equivalent value at that time.
In addition, you may no longer need to do this at all if you are looking for hands that 'one-shot' the blind, as you can use SMODS.last_hand_oneshot to check for this.
It is now easier to manipulate which objects appear in a pool by hooking the new function SMODS.add_to_pool(object, args). This function handles the in_pool call to each object when creating a pool, and if it returns true the object is added to the pool. The args table is optional, and I would recommend searching in your IDE for the function to see the different args tables.
(Calls to get_current_pool will add an args table of {source = _append} where _append is the 4th argument of get_current_pool)
A context stack has been added such that calculations can look at previous contexts to determine more advanced effects (this is particularly useful when using the probability contexts). You can use SMODS.get_previous_context() to get the context table of the previous context. Here is a basic example for a seal that guarantees Bloodstone triggers on the card it is applied to.
if context.fix_probability and context.identifier == 'bloodstone' then
local previous_context = SMODS.get_previous_context()
if previous_context and previous_context.other_card == card then
return {
numerator = context.denominator,
message = 'Fix!'
}
end
endThese parameters have been added to all centers, meaning that cards can naturally modify the card limit of an area, or take up more than the normal 1 slot. To make use of this feature, add card_limit = X or extra_slots_used = X to the config table of your object. The values of the CardArea that your object is in will automatically be updated to take these into account.
If you are creating a new CardArea, this feature will automatically apply to any CardArea with a type that is either 'joker' or 'hand'. If you want to disable this on your CardArea, add fixed_limit = true to the CardArea config. SMODS.should_handle_limit(area) can be hooked to allow different types of areas to access the automatic changes.
Due to the Negative edition having a dynamic tooltip based on area, other editions can have their tooltip update automatically too. Add localization entries for these keys to use this. (if an entry is missing, it will default to the standard edition entry)
'e_modprefix_editionkey' -- When in the joker area or on a joker in the shop
'e_modprefix_editionkey_consumable' -- When in the consumable area or on a consumable in the shop
'e_modprefix_editionkey_playing_card' -- When in the hand or on a playing card in the shop
'e_modprefix_editionkey_generic' -- In any area without a key or other objects in the shopIf you have added a new CardArea and want it to use these tooltips, add 'negative_info = 'string', (default options are 'joker', 'consumable', 'playing_card', 'generic'). You could hook SMODS.Edition:get_card_limit_key(), and add the respective localization entries, if you want to add a new category of tooltip. (Keys returned from this function must end with "_SMODS_INTERNAL" for the system to work with them)
This code adds a new parameter, juice, and a calculation method that uses it in the formula chips * mult * juice. You can copy it into your files and experiment to see how it works.
SMODS.Scoring_Parameter({
key = 'juice',
default_value = 0,
colour = mix_colours(G.C.PURPLE, G.C.YELLOW, 0.5),
calculation_keys = {'juice', 'xjuice'},
hands = {
['Pair'] = {[SMODS.current_mod.prefix..'_juice'] = 10, ['l_'..SMODS.current_mod.prefix..'_juice'] = 5, ['s_'..SMODS.current_mod.prefix..'_juice'] = 10},
['Four of a Kind'] = {[SMODS.current_mod.prefix..'_juice'] = 10, ['l_'..SMODS.current_mod.prefix..'_juice'] = 5, ['s_'..SMODS.current_mod.prefix..'_juice'] = 10},
["Flush Five"] = {[SMODS.current_mod.prefix..'_juice'] = 1, ['l_'..SMODS.current_mod.prefix..'_juice'] = 5, ['s_'..SMODS.current_mod.prefix..'_juice'] = 1},
["Flush House"] = {[SMODS.current_mod.prefix..'_juice'] = 1, ['l_'..SMODS.current_mod.prefix..'_juice'] = 5, ['s_'..SMODS.current_mod.prefix..'_juice'] = 1},
["Five of a Kind"] = {[SMODS.current_mod.prefix..'_juice'] = 1, ['l_'..SMODS.current_mod.prefix..'_juice'] = 5, ['s_'..SMODS.current_mod.prefix..'_juice'] = 1},
["Straight Flush"] = {[SMODS.current_mod.prefix..'_juice'] = 1, ['l_'..SMODS.current_mod.prefix..'_juice'] = 5, ['s_'..SMODS.current_mod.prefix..'_juice'] = 1},
["Full House"] = {[SMODS.current_mod.prefix..'_juice'] = 1, ['l_'..SMODS.current_mod.prefix..'_juice'] = 5, ['s_'..SMODS.current_mod.prefix..'_juice'] = 1},
["Flush"] = {[SMODS.current_mod.prefix..'_juice'] = 1, ['l_'..SMODS.current_mod.prefix..'_juice'] = 5, ['s_'..SMODS.current_mod.prefix..'_juice'] = 1},
["Straight"] = {[SMODS.current_mod.prefix..'_juice'] = 1, ['l_'..SMODS.current_mod.prefix..'_juice'] = 5, ['s_'..SMODS.current_mod.prefix..'_juice'] = 1},
["Three of a Kind"] = {[SMODS.current_mod.prefix..'_juice'] = 1, ['l_'..SMODS.current_mod.prefix..'_juice'] = 5, ['s_'..SMODS.current_mod.prefix..'_juice'] = 1},
["Two Pair"] = {[SMODS.current_mod.prefix..'_juice'] = 1, ['l_'..SMODS.current_mod.prefix..'_juice'] = 5, ['s_'..SMODS.current_mod.prefix..'_juice'] = 1},
["High Card"] = {[SMODS.current_mod.prefix..'_juice'] = 1, ['l_'..SMODS.current_mod.prefix..'_juice'] = 5, ['s_'..SMODS.current_mod.prefix..'_juice'] = 1},
},
calc_effect = function(self, effect, scored_card, key, amount, from_edition)
if not SMODS.Calculation_Controls.chips then return end
if key == 'juice' and amount then
if effect.card and effect.card ~= scored_card then juice_card(effect.card) end
self:modify(amount)
card_eval_status_text(scored_card, 'extra', nil, percent, nil,
{message = localize{type = 'variable', key = amount > 0 and 'a_chips' or 'a_chips_minus', vars = {amount}}, colour = self.colour})
return true
end
if key == 'xjuice' and amount then
if effect.card and effect.card ~= scored_card then juice_card(effect.card) end
self:modify(self.current * (amount - 1))
card_eval_status_text(scored_card, 'extra', nil, percent, nil,
{message = localize{type = 'variable', key = amount > 0 and 'a_chips' or 'a_chips_minus', vars = {'X'..amount}}, colour = self.colour})
return true
end
end
})
SMODS.Scoring_Calculation({
key = "juice",
func = function(self, chips, mult, flames)
return chips * mult * SMODS.get_scoring_parameter(self.mod.prefix..'_juice', flames)
end,
parameters = {'chips', 'mult', SMODS.current_mod.prefix..'_juice'},
replace_ui = function(self)
local scale = 0.3
return
{n=G.UIT.R, config={align = "cm", minh = 1, padding = 0.1}, nodes={
{n=G.UIT.C, config={align = 'cm', id = 'hand_chips'}, nodes = {
SMODS.GUI.score_container({
type = 'chips',
text = 'chip_text',
align = 'cr',
w = 1.1,
scale = scale
})
}},
SMODS.GUI.operator(scale*0.75),
{n=G.UIT.C, config={align = 'cm', id = 'hand_mult'}, nodes = {
SMODS.GUI.score_container({
type = 'mult',
align = 'cm',
w = 1.1,
scale = scale
})
}},
SMODS.GUI.operator(scale*0.75),
{n=G.UIT.C, config={align = 'cm', id = 'hand_modprefix_juice'}, nodes = {
SMODS.GUI.score_container({
type = 'modprefix_juice',
align = 'cl',
w = 1.1,
scale = scale
})
}},
}}
end
})Game Objects
- API Documentation
- SMODS.Achievement
- SMODS.Atlas
- SMODS.Attribute
- SMODS.Blind
- SMODS.CanvasSprite
- SMODS.Center
- SMODS.Challenge
- SMODS.DeckSkin
- SMODS.DrawStep
- SMODS.DynaTextEffect
- SMODS.Font
- SMODS.Gradient
- SMODS.https
- SMODS.JimboQuip
- SMODS.Keybind
- SMODS.Language
- SMODS.ObjectType and SMODS.ConsumableType
- SMODS.PokerHand
- SMODS.Rank and SMODS.Suit
- SMODS.Rarity
- SMODS.Scoring_Parameter and SMODS.Scoring_Calculation
- SMODS.Seal
- SMODS.Shader and SMODS.ScreenShader
- SMODS.Sound
- SMODS.Stake
- SMODS.Sticker
- SMODS.Tag
Guides
- Your First Mod
- Mod Metadata
- The Mod Object
- Calculate Functions
- Perma-bonuses
- Object Weights
- Logging
- Event Manager
- Localization
- Text Styling
- UI Structure
- Utility Functions
- All About
G - Internal Documentation
Release Notes
Found an issue, or want to add something? Submit a PR to the Wiki repo.



