Add new joker

This commit is contained in:
Emik 2026-06-08 22:35:42 +02:00
parent 0a50c41b0d
commit 69af47d3c7
Signed by: emik
GPG key ID: 6B0CD72A5E503BDF
22 changed files with 87 additions and 12 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 KiB

After

Width:  |  Height:  |  Size: 242 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 79 KiB

View file

@ -121,7 +121,11 @@ return {
Joker = {
j_Roland_amber = {
name = "Amber Acorn",
text = {"{X:mult,C:white}X#1#{} Mult", "Moves before", "hand is played"},
text = {
"{X:mult,C:white}X#1#{} Mult",
"Moves before",
"hand is played",
},
},
j_Roland_arctic = {
name = "Arctic Circle",
@ -161,6 +165,14 @@ return {
"if it is {C:dark_edition}Frozen",
},
},
j_Roland_crimson = {
name = "Crimson Heart",
text = {
"{X:mult,C:white}X#1#{} Mult",
"{C:red}Debuffs {C:attention}Joker",
"to the left",
},
},
j_Roland_domino = {
name = "Domino",
text = {

View file

@ -3,7 +3,7 @@
"id": "Roland",
"name": "Roland",
"prefix": "Roland",
"version": "2.8.25",
"version": "2.8.26",
"badge_colour": "8BE9FD",
"display_name": "Roland",
"main_file": "src/main.lua",

View file

@ -29,7 +29,6 @@ SMODS.Sound {
}
local function common_rank()
---@type { [integer]: integer }, { [integer]: string }
local tally, to_name = {}, {}
f(G.playing_cards):where(SMODS.has_no_rank, false):each(function(v)

View file

@ -173,7 +173,6 @@ SMODS.Challenge {
local mod = G.GAME.modifiers
mod.Roland_Eternally_Crimson = not context.setting_blind and mod.Roland_Eternally_Crimson or nil
local debuff = context.debuff_card
---@type (SMODS.Joker|{ability?: {Roland_crimson_heart_chosen: boolean?}, debuff: boolean?})[]
local cards = G.jokers.cards
if debuff and

View file

@ -268,7 +268,7 @@ q(function()
return v.config.center.key == card.Roland_frozen.proxy
end
return f(G.jokers.cards):any(eq) ---@type Card?
return f(G.jokers.cards):any(eq)
end
local orig_calculate = proxy.calculate

View file

@ -31,6 +31,21 @@ local joker = (function()
end
end)()
---@generic T
---@param tbl T[]
---@return fun(t: T[], i: integer): integer, T
---@return T[]
local function ipairs_reversed(tbl)
return function(t, i)
local k = i and i - 1 or #t
local v = t[k]
if v ~= nil then
return k, v
end
end, tbl
end
---@param card Card
local function is_frozen(card)
return card.edition and card.edition.key == "e_Roland_frozen"
@ -244,7 +259,7 @@ joker {
table.insert(info_queue, negative)
end,
calculate = function(_, _, context)
return (context.selling_self or context.forcetrigger) and f(G.consumeables.cards):each(function(v) --@type Card
return (context.selling_self or context.forcetrigger) and f(G.consumeables.cards):each(function(v)
return v.ability.consumeable and q {
delay = 1,
func = function()
@ -701,6 +716,50 @@ joker {
end,
}
joker {
key = "crimson",
pronouns = "she_her",
config = {extra = {xmult = 3}},
pixel_size = {w = 68, h = 68},
attributes = {"xmult"},
cost = 6,
rarity = 2,
eternal_compat = true,
blueprint_compat = true,
perishable_compat = false,
loc_vars = function(_, _, card)
return {vars = {card.ability.extra.xmult}}
end,
calculate = function(self, card, context)
return (self.crimson() or context.joker_main or context.forcetrigger) and
{card = card, xmult = card.ability.extra.xmult} or nil
end,
crimson = function()
f(G.jokers.cards, ipairs_reversed):each(function(v)
local right = G.jokers.cards[v.rank + 1]
local debuffed_by_crimson = right and
not right.debuff and
right.config.center.key == "j_Roland_crimson"
if debuffed_by_crimson and v.ability.Roland_crimson == nil then
v.ability.Roland_crimson = v.debuff and true or false
v:set_debuff(true)
elseif not debuffed_by_crimson and v.ability.Roland_crimson ~= nil then
v:set_debuff(v.ability.Roland_crimson)
v.ability.Roland_crimson = nil
end
end)
end,
}
local orig_stop_drag = Card.stop_drag
function Card:stop_drag(...)
local _ = self.area == G.jokers and G.P_CENTERS.j_Roland_crimson.crimson()
return orig_stop_drag(self, ...)
end
joker {
key = "martingale",
pronouns = "he_him",
@ -766,7 +825,6 @@ joker {
local extra = card.ability.extra
local col = {}
---@type { [number]: string|table|nil }|{colours: {[number]: {[1]: number, [2]: number, [3]: number, [4]: number}}}
local vars = f(self.Roland_idle_capacity):flatmap(function(v)
local l = localize_card(extra.cards[v], "b_Roland_unassigned").vars
@ -779,7 +837,7 @@ joker {
end):values():table()
table.insert(vars, extra.xmult)
vars.colours = col
vars["colours"] = col
return {vars = vars}
end,
calculate = function(_, card, context)

View file

@ -34,7 +34,7 @@ end
---@return V
---@nodiscard
local function autopairs(tbl, fpairs)
return (fpairs or tbl[#tbl] and ipairs or pairs)(tbl)
return (fpairs or (tbl[#tbl] and ipairs or pairs))(tbl)
end
---@param any any

View file

@ -43,6 +43,15 @@ if false then
-- This allows for better type inference.
SMODS.Mods.Roland.config = require "config"
---@type Card[]
CardArea.cards = CardArea.cards
--- @type { constants?: { TEN: table }, new: (fun(self: self, arr?: number[], sign?: number, noNormalize?: boolean): table), pow: (fun(x: number, y: number): number) }
_G["Big"] = _G["Big"]
--- @type fun(area: CardArea, ...: ...): Card
create_card_for_shop = create_card_for_shop
-- This exists to remove the @deprecated warning.
---Returns the elements from the given `list`. This function is equivalent to
---```lua

View file

@ -75,7 +75,7 @@ spectral {
table.insert(info_queue, G.P_CENTERS.m_stone)
end,
can_use = function()
return u() and next(G.hand.cards)
return u() and not not next(G.hand.cards)
end,
use = function(_, card)
q {

View file

@ -81,7 +81,6 @@ end
local orig_create_card_for_shop = create_card_for_shop
function create_card_for_shop(...)
---@type Card
local ret = orig_create_card_for_shop(...)
if not SMODS.Mods.Roland.config.illusion_seal or
@ -119,7 +118,6 @@ function get_blind_amount(ante, ...)
return 1 / 0
end
--- @type { constants?: { TEN: table }, new: (fun(self: self, arr?: number[], sign?: number, noNormalize?: boolean): table), pow: (fun(x: number, y: number): number) }
local big, rem = _G["Big"], tonumber(blind((ante % loop) + 1))
return ante / 15 >= loop and big:new(f(blind(ante - (loop * 15))):map(f().const(10)):table()) or