diff --git a/Cryptid/.gitignore b/Cryptid/.gitignore index d74fa80..4b6dff9 100644 --- a/Cryptid/.gitignore +++ b/Cryptid/.gitignore @@ -2,3 +2,5 @@ .vscode/* .luarc.json .lovelyignore +.idea/* +*.diff diff --git a/Cryptid/Cryptid.json b/Cryptid/Cryptid.json index 47393c0..b53982b 100644 --- a/Cryptid/Cryptid.json +++ b/Cryptid/Cryptid.json @@ -9,13 +9,16 @@ "priority": 114, "badge_colour": "708b91", "badge_text_colour": "FFFFFF", - "version": "0.5.5b", + "version": "0.5.12a", "dependencies": [ - "Talisman (>=2.0.9)", - "Steamodded (>=1.0.0~BETA-0314c)" + "Talisman (>=2.2.0a)", + "Steamodded (>=1.0.0~BETA-0827)" ], "conflicts": [ - "Saturn", - "AntePreview (>= 2.0.0~0c16a) (<<3.0.0)" + "AntePreview (>= 2.0.0~0c16a) (<<3.0.0)", + "Cartomancer (<= 4.11)" + ], + "provides": [ + "Cryptlib" ] } diff --git a/Cryptid/Cryptid.lua b/Cryptid/Cryptid.lua index 7c612a9..d58ccce 100644 --- a/Cryptid/Cryptid.lua +++ b/Cryptid/Cryptid.lua @@ -8,19 +8,23 @@ if not Cryptid then end local mod_path = "" .. SMODS.current_mod.path -- this path changes when each mod is loaded, but the local variable will retain Cryptid's path Cryptid.path = mod_path -Cryptid_config = SMODS.current_mod.config +Cryptid_config = SMODS.current_mod.config or {} --is this nil check needed? idk but i saw crash reports related to this + +-- Lovely Patch Target, toggles being able to change gameset config. Here for mod support +Cryptid_config.gameset_toggle = true -- Enable optional features SMODS.current_mod.optional_features = { retrigger_joker = true, post_trigger = true, - quantum_enhancements = false, -- Here are some other ones Steamodded has -- Cryptid doesn't use them YET, but these should be uncommented if Cryptid uses them -- These ones add new card areas that Steamodded will calculate through -- Might already be useful for sticker calc + + -- Cryptid uses cardarea deck now cardareas = { - --deck = true, + deck = true, discard = true, -- used by scorch }, } @@ -124,7 +128,7 @@ end -- either in [Mod]/Cryptid.lua or [Mod]/Cryptid/*.lua for _, mod in pairs(SMODS.Mods) do -- Note: Crashes with lone lua files - if mod.path and mod.id ~= "Cryptid" then + if not mod.disabled and mod.path and mod.id ~= "Cryptid" then local path = mod.path local files = NFS.getDirectoryItems(path) for _, file in ipairs(files) do @@ -182,6 +186,74 @@ function SMODS.injectItems(...) end end end + if G.PROFILES[G.SETTINGS.profile].all_unlocked then + G.PROFILES[G.SETTINGS.profile].cry_none = (Cryptid.enabled("set_cry_poker_hand_stuff") == true) + end + G.P_CENTERS.j_stencil.immutable = true + G.P_CENTERS.j_four_fingers.immutable = true + G.P_CENTERS.j_mime.immutable = true + G.P_CENTERS.j_ceremonial.immutable = true + G.P_CENTERS.j_marble.immutable = true + G.P_CENTERS.j_dusk.immutable = true + G.P_CENTERS.j_raised_fist.immutable = true + G.P_CENTERS.j_chaos.immutable = true + G.P_CENTERS.j_hack.immutable = true + G.P_CENTERS.j_pareidolia.immutable = true + G.P_CENTERS.j_supernova.immutable = true + G.P_CENTERS.j_space.immutable = true + G.P_CENTERS.j_dna.immutable = true + G.P_CENTERS.j_splash.immutable = true + G.P_CENTERS.j_sixth_sense.immutable = true + G.P_CENTERS.j_superposition.immutable = true + G.P_CENTERS.j_seance.immutable = true + G.P_CENTERS.j_riff_raff.immutable = true + G.P_CENTERS.j_shortcut.immutable = true + G.P_CENTERS.j_midas_mask.immutable = true + G.P_CENTERS.j_luchador.immutable = true + G.P_CENTERS.j_fortune_teller.immutable = true + G.P_CENTERS.j_diet_cola.immutable = true + G.P_CENTERS.j_mr_bones.immutable = true + G.P_CENTERS.j_sock_and_buskin.immutable = true + G.P_CENTERS.j_swashbuckler.immutable = true + G.P_CENTERS.j_certificate.immutable = true + G.P_CENTERS.j_smeared.immutable = true + G.P_CENTERS.j_ring_master.immutable = true + G.P_CENTERS.j_blueprint.immutable = true + G.P_CENTERS.j_oops.immutable = true + G.P_CENTERS.j_invisible.immutable = true + G.P_CENTERS.j_brainstorm.immutable = true + G.P_CENTERS.j_shoot_the_moon.immutable = true + G.P_CENTERS.j_cartomancer.immutable = true + G.P_CENTERS.j_astronomer.immutable = true + G.P_CENTERS.j_burnt.immutable = true + G.P_CENTERS.j_chicot.immutable = true + G.P_CENTERS.j_perkeo.immutable = true + G.P_CENTERS.j_hanging_chad.misprintize_caps = { extra = 40 } + G.P_CENTERS.c_high_priestess.misprintize_caps = { planets = 100 } + G.P_CENTERS.c_emperor.misprintize_caps = { tarots = 100 } + G.P_CENTERS.c_familiar.misprintize_caps = { extra = 100 } + G.P_CENTERS.c_grim.misprintize_caps = { extra = 100 } + G.P_CENTERS.c_incantation.misprintize_caps = { extra = 100 } + G.P_CENTERS.c_immolate.misprintize_caps = { destroy = 1e300 } + G.P_CENTERS.c_cryptid.misprintize_caps = { extra = 100, max_highlighted = 100 } + G.P_CENTERS.c_immolate.misprintize_caps = { destroy = 1e300 } + Cryptid.inject_pointer_aliases() + + --this has to be here because the colors dont exist earlier then this + Cryptid.circus_rarities["rare"] = { rarity = 3, base_mult = 2, order = 1, colour = G.C.RARITY.Rare } + Cryptid.circus_rarities["epic"] = { rarity = "cry_epic", base_mult = 3, order = 2, colour = G.C.RARITY.cry_epic } + Cryptid.circus_rarities["legendary"] = { rarity = 4, base_mult = 4, order = 3, colour = G.C.RARITY.Legendary } + Cryptid.circus_rarities["exotic"] = + { rarity = "cry_exotic", base_mult = 20, order = 4, colour = G.C.RARITY.cry_exotic } + + Cryptid.reload_localization() +end + +local old_repitions = SMODS.calculate_repetitions +SMODS.calculate_repetitions = function(card, context, reps) + local reps = old_repitions(card, context, reps) + reps = reps or { 1 } + return reps end local cryptidConfigTab = function() diff --git a/Cryptid/README.md b/Cryptid/README.md index d4a3bc7..5b86b33 100644 --- a/Cryptid/README.md +++ b/Cryptid/README.md @@ -2,7 +2,7 @@ # Cryptid An unbalanced Balatro mod. -Note: Cryptid requires [Steamodded **1.0.0~BETA-0314c**](https://github.com/Steamopollys/Steamodded/archive/refs/heads/main.zip) and [Talisman](https://github.com/MathIsFun0/Talisman/releases/latest). +Note: Cryptid requires [Steamodded](https://github.com/Steamodded/smods/releases/latest) and [Talisman](https://github.com/SpectralPack/Talisman/releases/latest). Cryptid currently adds: @@ -11,7 +11,7 @@ Cryptid currently adds: ![image](https://github.com/user-attachments/assets/2441010d-1f0d-4b3f-80f7-de45e071ad06) -### [Official Discord](https://discord.gg/cryptid) +### [Official Discord](https://discord.gg/eUf9Ur6RyB) ### [Mac Video Installation Guide](https://youtu.be/l5ni7fHgwTE?si=GAN5t5-y_IuEv8uA) ### [Not Mac Video Installation Guide](https://www.youtube.com/watch?v=aUr0gXE77rk) @@ -23,11 +23,8 @@ Cryptid currently adds: > *My game is crashing on startup/something doesn't appear to be loading!* Make sure everything is properly installed. -For Talisman, the folder that contains Talisman should be named `Talisman`. If you've downloaded the source code from GitHub (by clicking on [Code] and then [Download ZIP]), the folder within the ZIP may be called `Talisman-main`, which will cause a problem. Simply rename the folder(s) so that the `-main` part of the name is removed, so that the folder is just called `Talisman`. -Whenever you are manually updating Talisman or Cryptid, or any other mod for that matter, it's a good approach to instead delete the contents of the folder, then install the contents of the folder from the ZIP into the existing folder to avoid having to constantly rename the folder over and over. For automatic updates, try using the [automatic update script](https://discord.com/channels/1264429948970733782/1268911536638787625). It could also be that Steamodded is out of date, sometimes mods may use features of a new version that's absent in an older version, but don't change the version that they ask for. -You can grab the latest Steamodded by [clicking here](https://github.com/Steamopollys/Steamodded/archive/refs/heads/main.zip). > *I can't see any new jokers/content!* @@ -40,12 +37,12 @@ If they show up red, that means there's a problem. Hover over the mod icon (whic > *There's some content in the mod I don't like! Is there any way to remove them?* -You can disable some features of the mod by opening your Settings, going over to the Spectral Pack tab, clicking [Cryptid], then checking/unchecking what you want. -You can also enable/disable certain music tracks. If you're a streamer, consider disabling the Jimball music for your safety! +You can disable some features of the mod by opening your Mods, clicking [Cryptid], going over to the Config tab, and clicking Thematic Sets. There, you can toggle various Cryptid additions on or off as you see fit. +You can also enable/disable certain music tracks in the Music tab. If you're a streamer, consider disabling the Jimball music for your safety! > *I'm hitting infinity very often, is there any way to raise the limit of the scoring system?* -Talisman may be configured to be on **BigNum** mode, which has a maximum limit of ee308. You can make the limit virtually disappear by changing it to **OmegaNum**, which can handle e10##1000. You can configure it the same way; going into Settings, then the Spectral Pack tab, then Talisman. Be careful; if you have a saved run that was on a different number system, you won't be able to load it (unless if you switch back)! +Talisman may be configured to be on **BigNum** mode, which has a maximum limit of ee308. You can make the limit virtually disappear by changing it to **OmegaNum**, which can handle e10##1000. You can configure it by going into Mods, then clicking Talisman, and changing the Score Limit under Config. Be careful; if you have a saved run that was on a different number system, you won't be able to load it (unless if you switch back)! > *I've experienced a crash/bug!* diff --git a/Cryptid/assets/1x/atlasSleeves.png b/Cryptid/assets/1x/atlasSleeves.png index 7732baf..a402832 100644 Binary files a/Cryptid/assets/1x/atlasSleeves.png and b/Cryptid/assets/1x/atlasSleeves.png differ diff --git a/Cryptid/assets/1x/atlasepic.png b/Cryptid/assets/1x/atlasepic.png index 6a83066..f35ae50 100644 Binary files a/Cryptid/assets/1x/atlasepic.png and b/Cryptid/assets/1x/atlasepic.png differ diff --git a/Cryptid/assets/1x/atlasexotic.png b/Cryptid/assets/1x/atlasexotic.png index e4cac0d..94866c6 100644 Binary files a/Cryptid/assets/1x/atlasexotic.png and b/Cryptid/assets/1x/atlasexotic.png differ diff --git a/Cryptid/assets/1x/atlasnotjokers.png b/Cryptid/assets/1x/atlasnotjokers.png index b75c9a4..60d9cfd 100644 Binary files a/Cryptid/assets/1x/atlasnotjokers.png and b/Cryptid/assets/1x/atlasnotjokers.png differ diff --git a/Cryptid/assets/1x/atlasone.png b/Cryptid/assets/1x/atlasone.png index bebce10..7a53814 100644 Binary files a/Cryptid/assets/1x/atlasone.png and b/Cryptid/assets/1x/atlasone.png differ diff --git a/Cryptid/assets/1x/atlasspooky.png b/Cryptid/assets/1x/atlasspooky.png index 2b4b164..0273191 100644 Binary files a/Cryptid/assets/1x/atlasspooky.png and b/Cryptid/assets/1x/atlasspooky.png differ diff --git a/Cryptid/assets/1x/atlasthree.png b/Cryptid/assets/1x/atlasthree.png index c99ad1f..5ce3db3 100644 Binary files a/Cryptid/assets/1x/atlasthree.png and b/Cryptid/assets/1x/atlasthree.png differ diff --git a/Cryptid/assets/1x/atlastwo.png b/Cryptid/assets/1x/atlastwo.png index 4a01b78..56283d7 100644 Binary files a/Cryptid/assets/1x/atlastwo.png and b/Cryptid/assets/1x/atlastwo.png differ diff --git a/Cryptid/assets/1x/bl_cry.png b/Cryptid/assets/1x/bl_cry.png index 550abb9..84dfd23 100644 Binary files a/Cryptid/assets/1x/bl_cry.png and b/Cryptid/assets/1x/bl_cry.png differ diff --git a/Cryptid/assets/1x/bl_cry_two.png b/Cryptid/assets/1x/bl_cry_two.png new file mode 100644 index 0000000..2025ee8 Binary files /dev/null and b/Cryptid/assets/1x/bl_cry_two.png differ diff --git a/Cryptid/assets/1x/cry_misc.png b/Cryptid/assets/1x/cry_misc.png index e91183b..56da675 100644 Binary files a/Cryptid/assets/1x/cry_misc.png and b/Cryptid/assets/1x/cry_misc.png differ diff --git a/Cryptid/assets/1x/intercept_sprite.aseprite b/Cryptid/assets/1x/intercept_sprite.aseprite new file mode 100644 index 0000000..5182d11 Binary files /dev/null and b/Cryptid/assets/1x/intercept_sprite.aseprite differ diff --git a/Cryptid/assets/1x/pack_cry.png b/Cryptid/assets/1x/pack_cry.png index da9157d..760e471 100644 Binary files a/Cryptid/assets/1x/pack_cry.png and b/Cryptid/assets/1x/pack_cry.png differ diff --git a/Cryptid/assets/1x/shinyc.png b/Cryptid/assets/1x/shinyc.png index 79e0271..7966d51 100644 Binary files a/Cryptid/assets/1x/shinyc.png and b/Cryptid/assets/1x/shinyc.png differ diff --git a/Cryptid/assets/1x/sleeve_cry_glowing.png b/Cryptid/assets/1x/sleeve_cry_glowing.png new file mode 100644 index 0000000..3fd3361 Binary files /dev/null and b/Cryptid/assets/1x/sleeve_cry_glowing.png differ diff --git a/Cryptid/assets/1x/sticker_cry.png b/Cryptid/assets/1x/sticker_cry.png index be0b290..86e3f6c 100644 Binary files a/Cryptid/assets/1x/sticker_cry.png and b/Cryptid/assets/1x/sticker_cry.png differ diff --git a/Cryptid/assets/1x/tag_cry.png b/Cryptid/assets/1x/tag_cry.png index d7da3ba..6ae3ea5 100644 Binary files a/Cryptid/assets/1x/tag_cry.png and b/Cryptid/assets/1x/tag_cry.png differ diff --git a/Cryptid/assets/2x/atlasSleeves.png b/Cryptid/assets/2x/atlasSleeves.png index 6327e3c..e3ea0b1 100644 Binary files a/Cryptid/assets/2x/atlasSleeves.png and b/Cryptid/assets/2x/atlasSleeves.png differ diff --git a/Cryptid/assets/2x/atlasepic.png b/Cryptid/assets/2x/atlasepic.png index 35092df..3104e41 100644 Binary files a/Cryptid/assets/2x/atlasepic.png and b/Cryptid/assets/2x/atlasepic.png differ diff --git a/Cryptid/assets/2x/atlasexotic.png b/Cryptid/assets/2x/atlasexotic.png index 1b72fbe..501f13e 100644 Binary files a/Cryptid/assets/2x/atlasexotic.png and b/Cryptid/assets/2x/atlasexotic.png differ diff --git a/Cryptid/assets/2x/atlasnotjokers.png b/Cryptid/assets/2x/atlasnotjokers.png index ee64819..7277fb8 100644 Binary files a/Cryptid/assets/2x/atlasnotjokers.png and b/Cryptid/assets/2x/atlasnotjokers.png differ diff --git a/Cryptid/assets/2x/atlasone.png b/Cryptid/assets/2x/atlasone.png index 968a7cd..82f9310 100644 Binary files a/Cryptid/assets/2x/atlasone.png and b/Cryptid/assets/2x/atlasone.png differ diff --git a/Cryptid/assets/2x/atlasspooky.png b/Cryptid/assets/2x/atlasspooky.png index bd10f33..c693f74 100644 Binary files a/Cryptid/assets/2x/atlasspooky.png and b/Cryptid/assets/2x/atlasspooky.png differ diff --git a/Cryptid/assets/2x/atlasthree.png b/Cryptid/assets/2x/atlasthree.png index 4ea4d34..1656c70 100644 Binary files a/Cryptid/assets/2x/atlasthree.png and b/Cryptid/assets/2x/atlasthree.png differ diff --git a/Cryptid/assets/2x/atlastwo.png b/Cryptid/assets/2x/atlastwo.png index eb737c8..b4be434 100644 Binary files a/Cryptid/assets/2x/atlastwo.png and b/Cryptid/assets/2x/atlastwo.png differ diff --git a/Cryptid/assets/2x/bl_cry.png b/Cryptid/assets/2x/bl_cry.png index 02d8278..c7c49a5 100644 Binary files a/Cryptid/assets/2x/bl_cry.png and b/Cryptid/assets/2x/bl_cry.png differ diff --git a/Cryptid/assets/2x/bl_cry_two.png b/Cryptid/assets/2x/bl_cry_two.png new file mode 100644 index 0000000..c7c0aa8 Binary files /dev/null and b/Cryptid/assets/2x/bl_cry_two.png differ diff --git a/Cryptid/assets/2x/cry_misc.png b/Cryptid/assets/2x/cry_misc.png index ce1186d..c835b36 100644 Binary files a/Cryptid/assets/2x/cry_misc.png and b/Cryptid/assets/2x/cry_misc.png differ diff --git a/Cryptid/assets/2x/intercept_sprite.aseprite b/Cryptid/assets/2x/intercept_sprite.aseprite new file mode 100644 index 0000000..61b6432 Binary files /dev/null and b/Cryptid/assets/2x/intercept_sprite.aseprite differ diff --git a/Cryptid/assets/2x/pack_cry.png b/Cryptid/assets/2x/pack_cry.png index a36a50d..bbb649a 100644 Binary files a/Cryptid/assets/2x/pack_cry.png and b/Cryptid/assets/2x/pack_cry.png differ diff --git a/Cryptid/assets/2x/shinyc.png b/Cryptid/assets/2x/shinyc.png index 2515d04..5988a79 100644 Binary files a/Cryptid/assets/2x/shinyc.png and b/Cryptid/assets/2x/shinyc.png differ diff --git a/Cryptid/assets/2x/sleeve_cry_glowing.png b/Cryptid/assets/2x/sleeve_cry_glowing.png new file mode 100644 index 0000000..0bb63f8 Binary files /dev/null and b/Cryptid/assets/2x/sleeve_cry_glowing.png differ diff --git a/Cryptid/assets/2x/sticker_cry.png b/Cryptid/assets/2x/sticker_cry.png index 43cfd6e..4520dae 100644 Binary files a/Cryptid/assets/2x/sticker_cry.png and b/Cryptid/assets/2x/sticker_cry.png differ diff --git a/Cryptid/assets/2x/tag_cry.png b/Cryptid/assets/2x/tag_cry.png index d7c0e16..a3fa98b 100644 Binary files a/Cryptid/assets/2x/tag_cry.png and b/Cryptid/assets/2x/tag_cry.png differ diff --git a/Cryptid/assets/shaders/astral.fs b/Cryptid/assets/shaders/astral.fs index ea106c1..80a88d7 100644 --- a/Cryptid/assets/shaders/astral.fs +++ b/Cryptid/assets/shaders/astral.fs @@ -12,6 +12,9 @@ extern MY_HIGHP_OR_MEDIUMP vec2 image_details; extern bool shadow; extern MY_HIGHP_OR_MEDIUMP vec4 burn_colour_1; extern MY_HIGHP_OR_MEDIUMP vec4 burn_colour_2; +extern MY_HIGHP_OR_MEDIUMP vec2 mouse_screen_pos; +extern MY_HIGHP_OR_MEDIUMP float hovering; +extern MY_HIGHP_OR_MEDIUMP float screen_scale; vec4 dissolve_mask(vec4 tex, vec2 texture_coords, vec2 uv) { @@ -94,20 +97,144 @@ vec4 HSL(vec4 c) return hsl; } +vec4 RGBtoHSV(vec4 rgb) +{ + vec4 hsv; + float minVal = min(min(rgb.r, rgb.g), rgb.b); + float maxVal = max(max(rgb.r, rgb.g), rgb.b); + float delta = maxVal - minVal; + + // Value + hsv.z = maxVal; + + // Saturation + if (maxVal != 0.0) + hsv.y = delta / maxVal; + else { + // r = g = b = 0, s = 0, v is undefined + hsv.y = 0.0; + hsv.x = -1.0; + return hsv; + } + + // Hue + if (rgb.r == maxVal) + hsv.x = (rgb.g - rgb.b) / delta; // between yellow & magenta + else if (rgb.g == maxVal) + hsv.x = 2.0 + (rgb.b - rgb.r) / delta; // between cyan & yellow + else + hsv.x = 4.0 + (rgb.r - rgb.g) / delta; // between magenta & cyan + + hsv.x = hsv.x * (1.0 / 6.0); + if (hsv.x < 0.0) + hsv.x += 1.0; + + // Alpha + hsv.w = rgb.a; + + return hsv; +} + +vec4 HSVtoRGB(vec4 hsv) { + vec4 rgb; + + float h = hsv.x * 6.0; + float c = hsv.z * hsv.y; + float x = c * (1.0 - abs(mod(h, 2.0) - 1.0)); + float m = hsv.z - c; + + if (h < 1.0) { + rgb = vec4(c, x, 0.0, hsv.a); + } else if (h < 2.0) { + rgb = vec4(x, c, 0.0, hsv.a); + } else if (h < 3.0) { + rgb = vec4(0.0, c, x, hsv.a); + } else if (h < 4.0) { + rgb = vec4(0.0, x, c, hsv.a); + } else if (h < 5.0) { + rgb = vec4(x, 0.0, c, hsv.a); + } else { + rgb = vec4(c, 0.0, x, hsv.a); + } + + rgb.rgb += m; + + return rgb; +} + +float bitxor(float val1, float val2) +{ + float outp = 0.; + for(float i = 1.; i < 9.; i++) outp += floor(mod(mod(floor(val1*pow(2.,-i)),pow(2.,i))+mod(floor(val2*pow(2.,-i)),pow(2.,i)),2.))*pow(2.,i); + return outp/256.; +} + +float mod2(float val1, float mod1) +{ + val1 /= mod1; + val1 -= floor(val1); + return(mod1 * val1); +} + +#define PI 3.14159265358979323846 + +float rand(vec2 c){ + return fract(sin(dot(c.xy ,vec2(12.9898,78.233))) * 43758.5453); +} + +float noise(vec2 p, float freq ){ + float unit = 1./freq; + vec2 ij = floor(p/unit); + vec2 xy = mod(p,unit)/unit; + //xy = 3.*xy*xy-2.*xy*xy*xy; + xy = .5*(1.-cos(PI*xy)); + float a = rand((ij+vec2(0.,0.))); + float b = rand((ij+vec2(1.,0.))); + float c = rand((ij+vec2(0.,1.))); + float d = rand((ij+vec2(1.,1.))); + float x1 = mix(a, b, xy.x); + float x2 = mix(c, d, xy.x); + return mix(x1, x2, xy.y); +} + +float pNoise(vec2 p, int res){ + float persistance = .5; + float n = 0.; + float normK = 0.; + float f = 4.; + float amp = 1.; + int iCount = 0; + for (int i = 0; i<50; i++){ + n+=amp*noise(p, f); + f*=2.; + normK+=amp; + amp*=persistance; + if (iCount == res) break; + iCount++; + } + float nf = n/normK; + return nf*nf*nf*nf; +} + vec4 effect( vec4 colour, Image texture, vec2 texture_coords, vec2 screen_coords ) { vec4 tex = Texel(texture, texture_coords); vec2 uv = (((texture_coords)*(image_details)) - texture_details.xy*texture_details.ba)/texture_details.ba; + // Dummy, doesn't do anything but at least it makes the shader useable + if (uv.x > uv.x * 2.){ + uv = astral; + } + + float mod = astral.r * 1.0; + number low = min(tex.r, min(tex.g, tex.b)); number high = max(tex.r, max(tex.g, tex.b)); number delta = high - low; - number saturation_fac = 1. - max(0., 0.05*(1.1-delta)); + //vec4 hsl = HSL(vec4(tex.r, tex.g, tex.b, tex.a)); - vec4 hsl = HSL(vec4(tex.r*saturation_fac, tex.g*saturation_fac, tex.b, tex.a)); - - float t = astral.y*2.221 + mod(time,1.); + float t = astral.y*2.221 + time; vec2 floored_uv = (floor((uv*texture_details.ba)))/texture_details.ba; vec2 uv_scaled_centered = (floored_uv - 0.5) * 50.; @@ -119,22 +246,48 @@ vec4 effect( vec4 colour, Image texture, vec2 texture_coords, vec2 screen_coords cos(length(field_part1) / 19.483) + sin(length(field_part2) / 33.155) * cos(field_part2.y / 15.73) + cos(length(field_part3) / 27.193) * sin(field_part3.x / 21.92) ))/2.; - float res = (.5 + .5* cos( (astral.x) * 2.612 + ( field + -.5 ) *3.14)); - hsl.x = .8; - hsl.y = hsl.y * 0.8; - hsl.z = hsl.z * 0.2 + 0.6 * sin(hsl.z/2.5 - res/4. + sin(astral.y)/8. + 0.5)/1.4; + + vec4 pixel = Texel(texture, texture_coords); + + float cx = uv_scaled_centered.x * 1.; + float cy = uv_scaled_centered.y * 1.; + + + + vec4 hsl = HSL(vec4(tex.r, tex.g, tex.b, tex.a)); + + + // |y| = 50, |x| = 50 tex.rgb = RGB(hsl).rgb; - if (tex[3] < 0.7) - tex[3] = tex[3]/3.; + vec2 mouse_offset = (screen_coords.xy - mouse_screen_pos.xy)/screen_scale; + + float scaled_uvy = (uv.y +mouse_offset.y -0.5)*5.*1.338; + float scaled_uvx = (uv.x +mouse_offset.x -0.5)*5.; + float norm_uv = sqrt(scaled_uvx*scaled_uvx + scaled_uvy*scaled_uvy); + + pixel = vec4(pixel.rgb * 0.0 + tex.rgb * tex.a, pixel.a); + + float res = (.5 + .5* cos( (astral.x) * 2.612 + ( field + -.5 ) *3.14)); + vec4 textp = RGB(hsl); + tex.rgb = textp.rgb; + + float stars = ((pNoise(uv*10. + t/15.0, 10)*pNoise(uv*10. + t/15.0, 10)+1.5)/1.+0.15 + ((pNoise(uv*12. + t/15.0, 10)+1.2)/1.+0.3))/2.2+0.05 + 0.007*norm_uv * 1.1; + + float clusters = (pNoise(uv*10.0-t/15.0, 10)+1.5)/1.5-0.25 + 0.007*norm_uv; + + float super_clusters = (pNoise(uv/15.0, 10)+0.1)/2.+0.3 - 0.008*norm_uv; + + clusters *= clusters * clusters * clusters * 0.4; + stars *= stars * stars; + super_clusters *= super_clusters * super_clusters; + + colour.rgb = vec3(0.6, 0.45, 1.) * (((clusters + stars + super_clusters)+0.1)) * 0.285; + return dissolve_mask(tex*colour, texture_coords, uv); } -extern MY_HIGHP_OR_MEDIUMP vec2 mouse_screen_pos; -extern MY_HIGHP_OR_MEDIUMP float hovering; -extern MY_HIGHP_OR_MEDIUMP float screen_scale; - #ifdef VERTEX vec4 position( mat4 transform_projection, vec4 vertex_position ) { @@ -146,6 +299,6 @@ vec4 position( mat4 transform_projection, vec4 vertex_position ) float scale = 0.2*(-0.03 - 0.3*max(0., 0.3-mid_dist)) *hovering*(length(mouse_offset)*length(mouse_offset))/(2. -mid_dist); - return transform_projection * vertex_position + vec4(0,0,0,scale); + return transform_projection * vertex_position + vec4(0.,0.,0.,scale); } #endif \ No newline at end of file diff --git a/Cryptid/assets/shaders/blur.fs b/Cryptid/assets/shaders/blur.fs index 2933211..3235001 100644 --- a/Cryptid/assets/shaders/blur.fs +++ b/Cryptid/assets/shaders/blur.fs @@ -179,6 +179,6 @@ vec4 position( mat4 transform_projection, vec4 vertex_position ) float scale = 0.2*(-0.03 - 0.3*max(0., 0.3-mid_dist)) *hovering*(length(mouse_offset)*length(mouse_offset))/(2. -mid_dist); - return transform_projection * vertex_position + vec4(0,0,0,scale); + return transform_projection * vertex_position + vec4(0.,0.,0.,scale); } #endif \ No newline at end of file diff --git a/Cryptid/assets/shaders/glass.fs b/Cryptid/assets/shaders/glass.fs index f931c53..19fa9ca 100644 --- a/Cryptid/assets/shaders/glass.fs +++ b/Cryptid/assets/shaders/glass.fs @@ -104,6 +104,6 @@ vec4 position( mat4 transform_projection, vec4 vertex_position ) float scale = 0.2*(-0.03 - 0.3*max(0., 0.3-mid_dist)) *hovering*(length(mouse_offset)*length(mouse_offset))/(2. -mid_dist); - return transform_projection * vertex_position + vec4(0,0,0,scale); + return transform_projection * vertex_position + vec4(0.,0.,0.,scale); } #endif \ No newline at end of file diff --git a/Cryptid/assets/shaders/glitched.fs b/Cryptid/assets/shaders/glitched.fs index 0564c1b..2215360 100644 --- a/Cryptid/assets/shaders/glitched.fs +++ b/Cryptid/assets/shaders/glitched.fs @@ -139,6 +139,6 @@ vec4 position( mat4 transform_projection, vec4 vertex_position ) float scale = 0.2*(-0.03 - 0.3*max(0., 0.3-mid_dist)) *hovering*(length(mouse_offset)*length(mouse_offset))/(2. -mid_dist); - return transform_projection * vertex_position + vec4(0,0,0,scale); + return transform_projection * vertex_position + vec4(0.,0.,0.,scale); } #endif \ No newline at end of file diff --git a/Cryptid/assets/shaders/glitched_b.fs b/Cryptid/assets/shaders/glitched_b.fs new file mode 100644 index 0000000..cfaf149 --- /dev/null +++ b/Cryptid/assets/shaders/glitched_b.fs @@ -0,0 +1,282 @@ +#if defined(VERTEX) || __VERSION__ > 100 || defined(GL_FRAGMENT_PRECISION_HIGH) + #define MY_HIGHP_OR_MEDIUMP highp +#else + #define MY_HIGHP_OR_MEDIUMP mediump +#endif + +extern MY_HIGHP_OR_MEDIUMP vec2 glitched_b; +extern MY_HIGHP_OR_MEDIUMP number dissolve; +extern MY_HIGHP_OR_MEDIUMP number time; +extern MY_HIGHP_OR_MEDIUMP vec4 texture_details; +extern MY_HIGHP_OR_MEDIUMP vec2 image_details; +extern bool shadow; +extern MY_HIGHP_OR_MEDIUMP vec4 burn_colour_1; +extern MY_HIGHP_OR_MEDIUMP vec4 burn_colour_2; + +vec4 dissolve_mask(vec4 tex, vec2 texture_coords, vec2 uv) +{ + if (dissolve < 0.001) { + return vec4(shadow ? vec3(0.,0.,0.) : tex.xyz, shadow ? tex.a*0.3: tex.a); + } + + float adjusted_dissolve = (dissolve*dissolve*(3.-2.*dissolve))*1.02 - 0.01; //Adjusting 0.0-1.0 to fall to -0.1 - 1.1 scale so the mask does not pause at extreme values + + float t = time * 10.0 + 2003.; + vec2 floored_uv = (floor((uv*texture_details.ba)))/max(texture_details.b, texture_details.a); + vec2 uv_scaled_centered = (floored_uv - 0.5) * 2.3 * max(texture_details.b, texture_details.a); + + vec2 field_part1 = uv_scaled_centered + 50.*vec2(sin(-t / 143.6340), cos(-t / 99.4324)); + vec2 field_part2 = uv_scaled_centered + 50.*vec2(cos( t / 53.1532), cos( t / 61.4532)); + vec2 field_part3 = uv_scaled_centered + 50.*vec2(sin(-t / 87.53218), sin(-t / 49.0000)); + + float field = (1.+ ( + cos(length(field_part1) / 19.483) + sin(length(field_part2) / 33.155) * cos(field_part2.y / 15.73) + + cos(length(field_part3) / 27.193) * sin(field_part3.x / 21.92) ))/2.; + vec2 borders = vec2(0.2, 0.8); + + float res = (.5 + .5* cos( (adjusted_dissolve) / 82.612 + ( field + -.5 ) *3.14)) + - (floored_uv.x > borders.y ? (floored_uv.x - borders.y)*(5. + 5.*dissolve) : 0.)*(dissolve) + - (floored_uv.y > borders.y ? (floored_uv.y - borders.y)*(5. + 5.*dissolve) : 0.)*(dissolve) + - (floored_uv.x < borders.x ? (borders.x - floored_uv.x)*(5. + 5.*dissolve) : 0.)*(dissolve) + - (floored_uv.y < borders.x ? (borders.x - floored_uv.y)*(5. + 5.*dissolve) : 0.)*(dissolve); + + if (tex.a > 0.01 && burn_colour_1.a > 0.01 && !shadow && res < adjusted_dissolve + 0.8*(0.5-abs(adjusted_dissolve-0.5)) && res > adjusted_dissolve) { + if (!shadow && res < adjusted_dissolve + 0.5*(0.5-abs(adjusted_dissolve-0.5)) && res > adjusted_dissolve) { + tex.rgba = burn_colour_1.rgba; + } else if (burn_colour_2.a > 0.01) { + tex.rgba = burn_colour_2.rgba; + } + } + + return vec4(shadow ? vec3(0.,0.,0.) : tex.xyz, res > adjusted_dissolve ? (shadow ? tex.a*0.3: tex.a) : .0); +} + +number hue(number s, number t, number h) +{ + number hs = mod(h, 1.)*6.; + if (hs < 1.) return (t-s) * hs + s; + if (hs < 3.) return t; + if (hs < 4.) return (t-s) * (4.-hs) + s; + return s; +} + +vec4 RGB(vec4 c) +{ + if (c.y < 0.0001) + return vec4(vec3(c.z), c.a); + + number t = (c.z < .5) ? c.y*c.z + c.z : -c.y*c.z + (c.y+c.z); + number s = 2.0 * c.z - t; + return vec4(hue(s,t,c.x + 1./3.), hue(s,t,c.x), hue(s,t,c.x - 1./3.), c.w); +} + +vec4 HSL(vec4 c) +{ + number low = min(c.r, min(c.g, c.b)); + number high = max(c.r, max(c.g, c.b)); + number delta = high - low; + number sum = high+low; + + vec4 hsl = vec4(.0, .0, .5 * sum, c.a); + if (delta == .0) + return hsl; + + hsl.y = (hsl.z < .5) ? delta / sum : delta / (2.0 - sum); + + if (high == c.r) + hsl.x = (c.g - c.b) / delta; + else if (high == c.g) + hsl.x = (c.b - c.r) / delta + 2.0; + else + hsl.x = (c.r - c.g) / delta + 4.0; + + hsl.x = mod(hsl.x / 6., 1.); + return hsl; +} + +vec4 RGBtoHSV(vec4 rgb) +{ + vec4 hsv; + float minVal = min(min(rgb.r, rgb.g), rgb.b); + float maxVal = max(max(rgb.r, rgb.g), rgb.b); + float delta = maxVal - minVal; + + // Value + hsv.z = maxVal; + + // Saturation + if (maxVal != 0.0) + hsv.y = delta / maxVal; + else { + // r = g = b = 0, s = 0, v is undefined + hsv.y = 0.0; + hsv.x = -1.0; + return hsv; + } + + // Hue + if (rgb.r == maxVal) + hsv.x = (rgb.g - rgb.b) / delta; // between yellow & magenta + else if (rgb.g == maxVal) + hsv.x = 2.0 + (rgb.b - rgb.r) / delta; // between cyan & yellow + else + hsv.x = 4.0 + (rgb.r - rgb.g) / delta; // between magenta & cyan + + hsv.x = hsv.x * (1.0 / 6.0); + if (hsv.x < 0.0) + hsv.x += 1.0; + + // Alpha + hsv.w = rgb.a; + + return hsv; +} + +vec4 HSVtoRGB(vec4 hsv) { + vec4 rgb; + + float h = hsv.x * 6.0; + float c = hsv.z * hsv.y; + float x = c * (1.0 - abs(mod(h, 2.0) - 1.0)); + float m = hsv.z - c; + + if (h < 1.0) { + rgb = vec4(c, x, 0.0, hsv.a); + } else if (h < 2.0) { + rgb = vec4(x, c, 0.0, hsv.a); + } else if (h < 3.0) { + rgb = vec4(0.0, c, x, hsv.a); + } else if (h < 4.0) { + rgb = vec4(0.0, x, c, hsv.a); + } else if (h < 5.0) { + rgb = vec4(x, 0.0, c, hsv.a); + } else { + rgb = vec4(c, 0.0, x, hsv.a); + } + + rgb.rgb += m; + + return rgb; +} + +float bitxor(float val1, float val2) +{ + float outp = 0.; + for(float i = 1.; i < 9.; i++) outp += floor(mod(mod(floor(val1*pow(2.,-i)),pow(2.,i))+mod(floor(val2*pow(2.,-i)),pow(2.,i)),2.))*pow(2.,i); + return outp/256.; +} + +float mod2(float val1, float mod1) +{ + val1 /= mod1; + val1 -= floor(val1); + return(mod1 * val1); +} + + +vec4 effect( vec4 colour, Image texture, vec2 texture_coords, vec2 screen_coords ) +{ + vec4 tex = Texel(texture, texture_coords); + vec2 uv = (((texture_coords)*(image_details)) - texture_details.xy*texture_details.ba)/texture_details.ba; + + // Dummy, doesn't do anything but at least it makes the shader useable + if (uv.x > uv.x * 2.){ + uv = glitched_b; + } + + float mod = glitched_b.r * 1.0; + + number low = min(tex.r, min(tex.g, tex.b)); + number high = max(tex.r, max(tex.g, tex.b)); + number delta = high - low; + + //vec4 hsl = HSL(vec4(tex.r, tex.g, tex.b, tex.a)); + + float t = glitched_b.y*2.221 + time; + vec2 floored_uv = (floor((uv*texture_details.ba)))/texture_details.ba; + vec2 uv_scaled_centered = (floored_uv - 0.5) * 50.; + + vec2 field_part1 = uv_scaled_centered + 50.*vec2(sin(-t / 143.6340), cos(-t / 99.4324)); + vec2 field_part2 = uv_scaled_centered + 50.*vec2(cos( t / 53.1532), cos( t / 61.4532)); + vec2 field_part3 = uv_scaled_centered + 50.*vec2(sin(-t / 87.53218), sin(-t / 49.0000)); + + float field = (1.+ ( + cos(length(field_part1) / 19.483) + sin(length(field_part2) / 33.155) * cos(field_part2.y / 15.73) + + cos(length(field_part3) / 27.193) * sin(field_part3.x / 21.92) ))/2.; + + + vec4 pixel = Texel(texture, texture_coords); + + float cx = uv_scaled_centered.x * 1.; + float cy = uv_scaled_centered.y * 1.; + + float randnum = mod2(floor(4.*t), 256.)*mod2(floor(4.*t), 27.); + randnum = mod2(bitxor(pow(randnum, 3.) - randnum + 3., 7. + floor(randnum/11.)), 256.); + randnum = mod2(randnum*123.54,0.1)*10.; + + + + vec4 hsl = HSL(vec4(tex.r, tex.g, tex.b, tex.a)); + + float xorscale = 10.; + + // |y| = 50, |x| = 50 + + float mbx; + float mby; + float offx; + float offy; + float rmasksum = -1.; + float rectmask = 1.; + t = floor(t/4.); + + for(float i = 0.; i < 5.; i++) + { + randnum = bitxor(255.*randnum + mod2(t,81.), pow(randnum*(16.-i), 2.)); + mbx = (cx - 25.*sin(100./randnum)) * (1. + 2.*(floor(cos(177./randnum + 1.)))); + mby = (cy - 25.*cos(113./randnum + 1.)) * (1. + 2.*(floor(sin(221./randnum)))); + offx = bitxor(255.*randnum, pow(255.*randnum,5.) - 255.*randnum); + offy = bitxor(255.*randnum, pow(255.*randnum,5.) + 255.*randnum); + offx /= 10.; + offy /= 10.; + rectmask = (-mbx + abs(abs(mbx) + offx) - offx) - (mby - abs(abs(mby) - offy) + offy); + rmasksum *= -1. * min(0., max(-1., 5. - pow(rectmask, 2.))); + } + + float laddermask = pow(sin((23.-20.*randnum*randnum)*pow(sin(sin(cy*randnum) + pow(sin(cy*randnum),2.)),2.)),2.) * rmasksum; + + + hsl.x += floor(randnum + 0.1) * rmasksum * 4. * randnum * (1. - laddermask);// * bitxor(cx * xorscale, cy * xorscale)/4; + hsl.y += laddermask * (1. + 2. * rmasksum); + hsl.z += floor(randnum + 0.2) * (1. + rmasksum) * (1. - 1.5*hsl.z) * 0.1; + + tex.rgb = RGB(hsl).rgb; + + pixel = vec4(pixel.rgb * 0.0 + tex.rgb * tex.a, pixel.a); + + + + float res = (.5 + .5* cos( (glitched_b.x) * 2.612 + ( field + -.5 ) *3.14)); + vec4 textp = RGB(hsl); + tex.rgb = textp.rgb; + return dissolve_mask(tex*colour, texture_coords, uv); +} + +extern MY_HIGHP_OR_MEDIUMP vec2 mouse_screen_pos; +extern MY_HIGHP_OR_MEDIUMP float hovering; +extern MY_HIGHP_OR_MEDIUMP float screen_scale; + +#ifdef VERTEX +vec4 position( mat4 transform_projection, vec4 vertex_position ) +{ + if (hovering <= 0.){ + return transform_projection * vertex_position; + } + float mid_dist = length(vertex_position.xy - 0.5*love_ScreenSize.xy)/length(love_ScreenSize.xy); + vec2 mouse_offset = (vertex_position.xy - mouse_screen_pos.xy)/screen_scale; + float scale = 0.2*(-0.03 - 0.3*max(0., 0.3-mid_dist)) + *hovering*(length(mouse_offset)*length(mouse_offset))/(2. -mid_dist); + + return transform_projection * vertex_position + vec4(0.,0.,0.,scale); +} +#endif diff --git a/Cryptid/assets/shaders/gold.fs b/Cryptid/assets/shaders/gold.fs index ba79329..48888a0 100644 --- a/Cryptid/assets/shaders/gold.fs +++ b/Cryptid/assets/shaders/gold.fs @@ -109,6 +109,6 @@ vec4 position( mat4 transform_projection, vec4 vertex_position ) float scale = 0.2*(-0.03 - 0.3*max(0., 0.3-mid_dist)) *hovering*(length(mouse_offset)*length(mouse_offset))/(2. -mid_dist); - return transform_projection * vertex_position + vec4(0,0,0,scale); + return transform_projection * vertex_position + vec4(0.,0.,0.,scale); } #endif \ No newline at end of file diff --git a/Cryptid/assets/shaders/m.fs b/Cryptid/assets/shaders/m.fs index 0bc1e43..efd8283 100644 --- a/Cryptid/assets/shaders/m.fs +++ b/Cryptid/assets/shaders/m.fs @@ -130,6 +130,6 @@ vec4 position( mat4 transform_projection, vec4 vertex_position ) float scale = 0.2*(-0.03 - 0.3*max(0., 0.3-mid_dist)) *hovering*(length(mouse_offset)*length(mouse_offset))/(2. -mid_dist); - return transform_projection * vertex_position + vec4(0,0,0,scale); + return transform_projection * vertex_position + vec4(0.,0.,0.,scale); } #endif \ No newline at end of file diff --git a/Cryptid/assets/shaders/mosaic.fs b/Cryptid/assets/shaders/mosaic.fs index dd3ea25..4130e5c 100644 --- a/Cryptid/assets/shaders/mosaic.fs +++ b/Cryptid/assets/shaders/mosaic.fs @@ -145,6 +145,6 @@ vec4 position( mat4 transform_projection, vec4 vertex_position ) float scale = 0.2*(-0.03 - 0.3*max(0., 0.3-mid_dist)) *hovering*(length(mouse_offset)*length(mouse_offset))/(2. -mid_dist); - return transform_projection * vertex_position + vec4(0,0,0,scale); + return transform_projection * vertex_position + vec4(0.,0.,0.,scale); } #endif \ No newline at end of file diff --git a/Cryptid/assets/shaders/noisy.fs b/Cryptid/assets/shaders/noisy.fs index 6ccfc37..6b73ae0 100644 --- a/Cryptid/assets/shaders/noisy.fs +++ b/Cryptid/assets/shaders/noisy.fs @@ -88,6 +88,6 @@ vec4 position( mat4 transform_projection, vec4 vertex_position ) float scale = 0.2*(-0.03 - 0.3*max(0., 0.3-mid_dist)) *hovering*(length(mouse_offset)*length(mouse_offset))/(2. -mid_dist); - return transform_projection * vertex_position + vec4(0,0,0,scale); + return transform_projection * vertex_position + vec4(0.,0.,0.,scale); } #endif \ No newline at end of file diff --git a/Cryptid/assets/shaders/oversat.fs b/Cryptid/assets/shaders/oversat.fs index 090a388..5a9d9c7 100644 --- a/Cryptid/assets/shaders/oversat.fs +++ b/Cryptid/assets/shaders/oversat.fs @@ -222,6 +222,6 @@ vec4 position( mat4 transform_projection, vec4 vertex_position ) float scale = 0.2*(-0.03 - 0.3*max(0., 0.3-mid_dist)) *hovering*(length(mouse_offset)*length(mouse_offset))/(2. -mid_dist); - return transform_projection * vertex_position + vec4(0,0,0,scale); + return transform_projection * vertex_position + vec4(0.,0.,0.,scale); } #endif diff --git a/Cryptid/assets/shaders/ultrafoil.fs b/Cryptid/assets/shaders/ultrafoil.fs new file mode 100644 index 0000000..1fc68e9 --- /dev/null +++ b/Cryptid/assets/shaders/ultrafoil.fs @@ -0,0 +1,157 @@ +#if defined(VERTEX) || __VERSION__ > 100 || defined(GL_FRAGMENT_PRECISION_HIGH) + #define MY_HIGHP_OR_MEDIUMP highp +#else + #define MY_HIGHP_OR_MEDIUMP mediump +#endif + + +extern MY_HIGHP_OR_MEDIUMP vec2 ultrafoil; +extern MY_HIGHP_OR_MEDIUMP number dissolve; +extern MY_HIGHP_OR_MEDIUMP number time; +extern MY_HIGHP_OR_MEDIUMP vec4 texture_details; +extern MY_HIGHP_OR_MEDIUMP vec2 image_details; +extern bool shadow; +extern MY_HIGHP_OR_MEDIUMP vec4 burn_colour_1; +extern MY_HIGHP_OR_MEDIUMP vec4 burn_colour_2; + +vec4 dissolve_mask(vec4 tex, vec2 texture_coords, vec2 uv) +{ + if (dissolve < 0.001) { + return vec4(shadow ? vec3(0.,0.,0.) : tex.xyz, shadow ? tex.a*0.3: tex.a); + } + + float adjusted_dissolve = (dissolve*dissolve*(3. - 2. * dissolve)) * 1.02 - 0.01; //Adjusting 0.0-1.0 to fall to -0.1 - 1.1 scale so the mask does not pause at extreme values + + float t = time * 10.0 + 2003.; + vec2 floored_uv = (floor((uv*texture_details.ba)))/max(texture_details.b, texture_details.a); + vec2 uv_scaled_centered = (floored_uv - 0.5) * 2.3 * max(texture_details.b, texture_details.a); + + vec2 field_part1 = uv_scaled_centered + 50.*vec2(sin(-t / 143.6340), cos(-t / 99.4324)); + vec2 field_part2 = uv_scaled_centered + 50.*vec2(cos( t / 53.1532), cos( t / 61.4532)); + vec2 field_part3 = uv_scaled_centered + 50.*vec2(sin(-t / 87.53218), sin(-t / 49.0000)); + + float field = (1.+ ( + cos(length(field_part1) / 19.483) + sin(length(field_part2) / 33.155) * cos(field_part2.y / 15.73) + + cos(length(field_part3) / 27.193) * sin(field_part3.x / 21.92) ))/2.; + vec2 borders = vec2(0.2, 0.8); + + float res = (.5 + .5* cos( (adjusted_dissolve) / 82.612 + ( field + -.5 ) *3.14)) + - (floored_uv.x > borders.y ? (floored_uv.x - borders.y)*(5. + 5.*dissolve) : 0.)*(dissolve) + - (floored_uv.y > borders.y ? (floored_uv.y - borders.y)*(5. + 5.*dissolve) : 0.)*(dissolve) + - (floored_uv.x < borders.x ? (borders.x - floored_uv.x)*(5. + 5.*dissolve) : 0.)*(dissolve) + - (floored_uv.y < borders.x ? (borders.x - floored_uv.y)*(5. + 5.*dissolve) : 0.)*(dissolve); + + if (tex.a > 0.01 && burn_colour_1.a > 0.01 && !shadow && res < adjusted_dissolve + 0.8*(0.5-abs(adjusted_dissolve-0.5)) && res > adjusted_dissolve) { + if (!shadow && res < adjusted_dissolve + 0.5*(0.5-abs(adjusted_dissolve-0.5)) && res > adjusted_dissolve) { + tex.rgba = burn_colour_1.rgba; + } else if (burn_colour_2.a > 0.01) { + tex.rgba = burn_colour_2.rgba; + } + } + + return vec4(shadow ? vec3(0.,0.,0.) : tex.xyz, res > adjusted_dissolve ? (shadow ? tex.a*0.3: tex.a) : .0); +} + +number hue(number s, number t, number h) +{ + number hs = mod(h, 1.)*6.; + if (hs < 1.) return (t-s) * hs + s; + if (hs < 3.) return t; + if (hs < 4.) return (t-s) * (4.-hs) + s; + return s; +} + +vec4 RGB(vec4 c) +{ + if (c.y < 0.0001) + return vec4(vec3(c.z), c.a); + + number t = (c.z < .5) ? c.y*c.z + c.z : -c.y*c.z + (c.y+c.z); + number s = 2.0 * c.z - t; + return vec4(hue(s,t,c.x + 1./3.), hue(s,t,c.x), hue(s,t,c.x - 1./3.), c.w); +} + +vec4 HSL(vec4 c) +{ + number low = min(c.r, min(c.g, c.b)); + number high = max(c.r, max(c.g, c.b)); + number delta = high - low; + number sum = high+low; + + vec4 hsl = vec4(.0, .0, .5 * sum, c.a); + if (delta == .0) + return hsl; + + hsl.y = (hsl.z < .5) ? delta / sum : delta / (2.0 - sum); + + if (high == c.r) + hsl.x = (c.g - c.b) / delta; + else if (high == c.g) + hsl.x = (c.b - c.r) / delta + 2.0; + else + hsl.x = (c.r - c.g) / delta + 4.0; + + hsl.x = mod(hsl.x / 6., 1.); + return hsl; +} + +vec4 effect( vec4 colour, Image texture, vec2 texture_coords, vec2 screen_coords ) +{ + vec4 tex = Texel( texture, texture_coords); + vec2 uv = (((texture_coords)*(image_details)) - texture_details.xy*texture_details.ba)/texture_details.ba; + vec2 adjusted_uv = uv - vec2(0.5, 0.5); + adjusted_uv.x = adjusted_uv.x*texture_details.b/texture_details.a; + + number low = min(tex.r, min(tex.g, tex.b)); + number high = max(tex.r, max(tex.g, tex.b)); + number delta = min(high, max(0.5, 1. - low)); + + /* + //number fac = max(min(2.*sin((length(90.*adjusted_uv) + ultrafoil.r*2.) + 3.*(1.+0.8*cos(length(113.1121*adjusted_uv) - ultrafoil.r*3.121))) - 1. - max(5.-length(90.*adjusted_uv), 0.), 1.), 0.); + number fac = 0.8 + 0.5*sin(23.*uv.x+.37*uv.y + ultrafoil.r*12. + cos(ultrafoil.r*5.3 + uv.y*4.2 - uv.x*4.)); + number fac2 = 0.25 + 0.25*sin(20.*uv.x+.6*uv.y + ultrafoil.r*5. - cos(ultrafoil.r*2.3 + uv.y*8.2)); + number fac3 = 0.5 + 0.2*sin(32.*uv.x+.26*uv.y + ultrafoil.r*6.111 + sin(ultrafoil.r*5.3 + uv.y*3.2)); + number fac4 = 0.25 + 0.1*sin(10.*uv.x+.32*uv.y + ultrafoil.r*8.111 + sin(ultrafoil.r*1.3 + uv.y*13.2)); + number fac5 = sin(0.5*16.*uv.x+.16*uv.y + ultrafoil.r*12. + cos(ultrafoil.r*5.3 + uv.y*4.2 - uv.x*4.)); + + number maxfac = max(max(fac, max(fac2, max(fac3, max(fac4, 0.0)))) + 2.2*(fac+fac2+fac3+fac4), 0.); + + vec3 facv = vec3( + fac+fac2, + max(fac4+fac5,fac2+fac3), + fac+fac3+fac5 + );*/ + vec3 fac = vec3(0.0); + fac += vec3(0.2,0.4,0.7)*(sin(4.0*uv.x + ultrafoil.r*4.0 + cos(ultrafoil.r*5.3))+.5); + fac += vec3(0.5,0.1,0.7)*(sin(6.0*uv.x + ultrafoil.r*6.3 + cos(ultrafoil.r*2.))+.5); + fac += max(vec3(0.7,0.2,0.2)*(1.-pow(uv.x*10.0-10.0 + ultrafoil.r*2.3,2.)), vec3(0.)); + fac += max(vec3(0.5,0.3,0.6)*(1.-pow(uv.x*40.0-40.0 + ultrafoil.r*15.3,2.)), vec3(0.)); + fac += max(vec3(0.7,0.2,0.2)*(1.-pow(uv.x*10.0-20.0 + ultrafoil.r*3.7,2.)), vec3(0.)); + fac += max(vec3(0.5,0.3,0.6)*(1.-pow(uv.x*40.0-50.0 + ultrafoil.r*11.8,2.)), vec3(0.)); + fac += sqrt(uv.y*0.2); + + tex.rgb *= vec3(0.5,0.7,1.0); + tex.rgb += tex.rgb*fac*0.5; + //tex.a = min(tex.a, 0.3*tex.a + 0.9*min(0.5, maxfac*0.1)); + + return dissolve_mask(tex, texture_coords, uv); +} + +extern MY_HIGHP_OR_MEDIUMP vec2 mouse_screen_pos; +extern MY_HIGHP_OR_MEDIUMP float hovering; +extern MY_HIGHP_OR_MEDIUMP float screen_scale; + +#ifdef VERTEX +vec4 position( mat4 transform_projection, vec4 vertex_position ) +{ + if (hovering <= 0.){ + return transform_projection * vertex_position; + } + float mid_dist = length(vertex_position.xy - 0.5*love_ScreenSize.xy)/length(love_ScreenSize.xy); + vec2 mouse_offset = (vertex_position.xy - mouse_screen_pos.xy)/screen_scale; + float scale = 0.2*(-0.03 - 0.3*max(0., 0.3-mid_dist)) + *hovering*(length(mouse_offset)*length(mouse_offset))/(2. -mid_dist); + + return transform_projection * vertex_position + vec4(0.,0.,0.,scale); +} +#endif \ No newline at end of file diff --git a/Cryptid/assets/sounds/demitrigger.ogg b/Cryptid/assets/sounds/demitrigger.ogg new file mode 100644 index 0000000..df5f2ad Binary files /dev/null and b/Cryptid/assets/sounds/demitrigger.ogg differ diff --git a/Cryptid/assets/sounds/forcetrigger.ogg b/Cryptid/assets/sounds/forcetrigger.ogg new file mode 100644 index 0000000..8e8595f Binary files /dev/null and b/Cryptid/assets/sounds/forcetrigger.ogg differ diff --git a/Cryptid/config.lua b/Cryptid/config.lua index ebd9c6f..d1b7457 100644 --- a/Cryptid/config.lua +++ b/Cryptid/config.lua @@ -1,14 +1,14 @@ return { ["Cryptid"] = { - ["jimball_music"] = true, - ["code_music"] = true, - ["exotic_music"] = true, - ["big_music"] = true, - ["alt_bg_music"] = true, + ["jimball_music"] = true, -- plays funkytown when jimball + ["code_music"] = true, -- plays code music when code pack + ["exotic_music"] = true, -- plays exotic music when exotic joker + ["big_music"] = true, -- plays music when sufficiently high score + ["alt_bg_music"] = true, -- plays alternate title screen music based on gameset }, - ["family_mode"] = false, - ["experimental"] = false, - ["force_tooltips"] = true, - ["HTTPS"] = true, - ["menu"] = true, + ["family_mode"] = false, -- removes f*ck + ["experimental"] = false, -- experimental stuff + ["force_tooltips"] = true, -- i don't actually know what this does + ["HTTPS"] = true, -- your internet connection + ["menu"] = true, -- i don't know what this does either } diff --git a/Cryptid/items/achievement.lua b/Cryptid/items/achievement.lua index a8aeb51..dcfe336 100644 --- a/Cryptid/items/achievement.lua +++ b/Cryptid/items/achievement.lua @@ -423,6 +423,38 @@ local pin = { end end, } +local technically_positive = { + object_type = "Achievement", + key = "technically_positive", + order = 23, + bypass_all_unlocked = true, + atlas = "cry_achievements", + --reset_on_startup = true, + unlock_condition = function(self, args) + if args.type == "modify_jokers" then + for i = 1, #G.jokers.cards do + if + G.jokers.cards[i].config.center.key == "j_cry_negative" + and (G.jokers.cards[i].edition and G.jokers.cards[i].edition.negative) + then + return true + end + end + end + end, +} + +-- local stoned = { +-- object_type = "Achievement", +-- key = "stoned", +-- order = 24, +-- bypass_all_unlocked = true, +-- atlas = "cry_achievements", +-- --reset_on_startup = true, +-- unlock_condition = function(self, args) + +-- end, +-- } -- TODO: Add new Achievements. -- Current Ideas (Normal): @@ -477,6 +509,7 @@ local achievement_objects = { home_realtor, traffic_jam, perfectly_balanced, + technically_positive, --pin, Needs to be screened } return { name = "Achievements", items = achievement_objects } diff --git a/Cryptid/items/blind.lua b/Cryptid/items/blind.lua index 902f0e3..983cd75 100644 --- a/Cryptid/items/blind.lua +++ b/Cryptid/items/blind.lua @@ -11,6 +11,7 @@ local oldox = { boss = { min = 2, max = 10, + yes_orb = true, }, atlas = "nostalgia", order = 4, @@ -36,6 +37,7 @@ local oldhouse = { boss = { min = 3, max = 10, + yes_orb = true, }, atlas = "nostalgia", order = 5, @@ -64,6 +66,7 @@ local oldarm = { boss = { min = 3, max = 10, + yes_orb = true, }, atlas = "nostalgia", order = 6, @@ -92,6 +95,7 @@ local oldfish = { boss = { min = 2, max = 10, + yes_orb = true, }, atlas = "nostalgia", order = 7, @@ -117,6 +121,7 @@ local oldmanacle = { boss = { min = 1, max = 10, + yes_orb = true, }, atlas = "nostalgia", order = 8, @@ -142,6 +147,7 @@ local oldserpent = { boss = { min = 5, max = 10, + yes_orb = true, }, atlas = "nostalgia", order = 9, @@ -167,6 +173,7 @@ local oldpillar = { boss = { min = 3, max = 10, + yes_orb = true, }, atlas = "nostalgia", order = 10, @@ -195,6 +202,7 @@ local oldflint = { boss = { min = 3, max = 10, + yes_orb = true, }, atlas = "nostalgia", order = 11, @@ -223,6 +231,7 @@ local oldmark = { boss = { min = 4, max = 10, + yes_orb = true, }, atlas = "nostalgia", order = 12, @@ -249,14 +258,15 @@ local tax = { key = "tax", pos = { x = 0, y = 0 }, boss = { - min = 1, + min = 2, max = 10, + yes_orb = true, }, atlas = "blinds", order = 2, boss_colour = HEX("40ff40"), loc_vars = function(self, info_queue, card) - return { vars = { 0.4 * get_blind_amount(G.GAME.round_resets.ante) * 2 * G.GAME.starting_params.ante_scaling } } -- no bignum? + return { vars = { 0.4 * get_blind_amount(G.GAME.round_resets.ante) * 2 * G.GAME.starting_params.ante_scaling } } end, preview_ui = function(self) local value = self:loc_vars().vars[1] @@ -283,8 +293,14 @@ local tax = { collection_loc_vars = function(self) return { vars = { localize("cry_tax_placeholder") } } end, - cry_cap_score = function(self, score) - return math.floor(math.min(0.4 * G.GAME.blind.chips, score) + 0.5) + set_blind = function(self, reset, silent) + SMODS.set_scoring_calculation("cry_tax") + end, + defeat = function(self, silent) + SMODS.set_scoring_calculation("multiply") + end, + disable = function(self, silent) + SMODS.set_scoring_calculation("multiply") end, in_pool = function() return G.GAME.round_resets.hands >= 3 @@ -303,6 +319,7 @@ local box = { boss = { min = 1, max = 10, + yes_orb = true, }, atlas = "blinds", order = 13, @@ -327,8 +344,9 @@ local clock = { pos = { x = 0, y = 1 }, mult = 0, boss = { - min = 1, + min = 2, max = 10, + yes_orb = true, }, config = { tw_bl = { @@ -348,8 +366,10 @@ local clock = { cry_ante_base_mod = function(self, dt) if G.SETTINGS.paused then return 0 + elseif G.GAME.round == 0 and G.GAME.skips == 0 then + return 0 else - return 0.1 * (dt * math.min(G.SETTINGS.GAMESPEED, 4) / 4) / 3 + return 0.1 * ((dt * (G.GAME.modifiers.cry_rush_hour_iii or 1)) * math.min(G.SETTINGS.GAMESPEED, 4) / 4) / 3 end end, } @@ -366,6 +386,7 @@ local trick = { boss = { min = 1, max = 10, + yes_orb = true, }, atlas = "blinds", order = 14, @@ -402,6 +423,7 @@ local joke = { boss = { min = 1, max = 10, + yes_orb = true, }, atlas = "blinds", order = 15, @@ -449,6 +471,7 @@ local hammer = { boss = { min = 2, max = 10, + yes_orb = true, }, atlas = "blinds", order = 19, @@ -457,6 +480,7 @@ local hammer = { if card.area ~= G.jokers and not G.GAME.blind.disabled then if not SMODS.has_no_rank(card) + and not SMODS.has_enhancement(card, "m_cry_abstract") and ( card.base.value == "3" or card.base.value == "5" @@ -484,6 +508,7 @@ local magic = { boss = { min = 2, max = 10, + yes_orb = true, }, atlas = "blinds", order = 20, @@ -492,6 +517,7 @@ local magic = { if card.area ~= G.jokers and not G.GAME.blind.disabled then if not SMODS.has_no_rank(card) + and not SMODS.has_enhancement(card, "m_cry_abstract") and ( card.base.value == "2" or card.base.value == "4" @@ -519,6 +545,7 @@ local windmill = { boss = { min = 4, max = 10, + yes_orb = true, }, atlas = "blinds", order = 16, @@ -543,6 +570,7 @@ local striker = { boss = { min = 4, max = 10, + yes_orb = true, }, atlas = "blinds", order = 1, @@ -567,6 +595,7 @@ local shackle = { boss = { min = 1, max = 10, + yes_orb = true, }, atlas = "blinds", order = 18, @@ -601,6 +630,7 @@ local pin = { boss = { min = 4, max = 10, + yes_orb = true, }, atlas = "blinds", order = 17, @@ -617,10 +647,10 @@ local pin = { (card.area == G.jokers) and not G.GAME.blind.disabled and ( - card.config.center.rarity ~= 3 - and card.config.center.rarity ~= 2 - and card.config.center.rarity ~= 1 - and card.config.center.rarity ~= 5 + card.config.center.rarity == 4 + or card.config.center.rarity == "cry_epic" + or card.config.center.rarity == "cry_exotic" + or Cryptid.pin_debuff[card.config.center.rarity] ) then return true @@ -640,10 +670,11 @@ local scorch = { object_type = "Blind", name = "cry-scorch", key = "scorch", - pos = { x = 0, y = 18 }, -- use Trick as placeholder icon + pos = { x = 0, y = 18 }, boss = { min = 1, max = 10, + yes_orb = true, }, atlas = "blinds", order = 21, @@ -659,11 +690,11 @@ local scorch = { and (context.cardarea == G.play or context.cardarea == "unscored") and not G.GAME.blind.disabled then - return { remove = not context.destroy_card.ability.eternal } + return { remove = not SMODS.is_eternal(context.destroying_card) } end if context.discard and not G.GAME.blind.disabled then for i, card in ipairs(G.hand.highlighted) do - return { remove = not card.ability.eternal } + return { remove = not SMODS.is_eternal(card) } end end end, @@ -675,6 +706,285 @@ local scorch = { end end, } +-- +0.25X blind requirements +-- for every $5 you have when selected +local greed = { + dependencies = { + items = { + "set_cry_blind", + }, + }, + config = { + money_factor = 5, + blind_mod = 0.25, + max_scale = 5000, + }, + object_type = "Blind", + name = "cry-greed", + key = "greed", + pos = { x = 0, y = 19 }, -- use Tax as placeholder icon + boss = { + min = 1, + max = 10, + yes_orb = true, + }, + atlas = "blinds", + order = 22, + boss_colour = HEX("C19030"), + mult = 1, + loc_vars = function(self, info_queue, card) + return { + vars = { + number_format(5), + number_format(lenient_bignum((get_blind_amount(G.GAME.round_resets.ante) * 0.25))), + }, + } + end, + collection_loc_vars = function(self) + return { + vars = { + number_format(5), + "(" .. number_format(0.25) .. "X base)", + }, + } + end, + set_blind = function(self, reset, silent) + if to_big(G.GAME.dollars) > to_big(0) then + if to_big(G.GAME.dollars) < to_big(5000) then + G.GAME.blind.chips = -- go my equations + ((get_blind_amount(G.GAME.round_resets.ante) * G.GAME.starting_params.ante_scaling) + (math.floor( + G.GAME.dollars / 5 + ) * (get_blind_amount(G.GAME.round_resets.ante) * 0.25))) + else + G.GAME.blind.chips = -- set cap at $5000 + ( + (get_blind_amount(G.GAME.round_resets.ante) * G.GAME.starting_params.ante_scaling) + + ( + math.floor(5000 / 5) -- 1000 extra increments + * (get_blind_amount(G.GAME.round_resets.ante) * 0.25) + ) + ) + end + G.GAME.blind.chip_text = number_format(G.GAME.blind.chips) + end + end, + disable = function(self, silent) + G.GAME.blind.chips = get_blind_amount(G.GAME.round_resets.ante) * G.GAME.starting_params.ante_scaling + G.GAME.blind.chip_text = number_format(G.GAME.blind.chips) + end, +} +--Fasten all jokers after hand or discard +--After defeat, open a baneful buffoon pack containing: +---4 cursed jokers (can overflow) +---a "unique consumeable" that will banish the rightmost joker +--Only after that, are jokers unfastened +local decision = { + dependencies = { + items = { + "set_cry_blind", + "set_cry_cursed", + }, + }, + mult = 2, + object_type = "Blind", + name = "cry-Decision", + key = "decision", + pos = { x = 0, y = 20 }, + dollars = 5, + boss = { + min = 4, + max = 666666, + yes_orb = true, + }, + atlas = "blinds", + order = 23, + boss_colour = HEX("474931"), + get_loc_debuff_text = function(self) + return localize("cry_blind_baneful_pack") + end, + calculate = function(self, blind, context) + if context.discard and not G.GAME.blind.disabled and not G.GAME.cry_fastened then + --visual cue to wiggle all jokers + G.GAME.cry_fastened = true + if G.jokers.cards then + G.GAME.blind:wiggle() + G.GAME.blind.triggered = true + for i, v in pairs(G.jokers.cards) do + v:juice_up(0, 0.25) + end + end + end + end, + cry_before_play = function(self) + if not G.GAME.blind.disabled and not G.GAME.cry_fastened then + --visual cue to wiggle all jokers + G.GAME.cry_fastened = true + if G.jokers.cards then + G.GAME.blind:wiggle() + G.GAME.blind.triggered = true + for i, v in pairs(G.jokers.cards) do + v:juice_up(0, 0.25) + end + end + end + end, + cry_before_cash = function(self) + --Always fasten if before cash context (gaming chair, debug mode) + G.GAME.cry_fastened = true + G.GAME.blind:wiggle() + G.GAME.blind.triggered = true + G.GAME.cry_make_a_decision = true + G.E_MANAGER:add_event(Event({ + trigger = "before", + func = function() + local key = "p_cry_baneful_1" + local card = Card( + G.play.T.x + G.play.T.w / 2 - G.CARD_W * 1.27 / 2, + G.play.T.y + G.play.T.h / 2 - G.CARD_H * 1.27 / 2, + G.CARD_W * 1.27, + G.CARD_H * 1.27, + G.P_CARDS.empty, + G.P_CENTERS[key], + { bypass_discovery_center = true, bypass_discovery_ui = true } + ) + card.cost = 0 + card.from_tag = true + G.FUNCS.use_card({ config = { ref_table = card } }) + card:start_materialize() + pack_opened = true + return true + end, + })) + end, + disable = function(self, silent) + G.GAME.cry_fastened = nil + end, + defeat = function(self, silent) + G.GAME.cry_fastened = nil + end, +} + +local repulsor = { + dependencies = { + items = { + "set_cry_blind", + }, + }, + mult = 2, + object_type = "Blind", + name = "cry-repulsor", + key = "repulsor", + pos = { x = 0, y = 0 }, + dollars = 5, + boss = { + min = 4, + max = 666666, + yes_orb = true, + }, + atlas = "blinds_two", + order = 24, + boss_colour = HEX("7c5798"), + calculate = function(self, blind, context) + if not G.GAME.blind.disabled then + if context.before then + for i, v in pairs(G.jokers.cards) do + if v ~= G.jokers.cards[1] and v ~= G.jokers.cards[#G.jokers.cards] then + if not v.debuff then + G.GAME.blind.triggered = true + v.debuff = true + v.debuff_from_repulsor = true + end + end + end + end + if context.retrigger_joker_check and not context.retrigger_joker then + if context.other_card == G.jokers.cards[1] or context.other_card == G.jokers.cards[#G.jokers.cards] then + return { + repetitions = 1, + } + end + end + if context.after then + for i, v in pairs(G.jokers.cards) do + if v.debuff_from_repulsor then + v.debuff = nil + v.debuff_from_repulsor = true + end + end + end + end + end, +} + +local chromatic = { + dependencies = { + items = { + "set_cry_blind", + }, + }, + mult = 2, + object_type = "Blind", + name = "cry-chromatic", + key = "chromatic", + pos = { x = 0, y = 1 }, + dollars = 5, + boss = { + min = 1, + max = 666666, + yes_orb = true, + }, + atlas = "blinds_two", + order = 25, + boss_colour = HEX("a34f98"), + cry_modify_score = function(self, score) + if math.floor(G.GAME.current_round.hands_played + 1) % 2 == 1 then + return score * -1 + else + return score + end + end, +} + +local landlord = { + dependencies = { + items = { + "set_cry_blind", + }, + }, + mult = 2, + object_type = "Blind", + name = "cry-landlord", + key = "landlord", + pos = { x = 0, y = 2 }, + dollars = 5, + boss = { + min = 4, + max = 666666, + yes_orb = true, + }, + atlas = "blinds_two", + order = 26, + boss_colour = HEX("c89f13"), + debuff_hand = function(self, cards, hand, handname, check) + G.GAME.blind.triggered = false + local jokers = {} + for i, v in pairs(G.jokers.cards) do + if not v.ability.rental then + jokers[#jokers + 1] = v + end + end + if #jokers > 0 then + G.GAME.blind.triggered = true + if not check then + local joker = pseudorandom_element(jokers, pseudoseed("cry_landlord")) + joker:set_rental(true) + joker:juice_up() + G.GAME.blind:wiggle() + end + end + end, +} + --It seems Showdown blind order is seperate from normal blind collection order? convenient for me at least --Nvm they changed it local lavender_loop = { @@ -694,6 +1004,7 @@ local lavender_loop = { min = 3, max = 10, showdown = true, + yes_orb = true, }, atlas = "blinds", order = 91, @@ -708,22 +1019,20 @@ local lavender_loop = { G.GAME.cry_ach_conditions.patience_virtue_earnable = nil end, cry_round_base_mod = function(self, dt) + local aaa = 4 * (G.GAME.modifiers.cry_rush_hour_iii or 1) if G.GAME.cry_ach_conditions.patience_virtue_timer > 0 and G.GAME.cry_ach_conditions.patience_virtue_earnable ~= true then G.GAME.cry_ach_conditions.patience_virtue_timer = G.GAME.cry_ach_conditions.patience_virtue_timer - - dt - * (G.GAME.modifiers.cry_rush_hour_iii and 0.5 or 1) - * (G.SETTINGS.paused and 0 or 1) - * G.SETTINGS.GAMESPEED + - dt * (G.SETTINGS.paused and 0 or 1) * G.SETTINGS.GAMESPEED elseif G.GAME.current_round.hands_played == 0 then G.GAME.cry_ach_conditions.patience_virtue_earnable = true end if G.SETTINGS.paused or G.STATE == G.STATES.HAND_PLAYED then return 1 else - return 1.25 ^ (dt / (1.5 / math.min(G.SETTINGS.GAMESPEED, 4) * 4)) + return 1.25 ^ (dt / (1.5 / math.min(G.SETTINGS.GAMESPEED, 4) * aaa)) end end, } @@ -748,7 +1057,7 @@ local tornado = { order = 94, boss_colour = HEX("3dd9ca"), loc_vars = function(self) - return { vars = { "" .. ((Cryptid.safe_get(G.GAME, "probabilities", "normal") or 1) * 2), 3 } } + return { vars = { SMODS.get_probability_vars(self, 2, 3, "Turquoise Tornado") } } end, set_blind = function(self, reset, silent) if not reset then @@ -759,12 +1068,12 @@ local tornado = { return #Cryptid.advanced_find_joker("Oops! All 6s", nil, nil, { "eternal" }, nil) == 0 end, collection_loc_vars = function(self) - return { vars = { "" .. ((Cryptid.safe_get(G.GAME, "probabilities", "normal") or 1) * 2), 3 } } + return { vars = { SMODS.get_probability_vars(self, 2, 3, "Turquoise Tornado") } } end, debuff_hand = function(self, cards, hand, handname, check) if not check - and (pseudorandom(pseudoseed("tornado")) < ((G.GAME.probabilities.normal * 2) / 3)) + and SMODS.pseudorandom_probability(self, "tornado", 2, 3, "Turquoise Tornado") and not G.GAME.blind.disabled then --check for guarantee @@ -797,34 +1106,40 @@ local vermillion_virus = { min = 3, max = 10, showdown = true, + yes_orb = true, }, atlas = "blinds", order = 90, boss_colour = HEX("f65d34"), cry_before_play = function(self) - if G.jokers.cards[1] then - local idx = pseudorandom(pseudoseed("cry_vermillion_virus"), 1, #G.jokers.cards) - if G.jokers.cards[idx] then - if G.jokers.cards[idx].config.center.immune_to_vermillion then - card_eval_status_text( - G.jokers.cards[idx], - "extra", - nil, - nil, - nil, - { message = localize("k_nope_ex"), colour = G.C.JOKER_GREY } - ) - else - _card = create_card("Joker", G.jokers, nil, nil, nil, nil, nil, "cry_vermillion_virus_gen") - G.jokers.cards[idx]:remove_from_deck() - _card:add_to_deck() - _card:start_materialize() - G.jokers.cards[idx] = _card - _card:set_card_area(G.jokers) - G.jokers:set_ranks() - G.jokers:align_cards() + local eligible_cards = {} + local idx + --Check for eligible cards (not eternal and not immune) + for i = 1, #G.jokers.cards do + if not G.jokers.cards[i].config.center.immune_to_vermillion and not SMODS.is_eternal(G.jokers.cards[i]) then + eligible_cards[#eligible_cards + 1] = G.jokers.cards[i] + end + end + if #eligible_cards ~= 0 then + --Choose 1 eligible card and get the position of it + local option = pseudorandom_element(eligible_cards, pseudoseed("cry_vermillion_virus")) + for i = 1, #G.jokers.cards do + if G.jokers.cards[i] == option then + idx = i + break end end + if idx and G.jokers.cards[idx] then + _card = create_card("Joker", G.jokers, nil, nil, nil, nil, nil, "cry_vermillion_virus_gen") + G.jokers.cards[idx]:start_dissolve() + --G.jokers.cards[idx]:remove_from_deck() + _card:add_to_deck() + _card:start_materialize() + G.jokers.cards[idx] = _card + _card:set_card_area(G.jokers) + G.jokers:set_ranks() + G.jokers:align_cards() + end end end, } @@ -843,18 +1158,22 @@ local sapphire_stamp = { min = 3, max = 10, showdown = true, + yes_orb = true, }, atlas = "blinds", order = 92, boss_colour = HEX("4057d6"), cry_before_play = function(self) - local idx = pseudorandom(pseudoseed("cry_sapphire_stamp"), 1, #G.hand.highlighted) - G.hand:remove_from_highlighted(G.hand.highlighted[idx]) + if #G.hand.highlighted > 0 then + local idx = pseudorandom(pseudoseed("cry_sapphire_stamp"), 1, #G.hand.highlighted) + G.hand:remove_from_highlighted(G.hand.highlighted[idx]) + end end, set_blind = function(self, reset, silent) if not reset then G.GAME.stamp_mod = true - G.hand.config.highlighted_limit = G.hand.config.highlighted_limit + 1 + SMODS.change_play_limit(1) + SMODS.change_discard_limit(1) end end, defeat = function(self, silent) @@ -862,7 +1181,8 @@ local sapphire_stamp = { G.GAME.stamp_mod = nil end if not G.GAME.blind.disabled then - G.hand.config.highlighted_limit = G.hand.config.highlighted_limit - 1 + SMODS.change_play_limit(-1) + SMODS.change_discard_limit(-1) end end, disable = function(self, silent) @@ -870,7 +1190,8 @@ local sapphire_stamp = { G.GAME.stamp_mod = nil end if not G.GAME.blind.disabled then - G.hand.config.highlighted_limit = G.hand.config.highlighted_limit - 1 + SMODS.change_play_limit(-1) + SMODS.change_discard_limit(-1) end end, } @@ -1233,7 +1554,7 @@ local obsidian_orb = { if area == G.hand then if s.name == "The Wheel" - and pseudorandom(pseudoseed("ObsidianOrb")) < G.GAME.probabilities.normal / 7 + and SMODS.pseudorandom_probability(self, "ObsidianOrb", 1, 7, "Obsidian Orb") then return true end @@ -1348,6 +1669,21 @@ local obsidian_orb = { end end end, + cry_before_cash = function(self) + local decision_made = false + for k, _ in pairs(G.GAME.defeated_blinds) do + s = G.P_BLINDS[k] + if s.cry_before_cash then + decision_made = true + s:cry_before_cash() + end + end + if not decision_made then + G.GAME.cry_make_a_decision = nil + G.STATE = G.STATES.ROUND_EVAL + G.STATE_COMPLETE = false + end + end, get_loc_debuff_text = function(self) if not G.GAME.blind.debuff_boss then return localize("cry_debuff_obsidian_orb") @@ -1406,6 +1742,7 @@ local trophy = { end end, } + local items_togo = { oldox, oldhouse, @@ -1427,6 +1764,8 @@ local items_togo = { shackle, pin, scorch, + greed, + repulsor, vermillion_virus, tornado, sapphire_stamp, @@ -1434,5 +1773,8 @@ local items_togo = { clock, lavender_loop, trophy, + decision, + chromatic, + landlord, } return { name = "Blinds", items = items_togo } diff --git a/Cryptid/items/challenge.lua b/Cryptid/items/challenge.lua index 41eba28..c8be43e 100644 --- a/Cryptid/items/challenge.lua +++ b/Cryptid/items/challenge.lua @@ -51,7 +51,9 @@ local ballin = { key = "ballin", order = 1, rules = { - custom = {}, + custom = { + { id = "cry_force_enhancement", value = "m_stone" }, + }, modifiers = { { id = "joker_slots", value = 3 }, }, @@ -66,20 +68,6 @@ local ballin = { restrictions = { banned_cards = { { id = "j_vampire" }, - { id = "c_magician" }, - { id = "c_empress" }, - { id = "c_heirophant" }, - { id = "c_lovers" }, - { id = "c_chariot" }, - { id = "c_justice" }, - { id = "c_devil" }, - { id = "c_tower" }, - { id = "c_cry_seraph" }, - { id = "c_familiar" }, - { id = "c_grim" }, - { id = "c_incantation" }, - { id = "c_cry_eclipse" }, - { id = "c_cry_class" }, }, banned_other = {}, }, @@ -128,10 +116,6 @@ local rush_hour_ii = { { id = "j_diet_cola" }, { id = "v_directors_cut" }, { id = "v_retcon" }, - { id = "j_cry_pickle" }, - { id = "v_cry_copies" }, - { id = "v_cry_tag_printer" }, - { id = "v_cry_clone_machine" }, }, banned_other = {}, }, @@ -145,7 +129,7 @@ local rush_hour_iii = { custom = { { id = "cry_rush_hour" }, { id = "cry_rush_hour_ii" }, - { id = "cry_rush_hour_iii" }, + { id = "cry_rush_hour_iii", value = 2 }, { id = "cry_no_tags" }, }, modifiers = {}, @@ -222,10 +206,6 @@ local rush_hour_iii = { { id = "j_diet_cola" }, { id = "v_directors_cut" }, { id = "v_retcon" }, - { id = "j_cry_pickle" }, - { id = "v_cry_copies" }, - { id = "v_cry_tag_printer" }, - { id = "v_cry_clone_machine" }, }, banned_other = {}, }, @@ -506,61 +486,18 @@ function Game:start_run(args) if G.GAME.modifiers.cry_no_consumables then G.GAME.joker_rate = 1e300 end + for i, v in pairs(G.handlist) do + if v == "cry_Declare0" then + d0 = true + end + end + if not d0 then + table.insert(G.handlist, 1, "cry_Declare0") + table.insert(G.handlist, 1, "cry_Declare1") + table.insert(G.handlist, 1, "cry_Declare2") + end + Cryptid.base_values = {} end ---Add banned cards when specific features/mods are enabled here ---TODO other mods -if (SMODS.Mods["jen"] or {}).can_load then - ballin.restrictions.banned_cards[#ballin.restrictions.banned_cards + 1] = { id = "c_jen_chance" } - ballin.restrictions.banned_cards[#ballin.restrictions.banned_cards + 1] = { id = "c_jen_token_tag_cry_bundle" } - ballin.restrictions.banned_cards[#ballin.restrictions.banned_cards + 1] = { id = "c_jen_reverse_magician" } - ballin.restrictions.banned_cards[#ballin.restrictions.banned_cards + 1] = { id = "c_jen_reverse_empress" } - ballin.restrictions.banned_cards[#ballin.restrictions.banned_cards + 1] = { id = "c_jen_reverse_heirophant" } - ballin.restrictions.banned_cards[#ballin.restrictions.banned_cards + 1] = { id = "c_jen_reverse_lovers" } - ballin.restrictions.banned_cards[#ballin.restrictions.banned_cards + 1] = { id = "c_jen_reverse_chariot" } - ballin.restrictions.banned_cards[#ballin.restrictions.banned_cards + 1] = { id = "c_jen_reverse_justice" } - ballin.restrictions.banned_cards[#ballin.restrictions.banned_cards + 1] = { id = "c_jen_reverse_devil" } - ballin.restrictions.banned_cards[#ballin.restrictions.banned_cards + 1] = { id = "c_jen_reverse_tower" } - ballin.restrictions.banned_cards[#ballin.restrictions.banned_cards + 1] = { id = "c_jen_reverse_star" } - ballin.restrictions.banned_cards[#ballin.restrictions.banned_cards + 1] = { id = "c_jen_reverse_moon" } - ballin.restrictions.banned_cards[#ballin.restrictions.banned_cards + 1] = { id = "c_jen_reverse_sun" } - ballin.restrictions.banned_cards[#ballin.restrictions.banned_cards + 1] = { id = "c_jen_reverse_world" } - rng.restrictions.banned_cards[#rng.restrictions.banned_cards + 1] = { id = "c_jen_jokerinatarot" } - rng.restrictions.banned_cards[#rng.restrictions.banned_cards + 1] = { id = "c_jen_token_tag_uncommon" } - rng.restrictions.banned_cards[#rng.restrictions.banned_cards + 1] = { id = "c_jen_token_tag_rare" } - rng.restrictions.banned_cards[#rng.restrictions.banned_cards + 1] = { id = "c_jen_token_tag_top_up" } - rng.restrictions.banned_cards[#rng.restrictions.banned_cards + 1] = { id = "c_jen_token_tag_cry_epic" } - rng.restrictions.banned_cards[#rng.restrictions.banned_cards + 1] = { id = "c_jen_wraith_ex" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = { id = "j_jen_shikigami" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = { id = "c_jen_token_tag_charm" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = { id = "c_jen_token_tag_meteor" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = { id = "c_jen_token_tag_buffoon" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = { id = "c_jen_token_tag_ethereal" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = { id = "c_jen_token_tag_cry_bundle" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = { id = "c_jen_reverse_magician" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = { id = "c_jen_reverse_empress" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = { id = "c_jen_reverse_heirophant" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = { id = "c_jen_reverse_lovers" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = { id = "c_jen_reverse_chariot" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = { id = "c_jen_reverse_justice" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = { id = "c_jen_reverse_devil" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = { id = "c_jen_reverse_tower" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = - { id = "c_jen_reverse_high_priestess" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = { id = "c_jen_reverse_emperor" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = { id = "c_jen_reverse_death" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = { id = "c_jen_reverse_star" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = { id = "c_jen_reverse_moon" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = { id = "c_jen_reverse_sun" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = { id = "c_jen_reverse_world" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = { id = "c_jen_reverse_judgement" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = { id = "c_jen_mischief" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = { id = "c_jen_wonder" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = { id = "c_jen_familiar_ex" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = { id = "c_jen_grim_ex" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = { id = "c_jen_incantation_ex" } - onlycard.restrictions.banned_cards[#onlycard.restrictions.banned_cards + 1] = { id = "c_jen_cryptid_ex" } -end ---end of banned cards local challenges = { sticker_sheet, sticker_sheet_plus, diff --git a/Cryptid/items/code.lua b/Cryptid/items/code.lua index ca401a3..a8b70e1 100644 --- a/Cryptid/items/code.lua +++ b/Cryptid/items/code.lua @@ -1,4 +1,3 @@ ---note to self: refer to https://docs.google.com/document/d/1LNaIouU3vrtWIuPBdFCqLyjYAjVtq7t64xjHnckEY50/edit for order of remaining consumables local code = { object_type = "ConsumableType", key = "Code", @@ -7,10 +6,11 @@ local code = { collection_rows = { 4, 4 }, -- 4 pages for all code cards shop_rate = 0.0, loc_txt = {}, - default = (SMODS.Mods["jen"] or {}).can_load and "c_cry_oboe" or "c_cry_crash", + default = "c_cry_crash", can_stack = true, can_divide = true, } + local code_digital_hallucinations_compat = { colour = HEX("14b341"), loc_key = "cry_plus_code", @@ -21,6 +21,7 @@ local code_digital_hallucinations_compat = { G.consumeables:emplace(ccard) end, } +-- Program Pack, 1/2 local pack1 = { cry_credits = { idea = { @@ -45,7 +46,7 @@ local pack1 = { pos = { x = 0, y = 0 }, config = { extra = 2, choose = 1 }, cost = 4, - order = 1, + order = 805, weight = 0.96, create_card = function(self, card) return create_card("Code", G.pack_cards, nil, nil, true, true, nil, "cry_program_1") @@ -65,6 +66,7 @@ local pack1 = { group_key = "k_cry_program_pack", cry_digital_hallucinations = code_digital_hallucinations_compat, } +-- Program Pack Alt, 1/2 local pack2 = { cry_credits = { idea = { @@ -89,7 +91,7 @@ local pack2 = { pos = { x = 1, y = 0 }, config = { extra = 2, choose = 1 }, cost = 4, - order = 2, + order = 806, weight = 0.96, create_card = function(self, card) return create_card("Code", G.pack_cards, nil, nil, true, true, nil, "cry_program_2") @@ -109,6 +111,7 @@ local pack2 = { group_key = "k_cry_program_pack", cry_digital_hallucinations = code_digital_hallucinations_compat, } +-- Jumbo Program Pack, 1/4 local packJ = { cry_credits = { idea = { @@ -133,7 +136,7 @@ local packJ = { pos = { x = 2, y = 0 }, config = { extra = 4, choose = 1 }, cost = 6, - order = 3, + order = 807, weight = 0.48, create_card = function(self, card) return create_card("Code", G.pack_cards, nil, nil, true, true, nil, "cry_program_j") @@ -153,6 +156,7 @@ local packJ = { group_key = "k_cry_program_pack", cry_digital_hallucinations = code_digital_hallucinations_compat, } +-- Mega Program Pack, 2/4 local packM = { cry_credits = { idea = { @@ -177,7 +181,7 @@ local packM = { pos = { x = 3, y = 0 }, config = { extra = 4, choose = 2 }, cost = 8, - order = 4, + order = 808, weight = 0.12, create_card = function(self, card) return create_card("Code", G.pack_cards, nil, nil, true, true, nil, "cry_program_m") @@ -197,6 +201,8 @@ local packM = { group_key = "k_cry_program_pack", cry_digital_hallucinations = code_digital_hallucinations_compat, } +-- Console Tag +-- Gives a free Program Pack local console = { cry_credits = { idea = { @@ -212,12 +218,13 @@ local console = { dependencies = { items = { "p_cry_code_normal_1", + "set_cry_code", }, }, object_type = "Tag", atlas = "tag_cry", name = "cry-Console Tag", - order = 26, + order = 609, pos = { x = 3, y = 2 }, config = { type = "new_blind_choice" }, key = "console", @@ -256,6 +263,8 @@ local console = { end end, } +-- ://Crash +-- 1/6 to ACE, otherwise crash; determined by run seed rather than current seed local crash = { cry_credits = { idea = { @@ -278,10 +287,10 @@ local crash = { name = "cry-Crash", key = "crash", pos = { x = 7, y = 0 }, - config = {}, + no_collection = true, cost = 4, atlas = "atlasnotjokers", - order = 1, + order = 400, can_use = function(self, card) return true end, @@ -295,6 +304,10 @@ local crash = { local f = pseudorandom_element(crashes, pseudoseed("cry_crash")) f(self, card, area, copier) end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, init = function(self) function create_UIBox_crash(card) G.E_MANAGER:add_event(Event({ @@ -373,27 +386,31 @@ local crash = { --by WilsonTheWolf and MathIsFun_, funky error screen with random funny message messages = { "Oops.", + not Cryptid_config.family_mode and "Why don't you buy more jonkers? Are you stupid?" or "Oops.", + not Cryptid_config.family_mode and "Peter? What are you doing? Cards. WHAT THE FUCK?" or "Oops.", + not Cryptid_config.family_mode + and "what if instead of rush hour it was called kush hour and you just smoked a massive blunt" + or "Oops.", + not Cryptid_config.family_mode and "you are an idiot" or "Oops.", + not Cryptid_config.family_mode and "fuck you" or "Oops.", + not Cryptid_config.family_mode and "Nah fuck off" or "Oops.", "Your cards have been TOASTED, extra crispy for your pleasure.", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "What we have here is a certified whoopsidaisy", - "Why don't you buy more jonkers? Are you stupid?", "lmao", "How about a game of YOU MUST DIE?", "Sorry, I was in the bathroom. What'd I mi'Where'd... Where is everyone?", - "Peter? What are you doing? Cards. WHAT THE FUCK?", "what if it was called freaklatro", "4", "I SAWED THIS GAME IN HALF!", "is this rush hour 4", "You missed a semicolon on line 19742, you buffoon", - "you are an idiot", "You do not recognise the cards in the deck.", ":( Your P", "Assertion failed", "Play ULTRAKILL", "Play Nova Drift", "Play Balatro- wait", - "what if instead of rush hour it was called kush hour and you just smoked a massive blunt", "death.fell.accident.water", "Balatro's innards were made outards", "i am going to club yrou", @@ -407,7 +424,6 @@ local crash = { "I'm never going back this casino agai-", "what did you think would happen?", "DO THE EARTHQUAKE! [screams]", - "fuck you", "Screaming in the casino prank! AAAAAAAAAAAAAAAAAA", "https://www.youtube.com/watch?v=dQw4w9WgXcQ", "You musn't tear or crease it.", @@ -419,7 +435,6 @@ local crash = { "Looks like a skill issue to me.", "it turns out that card was ligma", "YouJustLostTheCasinoGame", - "Nah fuck off", "attempt to call global your_mom (value too large)", "Killed by intentional game design", "attempt to index field 'attempt to call global to_big (too big)' (a nil value)", @@ -430,6 +445,7 @@ local crash = { "[recursion]", "://SHART", "It's converging time.", + "Demitrigger!", "This is the last error message.", } function corruptString(str) @@ -834,6 +850,110 @@ local crash = { } end, } +-- ://Keygen, +-- Create a Perishable Banana voucher, destroy the previous Keygen voucher if exists +local keygen = { + cry_credits = { + idea = { + "HexaCryonic", + }, + art = { + "HexaCryonic", + }, + code = { + "SMG9000", + }, + }, + dependencies = { + items = { + "set_cry_code", + }, + }, + object_type = "Consumable", + set = "Code", + name = "cry-Keygen", + key = "keygen", + pos = { x = 12, y = 5 }, + cost = 4, + atlas = "atlasnotjokers", + order = 401, + can_use = function(self, card) + return true + end, + use = function(self, card, area, copier) + local area + if G.STATE == G.STATES.HAND_PLAYED then + if not G.redeemed_vouchers_during_hand then + G.redeemed_vouchers_during_hand = + CardArea(G.play.T.x, G.play.T.y, G.play.T.w, G.play.T.h, { type = "play", card_limit = 5 }) + end + area = G.redeemed_vouchers_during_hand + else + area = G.play + end + for i = 1, #G.vouchers.cards do + if G.vouchers.cards[i].ability.keygen then + local unredeemed_voucher = G.vouchers.cards[i] + local card = copy_card(unredeemed_voucher) + card.ability.extra = copy_table(unredeemed_voucher.ability.extra) + if card.facing == "back" then + card:flip() + end + + card:start_materialize() + area:emplace(card) + card.cost = 0 + card.shop_voucher = false + local current_round_voucher = G.GAME.current_round.voucher + card:unredeem() + G.GAME.current_round.voucher = current_round_voucher + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0, + func = function() + card:start_dissolve() + unredeemed_voucher:start_dissolve() + return true + end, + })) + end + end + + local _pool = get_current_pool("Voucher", nil, nil, nil, true) + local center = pseudorandom_element(_pool, pseudoseed("cry_keygen_redeem")) + local it = 1 + while center == "UNAVAILABLE" do + it = it + 1 + center = pseudorandom_element(_pool, pseudoseed("cry_keygen_redeem_resample" .. it)) + end + local card = create_card("Voucher", area, nil, nil, nil, nil, center) + card:start_materialize() + area:emplace(card) + card:set_perishable(true) + card.ability.perishable = true + card.ability.banana = true + card.ability.keygen = true + card.cost = 0 + card.shop_voucher = false + local current_round_voucher = G.GAME.current_round.voucher + card:redeem() + G.GAME.current_round.voucher = current_round_voucher + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0, + func = function() + card:start_dissolve() + return true + end, + })) + end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, +} +-- ://Payload +-- Triple interest gained on next cash out, stacks exponentially (multiplicative on modest) local payload = { cry_credits = { idea = { @@ -857,12 +977,15 @@ local payload = { key = "payload", pos = { x = 8, y = 0 }, config = { interest_mult = 3 }, - loc_vars = function(self, info_queue, center) - return { vars = { self.config.interest_mult } } + loc_vars = function(self, info_queue, card) + if not card then + return { vars = { self.config.interest_mult } } + end + return { vars = { card.ability.interest_mult } } end, cost = 4, atlas = "atlasnotjokers", - order = 2, + order = 402, can_use = function(self, card) return true end, @@ -873,61 +996,14 @@ local payload = { bulk_use = function(self, card, area, copier, number) G.GAME.cry_payload = to_big((G.GAME.cry_payload or 1)) * to_big(card.ability.interest_mult) ^ to_big(number) end, -} -local reboot = { - cry_credits = { - idea = { - "HexaCryonic", - }, - art = { - "HexaCryonic", - }, - code = { - "Math", - }, - }, - dependencies = { - items = { - "set_cry_code", - }, - }, - object_type = "Consumable", - set = "Code", - name = "cry-Reboot", - key = "reboot", - pos = { x = 9, y = 0 }, - config = {}, - cost = 4, - atlas = "atlasnotjokers", - order = 3, - can_use = function(self, card) - return G.STATE == G.STATES.SELECTING_HAND - end, - use = function(self, card, area, copier) - G.FUNCS.draw_from_hand_to_discard() - G.FUNCS.draw_from_discard_to_deck() - ease_discard( - math.max(0, G.GAME.round_resets.discards + G.GAME.round_bonus.discards) - G.GAME.current_round.discards_left - ) - ease_hands_played( - math.max(1, G.GAME.round_resets.hands + G.GAME.round_bonus.next_hands) - G.GAME.current_round.hands_left - ) - for k, v in pairs(G.playing_cards) do - v.ability.wheel_flipped = nil - end - G.E_MANAGER:add_event(Event({ - trigger = "immediate", - func = function() - G.STATE = G.STATES.DRAW_TO_HAND - G.deck:shuffle("cry_reboot" .. G.GAME.round_resets.ante) - G.deck:hard_set_T() - G.STATE_COMPLETE = false - return true - end, - })) + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) end, } -local revert = { +-- ://Exploit +-- Choose a hand, next hand is forced to that hand regardless of cards played, +1 asc power for that hand, multi-use 2 +local exploit = { cry_credits = { idea = { "Mjiojio", @@ -936,7 +1012,7 @@ local revert = { "HexaCryonic", }, code = { - "Math", + "Toneblock", }, }, dependencies = { @@ -946,100 +1022,60 @@ local revert = { }, object_type = "Consumable", set = "Code", - name = "cry-Revert", - key = "revert", - pos = { x = 10, y = 0 }, - config = {}, - cost = 4, + key = "exploit", + name = "cry-Exploit", atlas = "atlasnotjokers", - order = 4, - can_use = function(self, card) - return G.GAME.cry_revert - end, - use = function(self, card, area, copier) - G.E_MANAGER:add_event( - Event({ - trigger = "after", - delay = G.SETTINGS.GAMESPEED, - func = function() - G:delete_run() - G:start_run({ - savetext = STR_UNPACK(G.GAME.cry_revert), - }) - end, - }), - "other" - ) - end, - init = function(self) - local sr = save_run - function save_run() - --Sneaking this here but hopefully fixes pointer UI crashes - if G.GAME.USING_CODE then - return - end - if G.GAME.round_resets.ante ~= G.GAME.cry_revert_ante then - G.GAME.cry_revert_ante = G.GAME.round_resets.ante - G.GAME.cry_revert = nil - sr() - G.GAME.cry_revert = STR_PACK(G.culled_table) - sr() - end - sr() + pos = { x = 8, y = 3 }, + cost = 4, + order = 403, + config = { cry_multiuse = 2, extra = { enteredhand = "" } }, -- i don't think this ever uses config...? + loc_vars = function(self, info_queue, card) + if G.STAGE == G.STAGES.RUN and Cryptid.enabled("set_cry_poker_hand_stuff") == true then + local modest = Cryptid.gameset(G.P_CENTERS.c_cry_sunplanet) == "modest" + local current_power = Cryptid.safe_get(G, "GAME", "current_round", "current_hand", "cry_asc_num") + or Cryptid.calculate_ascension_power( + nil, + nil, + nil, + G.GAME.used_vouchers.v_cry_hyperspacetether, + G.GAME.bonus_asc_power + ) + local multiplier = modest and 1 + ((0.25 + G.GAME.sunnumber.modest) * current_power) + or (1.25 + G.GAME.sunnumber.not_modest) ^ current_power + info_queue[#info_queue + 1] = { + key = "asc_misc" .. (modest and 2 or ""), + set = "Other", + specific_vars = { + current_power, + multiplier, + modest and (G.GAME.sunnumber.modest + 0.25) or (G.GAME.sunnumber.not_modest + 1.25), + }, + } end + return { vars = { Cryptid.safe_get(card, "ability", "cry_multiuse") or self.config.cry_multiuse } } end, -} -local semicolon = { - cry_credits = { - idea = { - "HexaCryonic", - }, - art = { - "HexaCryonic", - }, - code = { - "Math", - }, - }, - dependencies = { - items = { - "set_cry_code", - }, - }, - object_type = "Consumable", - set = "Code", - name = "cry-Semicolon", - key = "semicolon", - pos = { - x = 7, - y = 1, - }, - config = {}, - cost = 4, - atlas = "atlasnotjokers", - order = 32, can_use = function(self, card) - return G.STATE == G.STATES.SELECTING_HAND and not G.GAME.blind.boss + return true end, use = function(self, card, area, copier) - G.E_MANAGER:add_event( - Event({ - trigger = "immediate", - func = function() - if G.STATE ~= G.STATES.SELECTING_HAND then - return false - end - G.GAME.current_round.semicolon = true - G.STATE = G.STATES.HAND_PLAYED - G.STATE_COMPLETE = true - end_round() - return true - end, - }), - "other" - ) + -- Un-use the card (re-use code is in lib/misc.lua) + if not card.ability.cry_multiuse or to_big(card.ability.cry_multiuse) <= to_big(1) then + G.GAME.CODE_DESTROY_CARD = copy_card(card) + G.consumeables:emplace(G.GAME.CODE_DESTROY_CARD) + G.GAME.CODE_DESTROY_CARD.ability.cry_multiuse = nil + end + if card.ability.cry_multiuse then + card.ability.cry_multiuse = card.ability.cry_multiuse + 1 + end + + G.GAME.USING_CODE = true + G.GAME.USING_EXPLOIT = true + G.GAME.ACTIVE_CODE_CARD = G.GAME.CODE_DESTROY_CARD or card + G.FUNCS.overlay_menu({ definition = G.UIDEF.exploit_menu() }) end, } +-- ://Malware +-- Apply Glitched edition to held in hand cards local malware = { cry_credits = { idea = { @@ -1061,14 +1097,11 @@ local malware = { set = "Code", name = "cry-Malware", key = "malware", - pos = { - x = 8, - y = 1, - }, + pos = { x = 8, y = 1 }, config = {}, cost = 4, atlas = "atlasnotjokers", - order = 9, + order = 404, can_use = function(self, card) return #G.hand.cards > 0 end, @@ -1114,17 +1147,23 @@ local malware = { })) end end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, } -local seed = { +-- ://NPERROR +-- Add last played hand back to your hand, multi-use 2 +local crynperror = { cry_credits = { idea = { - "Mjiojio", + "HexaCryonic", }, art = { "HexaCryonic", }, code = { - "Math", + "Nova", }, }, dependencies = { @@ -1134,90 +1173,44 @@ local seed = { }, object_type = "Consumable", set = "Code", - name = "cry-Seed", - key = "seed", - pos = { - x = 10, - y = 1, - }, - config = {}, + name = "cry-NPERROR", + key = "nperror", + pos = { x = 10, y = 5 }, cost = 4, atlas = "atlasnotjokers", - order = 12, + order = 405, + config = { cry_multiuse = 2 }, can_use = function(self, card) - --the card itself and one other card - return #G.jokers.highlighted - + #G.hand.highlighted - + #G.consumeables.highlighted - + (G.pack_cards and #G.pack_cards.highlighted or 0) - --+ (G.shop_cards and #G.shop_cards.highlighted or 0) TODO: this so you can use seed when it's in shop - == 2 - end, - loc_vars = function(self, info_queue, card) - info_queue[#info_queue + 1] = { key = "cry_rigged", set = "Other", vars = {} } + return G.GAME.last_hand_played_cards and (Cryptid.safe_get(G.GAME, "blind", "in_blind")) -- TODO: work in boosters end, use = function(self, card, area, copier) - if area then - area:remove_from_highlighted(card) - end - if G.jokers.highlighted[1] then - G.jokers.highlighted[1].ability.cry_rigged = true - if G.jokers.highlighted[1].config.center.key == "j_cry_googol_play" then - check_for_unlock({ type = "googol_play_rigged" }) + for i = 1, #G.GAME.last_hand_played_cards do + for _, v in pairs(G.discard.cards) do + if v.sort_id == G.GAME.last_hand_played_cards[i] then + if v.facing == "back" then + v:flip() + end + draw_card(G.discard, G.hand, i * 100 / 5, "up", nil, v) + end + end + for _, v in pairs(G.deck.cards) do + if v.sort_id == G.GAME.last_hand_played_cards[i] then + if v.facing == "back" then + v:flip() + end + draw_card(G.deck, G.hand, i * 100 / 5, "up", nil, v) + end end end - if G.hand.highlighted[1] then - G.hand.highlighted[1].ability.cry_rigged = true - end - if G.consumeables.highlighted[1] then - G.consumeables.highlighted[1].ability.cry_rigged = true - end - if Cryptid.safe_get(G, "pack_cards", "highlighted", 1) then - G.pack_cards.highlighted[1].ability.cry_rigged = true - end + end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) end, } -local rigged = { - dependencies = { - items = { - "c_cry_seed", - }, - }, - object_type = "Sticker", - atlas = "sticker", - pos = { x = 6, y = 1 }, - key = "cry_rigged", - no_sticker_sheet = true, - prefix_config = { key = false }, - badge_colour = HEX("14b341"), - draw = function(self, card) --don't draw shine - local notilt = nil - if card.area and card.area.config.type == "deck" then - notilt = true - end - if not G.shared_stickers["cry_rigged2"] then - G.shared_stickers["cry_rigged2"] = - Sprite(0, 0, G.CARD_W, G.CARD_H, G.ASSET_ATLAS["cry_sticker"], { x = 5, y = 1 }) - end -- no matter how late i init this, it's always late, so i'm doing it in the damn draw function - - G.shared_stickers[self.key].role.draw_major = card - G.shared_stickers["cry_rigged2"].role.draw_major = card - - G.shared_stickers[self.key]:draw_shader("dissolve", nil, nil, notilt, card.children.center) - - card.hover_tilt = card.hover_tilt / 2 -- call it spaghetti, but it's what hologram does so... - G.shared_stickers["cry_rigged2"]:draw_shader("dissolve", nil, nil, notilt, card.children.center) - G.shared_stickers["cry_rigged2"]:draw_shader( - "hologram", - nil, - card.ARGS.send_to_shader, - notilt, - card.children.center - ) -- this doesn't really do much tbh, but the slight effect is nice - card.hover_tilt = card.hover_tilt * 2 - end, -} -local hook = { +-- ://Rework +-- Destroy a selected joker, create a Rework Tag of that joker with an upgraded edition via collection +local rework = { cry_credits = { idea = { "HexaCryonic", @@ -1236,778 +1229,151 @@ local hook = { }, object_type = "Consumable", set = "Code", - name = "cry-Hook", - key = "hook", - pos = { - x = 7, - y = 4, - }, - config = {}, - cost = 4, + key = "rework", + name = "cry-Rework", atlas = "atlasnotjokers", - order = 14, - no_pool_flag = "beta_deck", + order = 406, + pos = { x = 10, y = 3 }, + cost = 4, + loc_vars = function(self, info_queue) + info_queue[#info_queue + 1] = + { set = "Tag", key = "tag_cry_rework", specific_vars = { "[edition]", "[joker]", "n" } } + return { vars = {} } + end, can_use = function(self, card) - return #G.jokers.highlighted == 2 - end, - loc_vars = function(self, info_queue, card) - info_queue[#info_queue + 1] = { key = "cry_hooked", set = "Other", vars = { "hooked Joker" } } + local cards = Cryptid.get_highlighted_cards({ G.jokers }, card, 1, 1, function(card) + return card.ability.set == "Joker" + end) + return #cards == 1 + and not SMODS.is_eternal(cards[1]) + and cards[1].ability.name + ~= ("cry-meteor" or "cry-exoplanet" or "cry-stardust" or "cry_cursed" or ("Diet Cola" or Card.get_gameset( + card + ) == "madness")) end, use = function(self, card, area, copier) - G.jokers.highlighted[1].ability.cry_hooked = true - G.jokers.highlighted[2].ability.cry_hooked = true - G.jokers.highlighted[1].hook_id = G.jokers.highlighted[2].sort_id - G.jokers.highlighted[2].hook_id = G.jokers.highlighted[1].sort_id - end, - init = function(self) - --HOOK:// patches (probably broken) - --[[local cj = Card.calculate_joker - function Card:calculate_joker(context) - local ret, trig = cj(self, context) - if - (ret or trig) - and self.ability.cry_hooked - and not context.post_trigger - and not context.cry_hook - and not context.retrigger_joker_check - and not context.megatrigger_check - then - context.cry_hook = true - for i = 1, #G.jokers.cards do - if G.jokers.cards[i].sort_id == self.hook_id then - card_eval_status_text( - G.jokers.cards[i], - "extra", - nil, - nil, - nil, - { message = localize("cry_hooked_ex"), colour = G.C.SET.Code } - ) - cj(G.jokers.cards[i], context) - --I tried a few things to get the color of messages to be green from the other joker, but they haven't worked :( - end - end - context.cry_hook = nil - end - return ret, trig - end--]] - local Cardstart_dissolveRef = Card.start_dissolve - function Card:start_dissolve(dissolve_colours, silent, dissolve_time_fac, no_juice) - if G.jokers then - for i = 1, #G.jokers.cards do - if G.jokers.cards[i].hook_id == self.sort_id then - G.jokers.cards[i].ability.cry_hooked = false - G.jokers.cards[i].hook_id = nil - end + local cards = Cryptid.get_highlighted_cards({ G.jokers }, card, 1, 1, function(card) + return card.ability.set == "Joker" + end) + local jkr = cards[1] + local found_index = 1 + if jkr.edition then + for i, v in ipairs(G.P_CENTER_POOLS.Edition) do + if v.key == jkr.edition.key then + found_index = i + break end end - Cardstart_dissolveRef(self, dissolve_colours, silent, dissolve_time_fac, no_juice) end - end, -} -local hooked = { - dependencies = { - items = { - "c_cry_hook", - }, - }, - object_type = "Sticker", - atlas = "sticker", - pos = { x = 5, y = 3 }, - no_edeck = true, - loc_vars = function(self, info_queue, card) - local var - if not card or not card.hook_id then - var = "[" .. localize("k_joker") .. "]" - else - for i = 1, #G.jokers.cards do - if G.jokers.cards[i].sort_id == card.hook_id then - var = localize({ type = "name_text", set = "Joker", key = G.jokers.cards[i].config.center.key }) - end - end - var = var or ("[no joker found - " .. (card.hook_id or "nil") .. "]") + found_index = found_index + 1 + if found_index > #G.P_CENTER_POOLS.Edition then + found_index = found_index - #G.P_CENTER_POOLS.Edition end - return { vars = { var or "hooked Joker" } } - end, - key = "cry_hooked", - no_sticker_sheet = true, - prefix_config = { key = false }, - badge_colour = HEX("14b341"), - draw = function(self, card) --don't draw shine - G.shared_stickers[self.key].role.draw_major = card - G.shared_stickers[self.key]:draw_shader("dissolve", nil, nil, nil, card.children.center) - end, -} -local variable = { - cry_credits = { - idea = { - "HexaCryonic", - }, - art = { - "HexaCryonic", - }, - code = { - "AlexZGreat", - }, - }, - dependencies = { - items = { - "set_cry_code", - }, - }, - object_type = "Consumable", - set = "Code", - key = "variable", - name = "cry-Variable", - atlas = "atlasnotjokers", - pos = { - x = 9, - y = 1, - }, - cost = 4, - order = 8, - config = { max_highlighted = 2, extra = { enteredrank = "" } }, - loc_vars = function(self, info_queue, card) - return { vars = { Cryptid.safe_get(card, "ability", "max_highlighted") or self.config.max_highlighted } } - end, - use = function(self, card, area, copier) - G.GAME.USING_CODE = true - G.ENTERED_RANK = "" - G.CHOOSE_RANK = UIBox({ - definition = create_UIBox_variable(card), - config = { - align = "cm", - offset = { x = 0, y = 10 }, - major = G.ROOM_ATTACH, - bond = "Weak", - instance_type = "POPUP", - }, - }) - G.CHOOSE_RANK.alignment.offset.y = 0 - G.ROOM.jiggle = G.ROOM.jiggle + 1 - G.CHOOSE_RANK:align_to_major() - end, - init = function(self) - function create_UIBox_variable(card) - G.E_MANAGER:add_event(Event({ - blockable = false, - func = function() - G.REFRESH_ALERTS = true - return true - end, - })) - local t = create_UIBox_generic_options({ - no_back = true, - colour = HEX("04200c"), - outline_colour = G.C.SECONDARY_SET.Code, - contents = { - { - n = G.UIT.R, - nodes = { - create_text_input({ - colour = G.C.SET.Code, - hooked_colour = darken(copy_table(G.C.SET.Code), 0.3), - w = 4.5, - h = 1, - max_length = 16, - extended_corpus = true, - prompt_text = localize("cry_code_rank"), - ref_table = G, - ref_value = "ENTERED_RANK", - keyboard_offset = 1, - }), - }, - }, - { - n = G.UIT.R, - nodes = { - UIBox_button({ - colour = G.C.SET.Code, - button = "variable_apply", - label = { localize("cry_code_apply") }, - minw = 4.5, - focus_args = { snap_to = true }, - }), - }, - }, - { - n = G.UIT.R, - nodes = { - UIBox_button({ - colour = G.C.RED, - button = "variable_apply_previous", - label = { localize("cry_code_apply_previous") }, - minw = 4.5, - focus_args = { snap_to = true }, - }), - }, - }, - { - n = G.UIT.R, - nodes = { - UIBox_button({ - colour = G.C.RED, - button = "variable_cancel", - label = { localize("cry_code_cancel") }, - minw = 4.5, - focus_args = { snap_to = true }, - }), - }, - }, - }, - }) - return t + local tag = Tag("tag_cry_rework") + if not tag.ability then + tag.ability = {} end - - G.FUNCS.variable_apply_previous = function() - if G.PREVIOUS_ENTERED_RANK then - G.ENTERED_RANK = G.PREVIOUS_ENTERED_RANK or "" - end - G.FUNCS.variable_apply() + if jkr.config.center.key == "c_base" then + jkr.config.center.key = "j_scholar" end - - G.FUNCS.variable_apply = function() - local rank_table = { - {}, - { "2", "Two", "II" }, - { "3", "Three", "III" }, - { "4", "Four", "IV" }, - { "5", "Five", "V" }, - { "6", "Six", "VI" }, - { "7", "Seven", "VII" }, - { "8", "Eight", "VIII" }, - { "9", "Nine", "IX" }, - { "10", "1O", "Ten", "X", "T" }, - { "J", "Jack" }, - { "Q", "Queen" }, - { "K", "King" }, - { "A", "Ace", "One", "1", "I" }, - { "M" }, - { "nil" }, - } - - local rank_suffix = nil - - for i, v in pairs(rank_table) do - for j, k in pairs(v) do - if string.lower(G.ENTERED_RANK) == string.lower(k) then - rank_suffix = i - end - end - end - - if rank_suffix then - local TempCard = {} - for i = 1, #G.hand.highlighted do - TempCard[i] = G.hand.highlighted[i] - end - G.PREVIOUS_ENTERED_RANK = G.ENTERED_RANK - G.GAME.USING_CODE = false - if rank_suffix == 15 then - check_for_unlock({ type = "cheat_used" }) - local card = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_jolly") - card:add_to_deck() - G.jokers:emplace(card) - elseif rank_suffix == 16 then - check_for_unlock({ type = "cheat_used" }) - local card = create_card("Code", G.consumeables, nil, nil, nil, nil, "c_cry_crash") - card:add_to_deck() - G.consumeables:emplace(card) - elseif rank_suffix == 17 then - check_for_unlock({ type = "cheat_used" }) - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.4, - func = function() - play_sound("tarot1") - return true - end, - })) - for i = 1, #TempCard do - local percent = 1.15 - (i - 0.999) / (#G.hand.highlighted - 0.998) * 0.3 - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.15, - func = function() - TempCard[i]:flip() - play_sound("card1", percent) - TempCard[i]:juice_up(0.3, 0.3) - return true - end, - })) - end - delay(0.2) - for i = 1, #TempCard do - local CARD = TempCard[i] - local percent = 0.85 + (i - 0.999) / (#TempCard - 0.998) * 0.3 - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.15, - func = function() - CARD:flip() - CARD:set_ability( - G.P_CENTERS[pseudorandom_element( - G.P_CENTER_POOLS.Consumeables, - pseudoseed("cry_variable") - ).key], - true, - nil - ) - play_sound("tarot2", percent) - CARD:juice_up(0.3, 0.3) - return true - end, - })) - end - else - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.4, - func = function() - play_sound("tarot1") - return true - end, - })) - for i = 1, #TempCard do - local percent = 1.15 - (i - 0.999) / (#TempCard - 0.998) * 0.3 - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.15, - func = function() - TempCard[i]:flip() - play_sound("card1", percent) - TempCard[i]:juice_up(0.3, 0.3) - return true - end, - })) - end - delay(0.2) - for i = 1, #TempCard do - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.1, - func = function() - local card = TempCard[i] - local suit_prefix = string.sub(card.base.suit, 1, 1) .. "_" - local r2suffix = nil - if rank_suffix < 10 then - r2suffix = tostring(rank_suffix) - elseif rank_suffix == 10 then - r2suffix = "T" - elseif rank_suffix == 11 then - r2suffix = "J" - elseif rank_suffix == 12 then - r2suffix = "Q" - elseif rank_suffix == 13 then - r2suffix = "K" - elseif rank_suffix == 14 then - r2suffix = "A" - end - card:set_base(G.P_CARDS[suit_prefix .. r2suffix]) - return true - end, - })) - end - for i = 1, #TempCard do - local percent = 0.85 + (i - 0.999) / (#TempCard - 0.998) * 0.3 - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.15, - func = function() - TempCard[i]:flip() - play_sound("tarot2", percent, 0.6) - TempCard[i]:juice_up(0.3, 0.3) - return true - end, - })) - end - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.2, - func = function() - G.hand:unhighlight_all() - return true - end, - })) - delay(0.5) - end - G.CHOOSE_RANK:remove() - end - end - - G.FUNCS.variable_cancel = function() - G.CHOOSE_RANK:remove() - G.GAME.USING_CODE = false - end - end, -} -local class = { - cry_credits = { - idea = { - "HexaCryonic", - }, - art = { - "HexaCryonic", - }, - code = { - "Math", - }, - }, - dependencies = { - items = { - "set_cry_code", - }, - }, - object_type = "Consumable", - set = "Code", - key = "class", - name = "cry-Class", - atlas = "atlasnotjokers", - pos = { - x = 11, - y = 1, - }, - cost = 4, - order = 16, - config = { max_highlighted = 1, extra = { enteredrank = "" } }, - loc_vars = function(self, info_queue, card) - return { vars = { Cryptid.safe_get(card, "ability", "max_highlighted") or self.config.max_highlighted } } - end, - use = function(self, card, area, copier) - G.GAME.USING_CODE = true - G.ENTERED_ENH = "" - G.CHOOSE_ENH = UIBox({ - definition = create_UIBox_class(card), - config = { - align = "cm", - offset = { x = 0, y = 10 }, - major = G.ROOM_ATTACH, - bond = "Weak", - instance_type = "POPUP", - }, - }) - G.CHOOSE_ENH.alignment.offset.y = 0 - G.ROOM.jiggle = G.ROOM.jiggle + 1 - G.CHOOSE_ENH:align_to_major() - end, - init = function(self) - function create_UIBox_class(card) - G.E_MANAGER:add_event(Event({ - blockable = false, - func = function() - G.REFRESH_ALERTS = true - return true - end, - })) - local t = create_UIBox_generic_options({ - no_back = true, - colour = HEX("04200c"), - outline_colour = G.C.SECONDARY_SET.Code, - contents = { - { - n = G.UIT.R, - nodes = { - create_text_input({ - colour = G.C.SET.Code, - hooked_colour = darken(copy_table(G.C.SET.Code), 0.3), - w = 4.5, - h = 1, - max_length = 16, - prompt_text = localize("cry_code_enh"), - ref_table = G, - ref_value = "ENTERED_ENH", - keyboard_offset = 1, - }), - }, - }, - { - n = G.UIT.R, - nodes = { - UIBox_button({ - colour = G.C.SET.Code, - button = "class_apply", - label = { localize("cry_code_apply") }, - minw = 4.5, - focus_args = { snap_to = true }, - }), - }, - }, - { - n = G.UIT.R, - nodes = { - UIBox_button({ - colour = G.C.RED, - button = "class_apply_previous", - label = { localize("cry_code_apply_previous") }, - minw = 4.5, - focus_args = { snap_to = true }, - }), - }, - }, - { - n = G.UIT.R, - nodes = { - UIBox_button({ - colour = G.C.RED, - button = "class_cancel", - label = { localize("cry_code_cancel") }, - minw = 4.5, - focus_args = { snap_to = true }, - }), - }, - }, - }, - }) - return t - end - - G.FUNCS.class_apply_previous = function() - if G.PREVIOUS_ENTERED_ENH then - G.ENTERED_ENH = G.PREVIOUS_ENTERED_ENH or "" - end - G.FUNCS.class_apply() - end - --todo: mod support - G.FUNCS.class_apply = function() - local enh_table = { - m_bonus = { "bonus" }, - m_mult = { "mult", "red" }, - m_wild = { "wild", "suit" }, - m_glass = { "glass", "xmult" }, - m_steel = { "steel", "metal", "grey" }, - m_stone = { "stone", "chip", "chips" }, - m_gold = { "gold", "money", "yellow" }, - m_lucky = { "lucky", "rng" }, - m_cry_echo = { "echo", "retrigger", "retriggers" }, - m_cry_light = { "light" }, - ccd = { "ccd" }, - null = { "nil" }, - } - - local enh_suffix = nil - - for i, v in pairs(enh_table) do - for j, k in pairs(v) do - if string.lower(G.ENTERED_ENH) == string.lower(k) then - enh_suffix = i - end - end - end - - if enh_suffix then - local TempCard = {} - for i = 1, #G.hand.highlighted do - TempCard[i] = G.hand.highlighted[i] - end - G.PREVIOUS_ENTERED_ENH = G.ENTERED_ENH - G.GAME.USING_CODE = false - if enh_suffix == "ccd" then - check_for_unlock({ type = "cheat_used" }) - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.4, - func = function() - play_sound("tarot1") - return true - end, - })) - for i = 1, #TempCard do - local percent = 1.15 - (i - 0.999) / (#G.hand.highlighted - 0.998) * 0.3 - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.15, - func = function() - TempCard[i]:flip() - play_sound("card1", percent) - TempCard[i]:juice_up(0.3, 0.3) - return true - end, - })) - delay(0.2) - end - for i = 1, #TempCard do - local CARD = TempCard[i] - local percent = 0.85 + (i - 0.999) / (#G.hand.highlighted - 0.998) * 0.3 - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.15, - func = function() - CARD:flip() - CARD:set_ability(Cryptid.random_consumable("cry_class"), true, nil) - play_sound("tarot2", percent) - CARD:juice_up(0.3, 0.3) - return true - end, - })) - end - elseif enh_suffix == "null" then - local destroyed_cards = {} - check_for_unlock({ type = "cheat_used" }) - for i = #TempCard, 1, -1 do - local card = TempCard[i] - if not card.ability.eternal then - destroyed_cards[#destroyed_cards + 1] = TempCard[i] - if card.ability.name == "Glass Card" then - card:shatter() - else - card:start_dissolve(nil, i == #TempCard) - end - end - end - if destroyed_cards[1] then - for j = 1, #G.jokers.cards do - eval_card( - G.jokers.cards[j], - { cardarea = G.jokers, remove_playing_cards = true, removed = destroyed_cards } - ) - end - end - G.CHOOSE_ENH:remove() - return - else - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.4, - func = function() - play_sound("tarot1") - return true - end, - })) - for i = 1, #TempCard do - local percent = 1.15 - (i - 0.999) / (#TempCard - 0.998) * 0.3 - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.15, - func = function() - TempCard[i]:flip() - play_sound("card1", percent) - TempCard[i]:juice_up(0.3, 0.3) - return true - end, - })) - end - delay(0.2) - for i = 1, #TempCard do - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.1, - func = function() - TempCard[i]:set_ability(G.P_CENTERS[enh_suffix]) - return true - end, - })) - end - for i = 1, #TempCard do - local percent = 0.85 + (i - 0.999) / (#TempCard - 0.998) * 0.3 - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.15, - func = function() - TempCard[i]:flip() - play_sound("tarot2", percent, 0.6) - TempCard[i]:juice_up(0.3, 0.3) - return true - end, - })) - end - end - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.2, - func = function() - G.hand:unhighlight_all() - return true - end, - })) - delay(0.5) - G.CHOOSE_ENH:remove() - end - end - - G.FUNCS.class_cancel = function() - G.GAME.USING_CODE = false - G.CHOOSE_ENH:remove() - end - end, -} -local commit = { - cry_credits = { - idea = { - "HexaCryonic", - }, - art = { - "HexaCryonic", - }, - code = { - "Math", - }, - }, - dependencies = { - items = { - "set_cry_code", - }, - }, - object_type = "Consumable", - set = "Code", - key = "commit", - name = "cry-Commit", - atlas = "atlasnotjokers", - pos = { - x = 8, - y = 2, - }, - cost = 4, - order = 31, - can_use = function(self, card) - return #G.jokers.highlighted == 1 - and not G.jokers.highlighted[1].ability.eternal - and not ( - type(G.jokers.highlighted[1].config.center.rarity) == "number" - and G.jokers.highlighted[1].config.center.rarity >= 5 - ) - end, - use = function(self, card, area, copier) - local deleted_joker_key = G.jokers.highlighted[1].config.center.key - local rarity = G.jokers.highlighted[1].config.center.rarity - local legendary = nil - --please someone add a rarity api to steamodded - if rarity == 1 then - rarity = 0 - elseif rarity == 2 then - rarity = 0.9 - elseif rarity == 3 then - rarity = 0.99 - elseif rarity == 4 then - rarity = nil - legendary = true - end -- Deleted check for "cry epic" it was giving rare jokers by setting rarity to 1 - local _first_dissolve = nil + tag.ability.rework_key = jkr.config.center.key + tag.ability.rework_edition = G.P_CENTER_POOLS.Edition[found_index].key + add_tag(tag) + --SMODS.Tags.tag_cry_rework.apply(tag, {type = "store_joker_create"}) G.E_MANAGER:add_event(Event({ trigger = "before", delay = 0.75, func = function() - G.jokers.highlighted[1]:start_dissolve(nil, _first_dissolve) - _first_dissolve = true - return true - end, - })) - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.4, - func = function() - play_sound("timpani") - local card = create_card("Joker", G.jokers, legendary, rarity, nil, nil, nil, "cry_commit") - card:add_to_deck() - G.jokers:emplace(card) - card:juice_up(0.3, 0.5) - if card.config.center.key == deleted_joker_key then - check_for_unlock({ type = "pr_unlock" }) - end + jkr:start_dissolve() return true end, })) end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, } +-- Rework Tag +-- Upgraded edition refers to the next edition along in the collection; base -> foil -> holo -> poly -> negative -> etc +local rework_tag = { + cry_credits = { + idea = { + "HexaCryonic", + }, + art = { + "HexaCryonic", + }, + code = { + "Math", + }, + }, + dependencies = { + items = { + "c_cry_rework", + }, + }, + object_type = "Tag", + atlas = "tag_cry", + name = "cry-Rework Tag", + order = 610, + pos = { x = 0, y = 3 }, + config = { type = "store_joker_create" }, + key = "rework", + ability = { rework_edition = nil, rework_key = nil }, + loc_vars = function(self, info_queue, tag) + local function p(w) + r = "" + local vowels = { "a", "e", "i", "o", "u" } + for i, v in ipairs(vowels) do + if string.sub(string.lower(w), 1, 1) == v then + r = "n" + break + end + end + return r + end + local ed = Cryptid.safe_get(tag, "ability", "rework_edition") + and localize({ type = "name_text", set = "Edition", key = tag.ability.rework_edition }) + or "[" .. string.lower(localize("k_edition")) .. "]" + return { + vars = { + ed, + Cryptid.safe_get(tag, "ability", "rework_key") + and localize({ type = "name_text", set = "Joker", key = tag.ability.rework_key }) + or "[" .. string.lower(localize("k_joker")) .. "]", + string.sub(ed, 1, 1) ~= "[" and p(ed) or "n", + }, + } + end, + apply = function(self, tag, context) + if context.type == "store_joker_create" then + local card = create_card("Joker", context.area, nil, nil, nil, nil, (tag.ability.rework_key or "j_scholar")) + create_shop_card_ui(card, "Joker", context.area) + card:set_edition((tag.ability.rework_edition or "e_foil"), true, nil, true) + card.states.visible = false + tag:yep("+", G.C.FILTER, function() + card:start_materialize() + return true + end) + tag.triggered = true + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.5, + func = function() + save_run() --fixes savescum bugs hopefully? + return true + end, + })) + return card + end + end, + in_pool = function() + return false + end, +} +-- ://Merge +-- Merges a selected consumable and playing card, destroying the consumable and turning the playing card into a CCD of that consumable local merge = { cry_credits = { idea = { @@ -2030,403 +1396,175 @@ local merge = { key = "merge", name = "cry-Merge", atlas = "atlasnotjokers", - pos = { - x = 7, - y = 2, - }, + pos = { x = 7, y = 2 }, cost = 4, - order = 21, + order = 407, can_use = function(self, card) - if #G.hand.highlighted ~= 1 + (card.area == G.hand and 1 or 0) then - return false - end - if #G.consumeables.highlighted ~= 1 + (card.area == G.consumeables and 1 or 0) then - return false - end - local n = 1 - if G.hand.highlighted[1] == card then - n = 2 - end - if G.hand.highlighted[n].ability.consumeable then - return false - end - local m = 1 - if G.consumeables.highlighted[1] == card then - m = 2 - end + local hand = Cryptid.get_highlighted_cards({ G.hand }, card, 1, 1) + local consumeables = Cryptid.get_highlighted_cards({ G.consumeables }, card, 1, 1, function(card) + return card.ability.consumeable + end) if - G.consumeables.highlighted[m].ability.eternal - or G.consumeables.highlighted[m].ability.set == "Unique" - or not G.consumeables.highlighted[m].ability.consumeable + #hand ~= 1 + or #consumeables ~= 1 + or SMODS.is_eternal(consumeables[1]) + or consumeables[1].ability.set == "Unique" then return false end return true end, use = function(self, card, area, copier) + local hand = Cryptid.get_highlighted_cards({ G.hand }, card, 1, 1) + local consumeables = Cryptid.get_highlighted_cards({ G.consumeables }, card, 1, 1, function(card) + return card.ability.consumeable + end) + if #hand == 1 and #consumeables == 1 then + G.E_MANAGER:add_event(Event({ + trigger = "immediate", + func = function() + G.cry_mergearea1 = + CardArea(G.play.T.x, G.play.T.y, G.play.T.w, G.play.T.h, { type = "play", card_limit = 5 }) + G.cry_mergearea2 = + CardArea(G.play.T.x, G.play.T.y, G.play.T.w, G.play.T.h, { type = "play", card_limit = 5 }) + local key = consumeables[1].config.center.key + local c = consumeables[1] + local CARD = hand[1] + play_sound("card1") + G.consumeables:remove_from_highlighted(c) + CARD.area = G.cry_mergearea1 + c.area = G.cry_mergearea2 + draw_card(G.hand, G.cry_mergearea1, 1, "up", true, CARD) + draw_card(G.consumeables, G.cry_mergearea2, 1, "up", true, c) + delay(0.2) + CARD:flip() + c:flip() + delay(0.2) + local percent = 0.85 + (1 - 0.999) / (#G.hand.highlighted - 0.998) * 0.3 + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.2, + func = function() + play_sound("timpani") + c:start_dissolve(nil, nil, 0) + CARD:flip() + CARD:set_ability(G.P_CENTERS[key], true, nil) + play_sound("tarot2", percent) + CARD:juice_up(0.3, 0.3) + return true + end, + })) + delay(0.5) + draw_card(G.cry_mergearea1, G.hand, 1, "up", true, CARD) + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.5, + func = function() + G.cry_mergearea2:remove_card(c) + G.cry_mergearea2:remove() + G.cry_mergearea1:remove() + G.cry_mergearea1 = nil + G.cry_mergearea2 = nil + return true + end, + })) + return true + end, + })) + end + end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, +} +-- ://Commit +-- Destroys a selected joker and creates a different joker of the same rarity +local commit = { + cry_credits = { + idea = { + "HexaCryonic", + }, + art = { + "HexaCryonic", + }, + code = { + "Math", + }, + }, + dependencies = { + items = { + "set_cry_code", + }, + }, + object_type = "Consumable", + set = "Code", + key = "commit", + name = "cry-Commit", + atlas = "atlasnotjokers", + pos = { x = 8, y = 2 }, + cost = 4, + order = 408, + can_use = function(self, card) + local jokers = Cryptid.get_highlighted_cards({ G.jokers }, card, 1, 1, function(card) + return card.ability.set == "Joker" and not card.getting_sliced + end) + return #jokers == 1 + and not SMODS.is_eternal(jokers[1]) + and not (type(jokers[1].config.center.rarity) == "number" and jokers[1].config.center.rarity >= 5) + end, + use = function(self, card, area, copier) + local jokers = Cryptid.get_highlighted_cards({ G.jokers }, card, 1, 1, function(card) + return card.ability.set == "Joker" and not card.getting_sliced + end) + local deleted_joker_key = jokers[1].config.center.key + local rarity = jokers[1].config.center.rarity + jokers[1].getting_sliced = true + local legendary = nil + --please someone add a rarity api to steamodded + if rarity == 1 then + rarity = 0 + elseif rarity == 2 then + rarity = 0.9 + elseif rarity == 3 then + rarity = 0.99 + elseif rarity == 4 then + rarity = nil + legendary = true + end -- Deleted check for "cry epic" it was giving rare jokers by setting rarity to 1 + local _first_dissolve = nil G.E_MANAGER:add_event(Event({ - trigger = "immediate", + trigger = "before", + delay = 0.75, func = function() - G.cry_mergearea1 = - CardArea(G.play.T.x, G.play.T.y, G.play.T.w, G.play.T.h, { type = "play", card_limit = 5 }) - G.cry_mergearea2 = - CardArea(G.play.T.x, G.play.T.y, G.play.T.w, G.play.T.h, { type = "play", card_limit = 5 }) - area:remove_from_highlighted(card) - local key = G.consumeables.highlighted[1].config.center.key - local c = G.consumeables.highlighted[1] - local CARD = G.hand.highlighted[1] - card:start_dissolve() - play_sound("card1") - G.consumeables:remove_from_highlighted(c) - CARD.area = G.cry_mergearea1 - c.area = G.cry_mergearea2 - draw_card(G.hand, G.cry_mergearea1, 1, "up", true, CARD) - draw_card(G.consumeables, G.cry_mergearea2, 1, "up", true, c) - delay(0.2) - CARD:flip() - c:flip() - delay(0.2) - local percent = 0.85 + (1 - 0.999) / (#G.hand.highlighted - 0.998) * 0.3 - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.2, - func = function() - play_sound("timpani") - c:start_dissolve(nil, nil, 0) - CARD:flip() - CARD:set_ability(G.P_CENTERS[key], true, nil) - play_sound("tarot2", percent) - CARD:juice_up(0.3, 0.3) - return true - end, - })) - delay(0.5) - draw_card(G.cry_mergearea1, G.hand, 1, "up", true, CARD) - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.5, - func = function() - G.cry_mergearea2:remove_card(c) - G.cry_mergearea2:remove() - G.cry_mergearea1:remove() - G.cry_mergearea1 = nil - G.cry_mergearea2 = nil - return true - end, - })) + jokers[1]:start_dissolve(nil, _first_dissolve) + _first_dissolve = true + return true + end, + })) + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.4, + func = function() + play_sound("timpani") + local card = create_card("Joker", G.jokers, legendary, rarity, nil, nil, nil, "cry_commit") + card:add_to_deck() + G.jokers:emplace(card) + card:juice_up(0.3, 0.5) + if card.config.center.key == deleted_joker_key then + check_for_unlock({ type = "pr_unlock" }) + end return true end, })) end, -} -local multiply = { - cry_credits = { - idea = { - "HexaCryonic", - }, - art = { - "HexaCryonic", - }, - code = { - "Math", - }, - }, - dependencies = { - items = { - "set_cry_code", - }, - }, - object_type = "Consumable", - set = "Code", - key = "multiply", - name = "cry-Multiply", - atlas = "atlasnotjokers", - order = 24, - pos = { - x = 10, - y = 2, - }, - cost = 4, - can_use = function(self, card) - if not G.GAME.modifiers.cry_beta then - return #G.jokers.highlighted == 1 and not Card.no(G.jokers.highlighted[1], "immutable", true) - else - return #G.jokers.highlighted == 2 - and not ( - Card.no(G.jokers.highlighted[1], "immutable", true) - or Card.no(G.jokers.highlighted[2], "immutable", true) - ) - end - end, - use = function(self, card, area, copier) - if not G.jokers.highlighted[1].config.cry_multiply then - G.jokers.highlighted[1].config.cry_multiply = 1 - end - G.jokers.highlighted[1].config.cry_multiply = G.jokers.highlighted[1].config.cry_multiply * 2 - Cryptid.with_deck_effects(G.jokers.highlighted[1], function(card) - Cryptid.misprintize(card, { min = 2, max = 2 }, nil, true) - end) - end, - init = function(self) - --reset Jokers at end of round - local er = end_round - function end_round() - er() - for i = 1, #G.jokers.cards do - if G.jokers.cards[i].config.cry_multiply then - m = G.jokers.cards[i].config.cry_multiply - Cryptid.with_deck_effects(G.jokers.cards[i], function(card) - Cryptid.misprintize(card, { min = 1 / m, max = 1 / m }, nil, true) - end) - G.jokers.cards[i].config.cry_multiply = nil - end - end - end - end, -} -local divide = { - cry_credits = { - idea = { - "HexaCryonic", - }, - art = { - "HexaCryonic", - }, - code = { - "Math", - }, - }, - dependencies = { - items = { - "set_cry_code", - }, - }, - object_type = "Consumable", - set = "Code", - key = "divide", - name = "cry-Divide", - atlas = "atlasnotjokers", - order = 23, - pos = { - x = 9, - y = 2, - }, - cost = 4, - can_use = function(self, card) - return G.STATE == G.STATES.SHOP - end, - can_bulk_use = true, - use = function(self, card, area, copier) - for i = 1, #G.shop_jokers.cards do - local c = G.shop_jokers.cards[i] - c.misprint_cost_fac = (c.misprint_cost_fac or 1) * 0.5 - c:set_cost() - end - for i = 1, #G.shop_booster.cards do - local c = G.shop_booster.cards[i] - c.misprint_cost_fac = (c.misprint_cost_fac or 1) * 0.5 - c:set_cost() - end - for i = 1, #G.shop_vouchers.cards do - local c = G.shop_vouchers.cards[i] - c.misprint_cost_fac = (c.misprint_cost_fac or 1) * 0.5 - c:set_cost() - end - end, - bulk_use = function(self, card, area, copier, number) - for i = 1, #G.shop_jokers.cards do - local c = G.shop_jokers.cards[i] - c.misprint_cost_fac = (c.misprint_cost_fac or 1) / (2 ^ number) - c:set_cost() - end - for i = 1, #G.shop_booster.cards do - local c = G.shop_booster.cards[i] - c.misprint_cost_fac = (c.misprint_cost_fac or 1) / (2 ^ number) - c:set_cost() - end - for i = 1, #G.shop_vouchers.cards do - local c = G.shop_vouchers.cards[i] - c.misprint_cost_fac = (c.misprint_cost_fac or 1) / (2 ^ number) - c:set_cost() - end - end, -} -local delete = { - cry_credits = { - idea = { - "Mjiojio", - }, - art = { - "HexaCryonic", - }, - code = { - "Math", - "Toneblock", - }, - }, - dependencies = { - items = { - "set_cry_code", - }, - }, - object_type = "Consumable", - set = "Code", - key = "delete", - name = "cry-Delete", - atlas = "atlasnotjokers", - order = 18, - pos = { - x = 11, - y = 2, - }, - cost = 4, - config = { cry_multiuse = 3 }, - loc_vars = function(self, info_queue, card) - return { vars = { Cryptid.safe_get(card, "ability", "cry_multiuse") or self.config.cry_multiuse } } - end, - can_use = function(self, card) - return G.STATE == G.STATES.SHOP - and card.area == G.consumeables - and #G.shop_jokers.highlighted + #G.shop_booster.highlighted + #G.shop_vouchers.highlighted == 1 - and G.shop_jokers.highlighted[1] ~= self - and G.shop_booster.highlighted[1] ~= self - and G.shop_vouchers.highlighted[1] ~= self - end, - use = function(self, card, area, copier) - if not G.GAME.banned_keys then - G.GAME.banned_keys = {} - end -- i have no idea if this is always initialised already tbh - if not G.GAME.cry_banned_pcards then - G.GAME.cry_banned_pcards = {} - end - local a = nil - local c = nil - local _p = nil - if G.shop_jokers.highlighted[1] then - _p = not not G.shop_jokers.highlighted[1].base.value - a = G.shop_jokers - c = G.shop_jokers.highlighted[1] - end - if G.shop_booster.highlighted[1] then - a = G.shop_booster - c = G.shop_booster.highlighted[1] - end - if G.shop_vouchers.highlighted[1] then - a = G.shop_vouchers - c = G.shop_vouchers.highlighted[1] - if c.shop_voucher then - G.GAME.current_round.voucher.spawn[c.config.center.key] = nil - G.GAME.current_round.cry_voucher_edition = nil - G.GAME.current_round.cry_voucher_stickers = - { eternal = false, perishable = false, rental = false, pinned = false, banana = false } - end - end - if c.config.center.rarity == "cry_exotic" then - check_for_unlock({ type = "what_have_you_done" }) - end - - G.GAME.cry_banished_keys[c.config.center.key] = true - - -- blanket ban all boosters of a specific type - if a == G.shop_booster then - local _center = c.config.center - for k, v in pairs(G.P_CENTER_POOLS.Booster) do - if - _center.kind == v.kind - and _center.config.extra == v.config.extra - and _center.config.choose == v.config.choose - then - G.GAME.cry_banished_keys[v.key] = true - end - end - end - - if _p then - for k, v in pairs(G.P_CARDS) do - -- blanket banning ranks here, probably more useful - if v.value == c.base.value then -- and v.suit == c.base.suit - G.GAME.cry_banned_pcards[k] = true - end - end - end - c:start_dissolve() - end, - init = function(self) - -- dumb hook because i don't feel like aggressively patching get_pack to do stuff - -- very inefficient - -- maybe smods should overwrite the function and make it more targetable? - local getpackref = get_pack - function get_pack(_key, _type) - local temp_banned = copy_table(G.GAME.banned_keys) - for k, v in pairs(G.GAME.cry_banished_keys) do - G.GAME.banned_keys[k] = v - end - local ret = getpackref(_key, _type) - G.GAME.banned_keys = copy_table(temp_banned) - return ret - end - end, - -- i was gonna use this function and all but... i don't like the way it does things - -- leaving it here so nobody screams at me - --[[ - keep_on_use = function(self, card) - if card.ability.cry_multiuse <= 1 then - return false - else - card.ability.cry_multiuse = card.ability.cry_multiuse - 1 - delay(0.3) - card:juice_up() - play_sound('tarot1') - card_eval_status_text(card, 'extra', nil, nil, nil, {message = card.ability.cry_multiuse, colour = G.C.SECONDARY_SET.Code}) - return true - end - end, - ]] -} -local spaghetti = { - cry_credits = { - idea = { - "HexaCryonic", - }, - art = { - "HexaCryonic", - }, - code = { - "Math", - }, - }, - dependencies = { - items = { - "set_cry_code", - }, - }, - object_type = "Consumable", - set = "Code", - key = "spaghetti", - name = "cry-Spaghetti", - atlas = "atlasnotjokers", - order = 13, - pos = { - x = 12, - y = 2, - }, - cost = 4, - loc_vars = function(self, info_queue, card) - info_queue[#info_queue + 1] = G.P_CENTERS.e_cry_glitched - info_queue[#info_queue + 1] = { set = "Other", key = "food_jokers" } - end, - can_use = function(self, card) - return true - end, - use = function(self, card, area, copier) - local card = create_card("Food", G.jokers, nil, nil, nil, nil, nil, "cry_spaghetti") - card:set_edition({ - cry_glitched = true, - }) - card:add_to_deck() - G.jokers:emplace(card) + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) end, } +-- ://MACHINECODE +-- Creates a random Glitched consumable local machinecode = { cry_credits = { idea = { @@ -2451,7 +1589,7 @@ local machinecode = { pos = { x = 7, y = 3 }, cost = 3, atlas = "atlasnotjokers", - order = 19, + order = 409, can_use = function(self, card) return true end, @@ -2494,7 +1632,7 @@ local machinecode = { local card = create_card("Consumeables", G.consumeables, nil, nil, nil, nil, k.key) card:set_edition({ cry_glitched = true }) card:add_to_deck() - if Incantation then + if card.setQty then card:setQty(v) end G.consumeables:emplace(card) @@ -2684,7 +1822,6 @@ local machinecode = { config = { object = DynaText({ string = arr, - colours = { G.C.BLACK }, pop_in_rate = 9999999, silent = true, random_element = true, @@ -2696,11 +1833,17 @@ local machinecode = { } end end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, } -local run = { +-- ://Spaghetti +-- Creates a random Glitched food joker +local spaghetti = { cry_credits = { idea = { - "Mjiojio", + "HexaCryonic", }, art = { "HexaCryonic", @@ -2716,411 +1859,39 @@ local run = { }, object_type = "Consumable", set = "Code", - name = "cry-Run", - key = "run", - pos = { x = 12, y = 0 }, - cost = 3, + key = "spaghetti", + name = "cry-Spaghetti", atlas = "atlasnotjokers", - order = 6, - can_use = function(self, card) - return Cryptid.safe_get(G.GAME, "blind", "in_blind") and not G.GAME.USING_RUN - end, - can_bulk_use = true, - use = function(self, card, area, copier) - G.cry_runarea = CardArea( - G.discard.T.x, - G.discard.T.y, - G.discard.T.w, - G.discard.T.h, - { type = "discard", card_limit = 1e100 } - ) - local hand_count = #G.hand.cards - for i = 1, hand_count do - draw_card(G.hand, G.cry_runarea, i * 100 / hand_count, "down", nil, nil, 0.07) - end - G.E_MANAGER:add_event(Event({ - trigger = "immediate", - func = function() - G.GAME.current_round.jokers_purchased = 0 - G.STATE = G.STATES.SHOP - G.GAME.USING_CODE = true - G.GAME.USING_RUN = true - G.GAME.RUN_STATE_COMPLETE = 0 - G.GAME.shop_free = nil - G.GAME.shop_d6ed = nil - G.STATE_COMPLETE = false - G.GAME.current_round.used_packs = {} - return true - end, - })) - end, - init = function(self) - local gfts = G.FUNCS.toggle_shop - G.FUNCS.toggle_shop = function(e) - gfts(e) - if G.GAME.USING_RUN then - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.5, - func = function() - G.GAME.USING_RUN = false - G.GAME.USING_CODE = false - return true - end, - })) - local hand_count = #G.cry_runarea.cards - for i = 1, hand_count do - draw_card(G.cry_runarea, G.hand, i * 100 / hand_count, "up", true) - end - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.5, - func = function() - G.GAME.current_round.used_packs = {} - G.cry_runarea:remove() - G.cry_runarea = nil - G.STATE = G.STATES.SELECTING_HAND - return true - end, - })) - end - end - local gus = Game.update_shop - function Game:update_shop(dt) - gus(self, dt) - if G.GAME.USING_RUN and G.STATE_COMPLETE and G.GAME.RUN_STATE_COMPLETE < 60 then - G.shop.alignment.offset.y = -5.3 - G.GAME.RUN_STATE_COMPLETE = G.GAME.RUN_STATE_COMPLETE + 1 - end - end - local guis = G.UIDEF.shop - function G.UIDEF.shop() - local ret = guis() - if G.GAME.USING_RUN then - G.SHOP_SIGN:remove() - G.SHOP_SIGN = { - remove = function() - return true - end, - alignment = { offset = { y = 0 } }, - } - end - return ret - end - end, -} -local exploit = { - cry_credits = { - idea = { - "Mjiojio", - }, - art = { - "HexaCryonic", - }, - code = { - "Toneblock", - }, - }, - dependencies = { - items = { - "set_cry_code", - }, - }, - object_type = "Consumable", - set = "Code", - key = "exploit", - name = "cry-Exploit", - atlas = "atlasnotjokers", - pos = { - x = 8, - y = 3, - }, + order = 410, + pos = { x = 12, y = 2 }, cost = 4, - order = 28, - config = { cry_multiuse = 2, extra = { enteredhand = "" } }, -- i don't think this ever uses config...? loc_vars = function(self, info_queue, card) - return { vars = { Cryptid.safe_get(card, "ability", "cry_multiuse") or self.config.cry_multiuse } } + info_queue[#info_queue + 1] = G.P_CENTERS.e_cry_glitched + info_queue[#info_queue + 1] = { set = "Other", key = "food_jokers" } end, can_use = function(self, card) return true end, use = function(self, card, area, copier) - G.GAME.USING_CODE = true - G.ENTERED_HAND = "" - G.CHOOSE_HAND = UIBox({ - definition = create_UIBox_exploit(card), - config = { - align = "cm", - offset = { x = 0, y = 10 }, - major = G.ROOM_ATTACH, - bond = "Weak", - instance_type = "POPUP", - }, + local card = create_card("Food", G.jokers, nil, nil, nil, nil, nil, "cry_spaghetti") + card:set_edition({ + cry_glitched = true, }) - G.CHOOSE_HAND.alignment.offset.y = 0 - G.ROOM.jiggle = G.ROOM.jiggle + 1 - G.CHOOSE_HAND:align_to_major() + card:add_to_deck() + G.jokers:emplace(card) end, - init = function(self) - function create_UIBox_exploit(card) - G.E_MANAGER:add_event(Event({ - blockable = false, - func = function() - G.REFRESH_ALERTS = true - return true - end, - })) - local t = create_UIBox_generic_options({ - no_back = true, - colour = HEX("04200c"), - outline_colour = G.C.SECONDARY_SET.Code, - contents = { - { - n = G.UIT.R, - nodes = { - create_text_input({ - colour = G.C.SET.Code, - hooked_colour = darken(copy_table(G.C.SET.Code), 0.3), - w = 4.5, - h = 1, - max_length = 24, - extended_corpus = true, - prompt_text = localize("cry_code_hand"), - ref_table = G, - ref_value = "ENTERED_HAND", - keyboard_offset = 1, - }), - }, - }, - { - n = G.UIT.R, - nodes = { - UIBox_button({ - colour = G.C.SET.Code, - button = "exploit_apply", - label = { localize("cry_code_exploit") }, - minw = 4.5, - focus_args = { snap_to = true }, - }), - }, - }, - { - n = G.UIT.R, - nodes = { - UIBox_button({ - colour = G.C.RED, - button = "exploit_apply_previous", - label = { localize("cry_code_exploit_previous") }, - minw = 4.5, - focus_args = { snap_to = true }, - }), - }, - }, - { - n = G.UIT.R, - nodes = { - UIBox_button({ - colour = G.C.RED, - button = "exploit_cancel", - label = { localize("cry_code_cancel") }, - minw = 4.5, - focus_args = { snap_to = true }, - }), - }, - }, - }, - }) - return t - end - G.FUNCS.exploit_apply_previous = function() - if G.PREVIOUS_ENTERED_HAND then - G.ENTERED_HAND = G.PREVIOUS_ENTERED_HAND or "" - end - G.FUNCS.exploit_apply() - end - G.FUNCS.exploit_apply = function() - local hand_table = { - ["High Card"] = { - "high card", - "high", - "1oak", - "1 of a kind", - "haha one", - }, - ["Pair"] = { - "pair", - "2oak", - "2 of a kind", - "m", - "window", - }, - ["Two Pair"] = { - "two pair", - "2 pair", - "mm", - "pairpair", - "pair of a kind", - }, - ["Three of a Kind"] = { - "three of a kind", - "3 of a kind", - "3oak", - "trips", - "triangle", - }, - ["Straight"] = { - "straight", - "lesbian", - "gay", - "bisexual", - "asexual", - "staircase", - }, - ["Flush"] = { - "flush", - "skibidi", - "toilet", - "floosh", - "monotone", - }, - ["Full House"] = { - "full house", - "full", - "that 70s show", - "modern family", - "family matters", - "the middle", - }, - ["Four of a Kind"] = { - "four of a kind", - "4 of a kind", - "4oak", - "22oakoak", - "quads", - "four to the floor", - }, - ["Straight Flush"] = { - "straight flush", - "strush", - "slush", - "slushie", - "slushy", - "monotone staircase", - }, - ["Five of a Kind"] = { - "five of a kind", - "5 of a kind", - "5oak", - "quints", - }, - ["Flush House"] = { - "flush house", - "flouse", - "outhouse", - "monotone house", - "the grey house", - }, - ["Flush Five"] = { - "flush five", - "fish", - "you know what that means", - "five of a flush", - "monotone fish", - }, - ["cry_Bulwark"] = { - "bulwark", - "flush rock", - "stoned", - "stone flush", - "flush stone", - "rock and stone", - }, - ["cry_Clusterfuck"] = { - "clusterfuck", - "fuck", - "wtf", - "cluster", - "what", - }, - ["cry_UltPair"] = { - "ultimate pair", - "ultpair", - "ult pair", - "pairpairpair", - "flush pair of a kind of a kind", - "2f2oakoak", - "two flush two of a kind of a kind", - }, - ["cry_WholeDeck"] = { - "the entire fucking deck", - "deck", - "tefd", - "fifty-two", - "you are fuck deck", - "deck of a kind", - "the entire deck", - "everything of a kind", - "everything", - }, - } - local current_hand = nil - for k, v in pairs(SMODS.PokerHands) do - local index = v.key - local current_name = G.localization.misc.poker_hands[index] - if not hand_table[v.key] then - hand_table[v.key] = { current_name } - end - end - for i, v in pairs(hand_table) do - for j, k in pairs(v) do - if string.lower(G.ENTERED_HAND) == string.lower(k) then - current_hand = i - end - end - end - if current_hand and G.GAME.hands[current_hand].visible then - G.PREVIOUS_ENTERED_HAND = G.ENTERED_HAND - G.GAME.cry_exploit_override = current_hand - G.FUNCS.exploit_cancel() - return - end - end - G.FUNCS.exploit_cancel = function() - G.CHOOSE_HAND:remove() - G.GAME.USING_CODE = false - end - -- mess with poker hand evaluation - local evaluate_poker_hand_ref = evaluate_poker_hand - function evaluate_poker_hand(hand) - local results = evaluate_poker_hand_ref(hand) - if G.GAME.cry_exploit_override then - if not results[G.GAME.cry_exploit_override][1] then - for _, v in ipairs(G.handlist) do - if results[v][1] then - results[G.GAME.cry_exploit_override] = results[v] - break - end - end - end - end - return results - end - local htuis = G.FUNCS.hand_text_UI_set - G.FUNCS.hand_text_UI_set = function(e) - htuis(e) - if G.GAME.cry_exploit_override then - e.config.object.colours = { G.C.SECONDARY_SET.Code } - else - e.config.object.colours = { G.C.UI.TEXT_LIGHT } - end - e.config.object:update_text() - end + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) end, } -local oboe = { +-- ://Seed +-- Gives any card Rigged +-- (TODO: make it work when used in shop) +local seed = { cry_credits = { idea = { - "HexaCryonic", + "Mjiojio", }, art = { "HexaCryonic", @@ -3136,196 +1907,88 @@ local oboe = { }, object_type = "Consumable", set = "Code", - key = "oboe", - name = "cry-oboe", - atlas = "atlasnotjokers", - order = 10, - config = { extra = { choices = 1 } }, - pos = { - x = 9, - y = 3, - }, + name = "cry-Seed", + key = "seed", + pos = { x = 10, y = 1 }, cost = 4, - can_bulk_use = true, + atlas = "atlasnotjokers", + order = 411, + can_use = function(self, card) + local cards = Cryptid.get_highlighted_cards({ G.jokers, G.hand, G.consumeables, G.pack_cards }, card, 1, 1) + --the card itself and one other card + return #cards == 1 + end, loc_vars = function(self, info_queue, card) - if not card then - return { vars = { self.config.extra.choices, (Cryptid.safe_get(G.GAME, "cry_oboe") or 0) } } - end - return { vars = { card.ability.extra.choices, (Cryptid.safe_get(G.GAME, "cry_oboe") or 0) } } - end, - can_use = function(self, card) - return true + info_queue[#info_queue + 1] = { key = "cry_rigged", set = "Other", vars = {} } end, use = function(self, card, area, copier) - G.GAME.cry_oboe = (G.GAME.cry_oboe or 0) + card.ability.extra.choices - end, - bulk_use = function(self, card, area, copier, number) - G.GAME.cry_oboe = (G.GAME.cry_oboe or 0) + (card.ability.extra.choices * number) - end, -} -local rework = { - cry_credits = { - idea = { - "HexaCryonic", - }, - art = { - "HexaCryonic", - }, - code = { - "Math", - }, - }, - dependencies = { - items = { - "set_cry_code", - }, - }, - object_type = "Consumable", - set = "Code", - key = "rework", - name = "cry-Rework", - atlas = "atlasnotjokers", - order = 25, - no_pool_flag = "beta_deck", - pos = { - x = 10, - y = 3, - }, - cost = 4, - loc_vars = function(self, info_queue) - info_queue[#info_queue + 1] = - { set = "Tag", key = "tag_cry_rework", specific_vars = { "[edition]", "[joker]", "n" } } - return { vars = {} } - end, - can_use = function(self, card) - if not G.GAME.modifiers.cry_beta then - return #G.jokers.highlighted == 1 - and not G.jokers.highlighted[1].ability.eternal - and G.jokers.highlighted[1].ability.name - ~= ("cry-meteor" or "cry-exoplanet" or "cry-stardust" or "cry_cursed" or ("Diet Cola" or Card.get_gameset( - card - ) == "madness")) - else - return #G.jokers.highlighted == 2 - and not G.jokers.highlighted[1].ability.eternal - and G.jokers.highlighted[1].ability.name - ~= ("cry-meteor" or "cry-exoplanet" or "cry-stardust" or "cry_cursed" or ("Diet Cola" or Card.get_gameset( - card - ) == "madness")) - end - end, - use = function(self, card, area, copier) - local jkr = G.jokers.highlighted[1] - local found_index = 1 - if jkr.edition then - for i, v in ipairs(G.P_CENTER_POOLS.Edition) do - if v.key == jkr.edition.key then - found_index = i - break - end + local cards = Cryptid.get_highlighted_cards({ G.jokers, G.hand, G.consumeables, G.pack_cards }, card, 1, 1) + if cards[1] then + cards[1].ability.cry_rigged = true + if cards[1].config.center.key == "j_cry_googol_play" then + check_for_unlock({ type = "googol_play_rigged" }) end end - found_index = found_index + 1 - if found_index > #G.P_CENTER_POOLS.Edition then - found_index = found_index - #G.P_CENTER_POOLS.Edition - end - local tag = Tag("tag_cry_rework") - if not tag.ability then - tag.ability = {} - end - if jkr.config.center.key == "c_base" then - jkr.config.center.key = "j_scholar" - end - tag.ability.rework_key = jkr.config.center.key - tag.ability.rework_edition = G.P_CENTER_POOLS.Edition[found_index].key - add_tag(tag) - --SMODS.Tags.tag_cry_rework.apply(tag, {type = "store_joker_create"}) - G.E_MANAGER:add_event(Event({ - trigger = "before", - delay = 0.75, - func = function() - jkr:start_dissolve() - return true - end, - })) - end, -} -local rework_tag = { - cry_credits = { - idea = { - "HexaCryonic", - }, - art = { - "HexaCryonic", - }, - code = { - "Math", - }, - }, - dependencies = { - items = { - "c_cry_rework", - }, - }, - object_type = "Tag", - atlas = "tag_cry", - name = "cry-Rework Tag", - order = 19, - pos = { x = 0, y = 3 }, - config = { type = "store_joker_create" }, - key = "rework", - ability = { rework_edition = nil, rework_key = nil }, - loc_vars = function(self, info_queue, tag) - local function p(w) - r = "" - local vowels = { "a", "e", "i", "o", "u" } - for i, v in ipairs(vowels) do - if string.sub(string.lower(w), 1, 1) == v then - r = "n" - break - end - end - return r - end - local ed = Cryptid.safe_get(tag, "ability", "rework_edition") - and localize({ type = "name_text", set = "Edition", key = tag.ability.rework_edition }) - or "[" .. string.lower(localize("k_edition")) .. "]" - return { - vars = { - ed, - Cryptid.safe_get(tag, "ability", "rework_key") - and localize({ type = "name_text", set = "Joker", key = tag.ability.rework_key }) - or "[" .. string.lower(localize("k_joker")) .. "]", - string.sub(ed, 1, 1) ~= "[" and p(ed) or "n", - }, - } - end, - apply = function(self, tag, context) - if context.type == "store_joker_create" then - local card = create_card("Joker", context.area, nil, nil, nil, nil, (tag.ability.rework_key or "j_scholar")) - create_shop_card_ui(card, "Joker", context.area) - card:set_edition((tag.ability.rework_edition or "e_foil"), true, nil, true) - card.states.visible = false - tag:yep("+", G.C.FILTER, function() - card:start_materialize() - return true - end) - tag.triggered = true + if cards[1].area == G.hand then G.E_MANAGER:add_event(Event({ trigger = "after", - delay = 0.5, func = function() - save_run() --fixes savescum bugs hopefully? + G.hand:unhighlight_all() return true end, })) - return card end end, - in_pool = function() - return false + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) end, } +-- Rigged sticker, guarantees listed odds (most of the time) +local rigged = { + dependencies = { + items = { + "c_cry_seed", + "set_cry_code", + }, + }, + object_type = "Sticker", + atlas = "sticker", + pos = { x = 6, y = 1 }, + key = "cry_rigged", + no_sticker_sheet = true, + prefix_config = { key = false }, + badge_colour = HEX("14b341"), + order = 605, + draw = function(self, card) --don't draw shine + local notilt = nil + if card.area and card.area.config.type == "deck" then + notilt = true + end + if not G.shared_stickers["cry_rigged2"] then + G.shared_stickers["cry_rigged2"] = + Sprite(0, 0, G.CARD_W, G.CARD_H, G.ASSET_ATLAS["cry_sticker"], { x = 5, y = 1 }) + end -- no matter how late i init this, it's always late, so i'm doing it in the damn draw function + + G.shared_stickers[self.key].role.draw_major = card + G.shared_stickers["cry_rigged2"].role.draw_major = card + + G.shared_stickers[self.key]:draw_shader("dissolve", nil, nil, notilt, card.children.center) + + card.hover_tilt = card.hover_tilt / 2 -- call it spaghetti, but it's what hologram does so... + G.shared_stickers["cry_rigged2"]:draw_shader("dissolve", nil, nil, notilt, card.children.center) + G.shared_stickers["cry_rigged2"]:draw_shader( + "hologram", + nil, + card.ARGS.send_to_shader, + notilt, + card.children.center + ) -- this doesn't really do much tbh, but the slight effect is nice + card.hover_tilt = card.hover_tilt * 2 + end, +} +-- ://Patch +-- Removes all visible debuffs, flips cards face up local patch = { dependencies = { items = { @@ -3337,17 +2000,11 @@ local patch = { key = "patch", name = "cry-patch", atlas = "atlasnotjokers", - order = 26, + order = 412, config = {}, - pos = { - x = 8, - y = 4, - }, + pos = { x = 8, y = 4 }, cost = 4, can_bulk_use = true, - loc_vars = function(self, info_queue, card) - return {} - end, can_use = function(self, card) return true end, @@ -3436,17 +2093,22 @@ local patch = { })) end end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, } -local ctrl_v = { +-- ://Update, TBD, missing art +local cryupdate = { cry_credits = { idea = { - "ItsFlowwey", - }, - art = { "HexaCryonic", }, + art = { + "Gemstonez", + }, code = { - "Foegro", + "Nova", }, }, dependencies = { @@ -3456,90 +2118,299 @@ local ctrl_v = { }, object_type = "Consumable", set = "Code", - key = "ctrl_v", - name = "cry-Ctrl-V", - atlas = "atlasnotjokers", - order = 27, - config = {}, - pos = { - x = 9, - y = 4, - }, + name = "cry-Update", + key = "cryupdate", + pos = { x = 6, y = 4 }, cost = 4, - can_bulk_use = true, - loc_vars = function(self, info_queue, card) - return {} - end, + atlas = "atlasnotjokers", + order = 413, can_use = function(self, card) - return #G.hand.highlighted + #G.consumeables.highlighted == 2 + return false + end, + -- use = function(self, card, area, copier) + + -- end, + -- bulk_use = function(self, card, area, copier, number) + + -- end, +} -- UNIMPLEMENTED +-- Hook:// +-- Applies Hooked to two jokers +local hook = { + cry_credits = { + idea = { + "HexaCryonic", + }, + art = { + "HexaCryonic", + }, + code = { + "Nova", + }, + }, + gameset_config = { + modest = { disabled = true }, + mainline = { disabled = false }, + madness = { disabled = false }, + experimental = { disabled = false }, + }, + dependencies = { + items = { + "set_cry_code", + }, + }, + object_type = "Consumable", + set = "Code", + name = "cry-Hook", + key = "hook", + pos = { x = 7, y = 4 }, + config = {}, + cost = 4, + atlas = "atlasnotjokers", + order = 414, + can_use = function(self, card) + local jokers = Cryptid.get_highlighted_cards({ G.jokers }, card, 2, 2) + return #jokers == 2 + end, + loc_vars = function(self, info_queue, card) + info_queue[#info_queue + 1] = { key = "cry_hooked", set = "Other", vars = { "hooked Joker" } } end, use = function(self, card, area, copier) - if area then - area:remove_from_highlighted(card) - end - if G.hand.highlighted[1] then - G.E_MANAGER:add_event(Event({ - func = function() - local card = copy_card(G.hand.highlighted[1]) - card:add_to_deck() - table.insert(G.playing_cards, card) - G.hand:emplace(card) - playing_card_joker_effects({ card }) - return true - end, - })) - end - if G.consumeables.highlighted[1] then - G.E_MANAGER:add_event(Event({ - func = function() - local card = copy_card(G.consumeables.highlighted[1]) - if card.ability.name and card.ability.name == "cry-Chambered" then - card.ability.extra.num_copies = 1 + local jokers = Cryptid.get_highlighted_cards({ G.jokers }, card, 2, 2) + local card1 = jokers[1] + local card2 = jokers[2] + if card1 and card2 then + if card1.ability.cry_hooked then + for _, v in ipairs(G.jokers.cards) do + if v.sort_id == card1.ability.cry_hook_id then + v.ability.cry_hooked = false end - card:add_to_deck() - if Incantation then - card:setQty(1) + end + end + if card2.ability.cry_hooked then + for _, v in ipairs(G.jokers.cards) do + if v.sort_id == card2.ability.cry_hook_id then + v.ability.cry_hooked = false end - G.consumeables:emplace(card) - return true - end, - })) + end + end + card1.ability.cry_hooked = true + card2.ability.cry_hooked = true + card1.ability.cry_hook_id = card2.sort_id + card2.ability.cry_hook_id = card1.sort_id end end, - bulk_use = function(self, card, area, copier, number) - for i = 1, number do - if area then - area:remove_from_highlighted(card) + init = function(self) + local Cardstart_dissolveRef = Card.start_dissolve + function Card:start_dissolve(dissolve_colours, silent, dissolve_time_fac, no_juice) + if G.jokers then + for i = 1, #G.jokers.cards do + if + (G.jokers.cards[i].ability.cry_hook_id == self.sort_id) + or (G.jokers.cards[i].sort_id == self.ability.cry_hook_id) + then + G.jokers.cards[i].ability.cry_hooked = false + G.jokers.cards[i].ability.cry_hook_id = nil + end + end end - if G.hand.highlighted[1] then - G.E_MANAGER:add_event(Event({ - func = function() - local card = copy_card(G.hand.highlighted[1]) - card:add_to_deck() - G.hand:emplace(card) - return true - end, - })) + Cardstart_dissolveRef(self, dissolve_colours, silent, dissolve_time_fac, no_juice) + end + end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, +} +-- Hooked Sticker +-- When a joker is naturally triggered, Force-Trigger the hooked joker +local hooked = { + dependencies = { + items = { + "set_cry_code", + "c_cry_hook", + }, + }, + object_type = "Sticker", + atlas = "sticker", + pos = { x = 5, y = 3 }, + no_edeck = true, + order = 606, + loc_vars = function(self, info_queue, card) + local var + if not card or not card.ability.cry_hook_id then + var = "[" .. localize("k_joker") .. "]" + else + for i = 1, #G.jokers.cards do + if G.jokers.cards[i].sort_id == card.ability.cry_hook_id then + var = localize({ type = "name_text", set = "Joker", key = G.jokers.cards[i].config.center_key }) + end end - if G.consumeables.highlighted[1] then - G.E_MANAGER:add_event(Event({ - func = function() - local card = copy_card(G.consumeables.highlighted[1]) - if card.ability.name and card.ability.name == "cry-Chambered" then - card.ability.extra.num_copies = 1 - end - card:add_to_deck() - if Incantation then - card:setQty(1) - end - G.consumeables:emplace(card) - return true - end, - })) + var = var or ("[no joker found - " .. (card.ability.cry_hook_id or "nil") .. "]") + end + return { vars = { var or "hooked Joker" } } + end, + key = "cry_hooked", + no_sticker_sheet = true, + prefix_config = { key = false }, + badge_colour = HEX("14b341"), + draw = function(self, card) --don't draw shine + G.shared_stickers[self.key].role.draw_major = card + G.shared_stickers[self.key]:draw_shader("dissolve", nil, nil, nil, card.children.center) + end, + calculate = function(self, card, context) + if + context.other_card == card + and context.post_trigger + and not context.forcetrigger + and not context.other_context.forcetrigger + and not context.other_context.mod_probability + and not context.other_context.fixed_probability + then + for i = 1, #G.jokers.cards do + if G.jokers.cards[i].sort_id == card.ability.cry_hook_id then + local results = Cryptid.forcetrigger(G.jokers.cards[i], context) + if results and results.jokers then + return results.jokers + end + end end end end, } +-- ://Off By One +-- The next opened booster pack has +1/+1 slots/selections +local oboe = { + cry_credits = { + idea = { + "HexaCryonic", + }, + art = { + "HexaCryonic", + }, + code = { + "Math", + }, + }, + dependencies = { + items = { + "set_cry_code", + }, + }, + object_type = "Consumable", + set = "Code", + key = "oboe", + name = "cry-oboe", + atlas = "atlasnotjokers", + order = 415, + config = { extra = { choices = 1 } }, + pos = { x = 9, y = 3 }, + cost = 4, + can_bulk_use = true, + loc_vars = function(self, info_queue, card) + if not card then + return { vars = { math.floor(self.config.extra.choices), (Cryptid.safe_get(G.GAME, "cry_oboe") or 0) } } + end + return { vars = { math.floor(card.ability.extra.choices), (Cryptid.safe_get(G.GAME, "cry_oboe") or 0) } } + end, + can_use = function(self, card) + return true + end, + use = function(self, card, area, copier) + G.GAME.cry_oboe = G.GAME.cry_oboe + math.floor(card.ability.extra.choices) + end, + bulk_use = function(self, card, area, copier, number) + G.GAME.cry_oboe = G.GAME.cry_oboe + (math.floor(card.ability.extra.choices) * number) + end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, +} +-- ://Assemble +-- Add the number of jokers to selected hand's +mult +local assemble = { + cry_credits = { + idea = { + "HexaCryonic", + }, + art = { + "HexaCryonic", + }, + code = { + "Nova", + }, + }, + dependencies = { + items = { + "set_cry_code", + }, + }, + object_type = "Consumable", + set = "Code", + name = "cry-Assemble", + key = "assemble", + pos = { x = 11, y = 5 }, + cost = 4, + atlas = "atlasnotjokers", + order = 416, + can_use = function(self, card) + local aaa = 0 + if Cryptid.enabled("set_cry_poker_hand_stuff") == true and G.PROFILES[G.SETTINGS.profile].cry_none then + aaa = -1 + end + local cards = Cryptid.get_highlighted_cards({ G.hand }, card, aaa + 1, 999) + return (#cards > aaa and #G.jokers.cards > 1) + end, + use = function(self, card, area, copier) + local upgrade_hand + local num = 0 + if G.PROFILES[G.SETTINGS.profile].cry_none then + num = -1 + end + local hand = Cryptid.get_highlighted_cards({ G.hand }, card, num + 1, G.hand.config.highlighted_limit) + if #hand > num and not G.cry_force_use then + upgrade_hand = G.GAME.hands[G.FUNCS.get_poker_hand_info(hand)] + else + G.E_MANAGER:add_event(Event({ + trigger = "after", + func = function() + local text = G.FUNCS.get_poker_hand_info(G.play.cards) + upgrade_hand = G.GAME.hands[text] + or (G.PROFILES[G.SETTINGS.profile].cry_none and G.GAME.hands["cry_None"]) + upgrade_hand.mult = upgrade_hand.mult + #G.jokers.cards + return true + end, + })) + end + if upgrade_hand then + upgrade_hand.mult = upgrade_hand.mult + #G.jokers.cards + G.hand:unhighlight_all() + end + end, + bulk_use = function(self, card, area, copier, number) + local upgrade_hand + local num = 0 + if G.PROFILES[G.SETTINGS.profile].cry_none then + num = -1 + end + if #G.hand.highlighted > num then + upgrade_hand = G.GAME.hands[G.FUNCS.get_poker_hand_info(G.hand.highlighted)] + elseif #G.play.cards > num then + upgrade_hand = G.GAME.hands[G.FUNCS.get_poker_hand_info(G.play.cards)] + end + if upgrade_hand then + upgrade_hand.mult = upgrade_hand.mult + #G.jokers.cards * number + G.hand:unhighlight_all() + end + end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, +} +-- ://Instantiate +-- Draw 2 cards; one with selected card's rank and the other with selected card's suit (if possible) local inst = { cry_credits = { idea = { @@ -3562,37 +2433,29 @@ local inst = { key = "inst", name = "cry-Inst", atlas = "atlasnotjokers", - order = 28, - config = {}, - pos = { - x = 10, - y = 4, - }, + order = 417, + pos = { x = 10, y = 4 }, cost = 4, can_bulk_use = true, loc_vars = function(self, info_queue, card) return {} end, can_use = function(self, card) - local selected_cards = {} - for i = 1, #G.hand.highlighted do - if G.hand.highlighted[i] ~= card then - selected_cards[#selected_cards + 1] = G.hand.highlighted[i] - end - end - return #selected_cards == 1 + local cards = Cryptid.get_highlighted_cards({ G.hand }, card, 1, 1) + return #cards == 1 end, use = function(self, card, area, copier) local same = 0 + local cards = Cryptid.get_highlighted_cards({ G.hand }, card, 1, 1) for i = 1, #G.deck.cards do - if G.deck.cards[i].base.value == G.hand.highlighted[1].base.value then + if G.deck.cards[i].base.value == cards[1].base.value then same = i draw_card(G.deck, G.hand, nil, nil, false, G.deck.cards[i]) break end end for i = 1, #G.deck.cards do - if G.deck.cards[i].base.suit == G.hand.highlighted[1].base.suit and i ~= same then + if G.deck.cards[i].base.suit == cards[1].base.suit and i ~= same then draw_card(G.deck, G.hand, nil, nil, false, G.deck.cards[i]) break end @@ -3601,22 +2464,1725 @@ local inst = { bulk_use = function(self, card, area, copier, number) for j = 1, number do local same = 0 + local cards = Cryptid.get_highlighted_cards({ G.hand }, card, 1, 1) for i = 1, #G.deck.cards do - if G.deck.cards[i].base.value == G.hand.highlighted[1].base.value then + if G.deck.cards[i].base.value == cards[1].base.value then same = i draw_card(G.deck, G.hand, nil, nil, false, G.deck.cards[i]) break end end for i = 1, #G.deck.cards do - if G.deck.cards[i].base.suit == G.hand.highlighted[1].base.suit and i ~= same then + if G.deck.cards[i].base.suit == cards[1].base.suit and i ~= same then draw_card(G.deck, G.hand, nil, nil, false, G.deck.cards[i]) break end end end end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, } +-- ://Revert +-- Loads the game state from the end of the last boss blind, at cash out +local revert = { + cry_credits = { + idea = { + "Mjiojio", + }, + art = { + "HexaCryonic", + }, + code = { + "Math", + }, + }, + dependencies = { + items = { + "set_cry_code", + }, + }, + object_type = "Consumable", + set = "Code", + name = "cry-Revert", + key = "revert", + pos = { x = 10, y = 0 }, + config = {}, + cost = 4, + atlas = "atlasnotjokers", + order = 418, + can_use = function(self, card) + return G.GAME.cry_revert + end, + use = function(self, card, area, copier) + if not G.GAME.cry_revert then + return + end + G.E_MANAGER:add_event( + Event({ + trigger = "after", + delay = G.SETTINGS.GAMESPEED, + func = function() + G:delete_run() + G:start_run({ + savetext = STR_UNPACK(G.GAME.cry_revert), + }) + end, + }), + "other" + ) + end, + init = function(self) + local sr = save_run + function save_run() + --Sneaking this here but hopefully fixes pointer UI crashes + if G.GAME.USING_CODE then + return + end + if G.GAME.round_resets.ante ~= G.GAME.cry_revert_ante then + G.GAME.cry_revert_ante = G.GAME.round_resets.ante + G.GAME.cry_revert = nil + sr() + G.GAME.cry_revert = STR_PACK(G.culled_table) + sr() + end + sr() + end + end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, +} +-- Function:// +-- Saves the last 3 consumables used on first use, every use thereafter creates a copy of all 3 of those +local cryfunction = { + cry_credits = { + idea = { + "HexaCryonic", + }, + art = { + "HexaCryonic", + }, + code = { + "Nova", + }, + }, + dependencies = { + items = { + "set_cry_code", + }, + }, + object_type = "Consumable", + set = "Code", + name = "cry-Function", + key = "cryfunction", + atlas = "atlasnotjokers", + pos = { x = 11, y = 0 }, + cost = 4, + order = 419, + loc_vars = function(self, info_queue, card) + lclze = function(index) + local func_card = (G.GAME.cry_function_cards or G.GAME.cry_last_used_consumeables)[index] + if not func_card then + return "None" + end + for _, group in pairs(G.localization.descriptions) do + if _ ~= "Back" then + for key, card in pairs(group) do + if key == func_card then + return card.name + end + end + end + end + return "None" + end + info_queue[#info_queue + 1] = { + key = "cry_function_sticker_desc", + set = "Other", + vars = { + lclze(1), + lclze(2), + lclze(3), + }, + } + end, + can_use = function(self, card) + return true + end, + use = function(self, card, area, copier) + if #G.consumeables.cards < G.consumeables.config.card_limit then + if not G.GAME.cry_function_cards and #G.GAME.cry_last_used_consumeables == 0 then + G.E_MANAGER:add_event(Event({ + func = function() + local new_card = create_card( + "Code", + G.consumeables, + nil, + nil, + nil, + nil, + "c_cry_cryfunction", + "cry_cryfunction" + ) + new_card:add_to_deck() + G.consumeables:emplace(new_card) + G.GAME.consumeable_buffer = 0 + return true + end, + })) + elseif not G.GAME.cry_function_cards then + G.GAME.cry_function_cards = {} + for i = 1, #G.GAME.cry_function_stupid_workaround do + G.GAME.cry_function_cards[i] = G.GAME.cry_function_stupid_workaround[i] + end + else + G.E_MANAGER:add_event(Event({ + func = function() + local new_card = create_card( + "Consumeables", + G.consumeables, + nil, + nil, + nil, + nil, + G.GAME.cry_function_cards[1], + "cry_cryfunction" + ) + new_card:add_to_deck() + new_card.ability.cry_function_sticker = true + new_card.ability.cry_function_counter = 1 + G.consumeables:emplace(new_card) + G.GAME.consumeable_buffer = 0 + return true + end, + })) + end + end + end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, +} +-- Function:// Sticker +-- When used, creates the next saved Function:// card +local function_sticker = { + dependencies = { + items = { + "set_cry_code", + "c_cry_cryfunction", + }, + }, + object_type = "Sticker", + atlas = "sticker", + pos = { x = 3, y = 5 }, + config = {}, + key = "cry_function_sticker", + no_sticker_sheet = true, + prefix_config = { key = false }, + badge_colour = HEX("14b341"), + order = 607, + draw = function(self, card) --don't draw shine + G.shared_stickers["cry_function_sticker"].role.draw_major = card + G.shared_stickers["cry_function_sticker"]:draw_shader("dissolve", nil, nil, nil, card.children.center) + end, + -- loc_vars = function(self, info_queue, card) + -- info_queue[#info_queue + 1] = { + -- key = "cry_function_sticker_desc", + -- set = "Other", + -- vars = { + -- (G.GAME.cry_function_cards or G.GAME.cry_last_used_consumeables)[1], + -- (G.GAME.cry_function_cards or G.GAME.cry_last_used_consumeables)[2], + -- (G.GAME.cry_function_cards or G.GAME.cry_last_used_consumeables)[3], + -- }, + -- } + -- end, + loc_vars = function(self, info_queue, card) + lclze = function(index) + local func_card = (G.GAME.cry_function_cards or G.GAME.cry_last_used_consumeables)[index] + if not func_card then + return "None" + end + for _, group in pairs(G.localization.descriptions) do + if _ ~= "Back" then + for key, card in pairs(group) do + if key == func_card then + return card.name + end + end + end + end + return "None" + end + return { + key = "cry_function_sticker", + set = "Other", + vars = { + lclze(1), + lclze(2), + lclze(3), + }, + } + end, +} +-- ://Run +-- visit a shop mid-blind +local run = { + cry_credits = { + idea = { + "Mjiojio", + }, + art = { + "HexaCryonic", + }, + code = { + "Math", + }, + }, + dependencies = { + items = { + "set_cry_code", + }, + }, + object_type = "Consumable", + set = "Code", + name = "cry-Run", + key = "run", + pos = { x = 12, y = 0 }, + cost = 3, + atlas = "atlasnotjokers", + order = 420, + can_use = function(self, card) + return Cryptid.safe_get(G.GAME, "blind", "in_blind") and not G.GAME.USING_RUN + end, + can_bulk_use = true, + use = function(self, card, area, copier) + G.cry_runarea = CardArea( + G.discard.T.x, + G.discard.T.y, + G.discard.T.w, + G.discard.T.h, + { type = "discard", card_limit = 1e100 } + ) + local hand_count = #G.hand.cards + for i = 1, hand_count do + draw_card(G.hand, G.cry_runarea, i * 100 / hand_count, "down", nil, nil, 0.07) + end + G.E_MANAGER:add_event(Event({ + trigger = "immediate", + func = function() + G.GAME.current_round.jokers_purchased = 0 + G.STATE = G.STATES.SHOP + G.GAME.USING_CODE = true + G.GAME.USING_RUN = true + G.GAME.RUN_STATE_COMPLETE = 0 + G.GAME.shop_free = nil + G.GAME.shop_d6ed = nil + G.STATE_COMPLETE = false + G.GAME.current_round.used_packs = {} + return true + end, + })) + end, + init = function(self) + local gfts = G.FUNCS.toggle_shop + G.FUNCS.toggle_shop = function(e) + gfts(e) + if G.GAME.USING_RUN then + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.5, + func = function() + G.GAME.USING_RUN = false + G.GAME.USING_CODE = false + return true + end, + })) + local hand_count = #G.cry_runarea.cards + for i = 1, hand_count do + draw_card(G.cry_runarea, G.hand, i * 100 / hand_count, "up", true) + end + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.5, + func = function() + G.GAME.current_round.used_packs = {} + G.cry_runarea:remove() + G.cry_runarea = nil + G.STATE = G.STATES.SELECTING_HAND + return true + end, + })) + end + end + local gus = Game.update_shop + function Game:update_shop(dt) + gus(self, dt) + if G.GAME.USING_RUN and G.STATE_COMPLETE and G.GAME.RUN_STATE_COMPLETE < 60 then + G.shop.alignment.offset.y = -5.3 + G.GAME.RUN_STATE_COMPLETE = G.GAME.RUN_STATE_COMPLETE + 1 + end + end + local guis = G.UIDEF.shop + function G.UIDEF.shop() + local ret = guis() + if G.GAME.USING_RUN then + G.SHOP_SIGN:remove() + G.SHOP_SIGN = { + remove = function() + return true + end, + alignment = { offset = { y = 0 } }, + } + end + return ret + end + end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, +} + +-- ://Declare +-- Create a new Poker hand from selected cards +local declare = { + cry_credits = { + idea = { + "Ronnec", + "cassknows", + }, + art = { + "lord.ruby", + }, + code = { + "lord.ruby", + }, + }, + dependencies = { + items = { + "set_cry_code", + }, + }, + object_type = "Consumable", + set = "Code", + name = "cry-Declare", + key = "declare", + pos = { x = 6, y = 4 }, + cost = 4, + atlas = "atlasnotjokers", + order = 420.5, + loc_vars = function(self, q, card) + return { + vars = { + localize( + ({ + "Straight", + "Flush", + "Full House", + "Full House", + })[(G.GAME.DECLARE_USED or 0) + 1], + "poker_hands" + ), + number_format(3 - (G.GAME.DECLARE_USED or 0)), + }, + } + end, + can_use = function(self, card) + G.GAME.DECLARE_USED = G.GAME.DECLARE_USED or 0 + return (G.GAME.DECLARE_USED or 0) < 3 + end, + use = function(self, card, area, copier) + G.GAME.USING_CODE = true + G.GAME.USING_DECLARE = true + G.ENTERED_CARD = "" + G.CHOOSE_CARD = UIBox({ + definition = create_UIBox_declare(card), + config = { + align = "cm", + offset = { x = 0, y = 10 }, + major = G.ROOM_ATTACH, + bond = "Weak", + instance_type = "POPUP", + }, + }) + G.CHOOSE_CARD.alignment.offset.y = 0 + G.ROOM.jiggle = G.ROOM.jiggle + 1 + G.CHOOSE_CARD:align_to_major() + end, + init = function() + function create_UIBox_declare(card) + G.E_MANAGER:add_event(Event({ + blockable = false, + func = function() + G.REFRESH_ALERTS = true + return true + end, + })) + local t = create_UIBox_generic_options({ + no_back = true, + colour = HEX("04200c"), + outline_colour = G.C.SECONDARY_SET.Code, + contents = { + { + n = G.UIT.R, + nodes = { + create_text_input({ + colour = G.C.SET.Code, + hooked_colour = darken(copy_table(G.C.SET.Code), 0.3), + w = 4.5, + h = 1, + max_length = 100, + extended_corpus = true, + prompt_text = localize("cry_code_enter_hand"), + ref_table = G, + ref_value = "ENTERED_CARD", + keyboard_offset = 1, + }), + }, + }, + { + n = G.UIT.R, + config = { align = "cm" }, + nodes = { + UIBox_button({ + colour = G.C.SET.Code, + button = "declare_apply", + label = { localize("cry_code_with_suits") }, + minw = 4.5, + focus_args = { snap_to = true }, + }), + }, + }, + { + n = G.UIT.R, + config = { align = "cm" }, + nodes = { + UIBox_button({ + colour = G.C.SET.Code, + button = "declare_apply_suitless", + label = { localize("cry_code_without_suits") }, + minw = 4.5, + focus_args = { snap_to = true }, + }), + }, + }, + { + n = G.UIT.R, + config = { align = "cm" }, + nodes = { + UIBox_button({ + colour = G.C.RED, + button = "declare_cancel", + label = { localize("cry_code_cancel") }, + minw = 4.5, + focus_args = { snap_to = true }, + }), + }, + }, + }, + }) + return t + end + G.FUNCS.declare_cancel = function() + if G.CHOOSE_CARD then + G.CHOOSE_CARD:remove() + end + G.GAME.USING_CODE = false + G.GAME.USING_DECLARE = false + end + G.FUNCS.declare_apply = function() + G.GAME.hands["cry_Declare" .. tostring(G.GAME.DECLARE_USED or 0)] = + Cryptid.create_declare_hand(G.hand.highlighted, G.ENTERED_CARD) + G.GAME.DECLARE_USED = (G.GAME.DECLARE_USED or 0) + 1 + G.FUNCS.declare_cancel() + end + G.FUNCS.declare_apply_suitless = function() + G.GAME.hands["cry_Declare" .. tostring(G.GAME.DECLARE_USED or 0)] = + Cryptid.create_declare_hand(G.hand.highlighted, G.ENTERED_CARD, true) + G.GAME.DECLARE_USED = (G.GAME.DECLARE_USED or 0) + 1 + G.FUNCS.declare_cancel() + end + Cryptid.create_declare_hand = function(cards, name, suitless) + if G.ENTERED_CARD == "" then + G.ENTERED_CARD = "cry_Declare" .. tostring(G.GAME.DECLARE_USED or 0) + end + local complexity = #cards + local ranks = {} + local suits = {} + for i, v in pairs(cards) do + if not ranks[v.base.value] then + ranks[v.base.value] = true + end + end + for i, v in pairs(cards) do + if not suits[v.base.suit] and not suitless then + suits[v.base.suit] = true + end + end + local s = #suits - 1 + local r = #ranks - 1 + local mult = math.floor((complexity / 1.41428) ^ 2.25 + s + r) + if mult < 1 then + mult = 1 + end + local chips = math.floor(mult * 9.55) + local l_chips = chips * 0.25 + local l_mult = mult * 0.25 + local declare_cards = {} + for i, v in pairs(cards) do + local card = { + rank = v:get_id() > 0 and v:get_id() or "rankless", + suit = not suitless and (SMODS.has_no_suit(v) and "suitless" or v.base.suit), + } + declare_cards[#declare_cards + 1] = card + end + for i, v in pairs(G.GAME.hands) do + v.order = (v.order or 0) + 1 + end + return { + order = 1, + l_mult = l_mult, + l_chips = l_chips, + mult = mult, + chips = chips, + example = Cryptid.create_declare_example(cards, suitless), + visible = true, + played = 0, + _saved_d_v = true, + played_this_round = 0, + s_mult = mult, + s_chips = chips, + from_declare = true, + declare_cards = declare_cards, + declare_name = G.ENTERED_CARD, + level = 1, + index = G.GAME.DECLARE_USED or 0, + suitless = suitless, + } + end + local localize_ref = localize + function localize(first, second, ...) + if second == "poker_hands" then + if G and G.GAME and G.GAME.hands[first] and G.GAME.hands[first].declare_name then + return G.GAME.hands[first].declare_name + end + end + if second == "poker_hand_descriptions" then + if G and G.GAME and G.GAME.hands[first] and G.GAME.hands[first].suitless then + return localize_ref(first .. "_suitless", second, ...) + end + end + return localize_ref(first, second, ...) + end + local is_visibleref = SMODS.is_poker_hand_visible + function SMODS.is_poker_hand_visible(handname) + if not SMODS.PokerHands[handname] then + return G.GAME.hands[handname] and G.GAME.hands[handname].visible + end + return is_visibleref(handname) + end + function Cryptid.create_declare_example(cards, suitless) + local c = {} + for i, v in pairs(cards) do + local key = SMODS.Suits[v.base.suit].card_key .. "_" .. SMODS.Ranks[v.base.value].card_key + local enhancement = (SMODS.has_no_suit(v) and "m_stone") or (suitless and "m_wild") or nil + c[#c + 1] = { key, true, enhancement = enhancement } + end + return c + end + end, +} + +-- ://Class +-- Change a selected card's enhancement to one of your choosing (or nil) + +local enh_table = { + m_bonus = { "bonus" }, + m_mult = { "mult", "red" }, + m_wild = { "wild", "suit" }, + m_glass = { "glass", "xmult" }, + m_steel = { "steel", "metal", "grey" }, + m_stone = { "stone", "chip", "chips" }, + m_gold = { "gold", "money", "yellow" }, + m_lucky = { "lucky", "rng" }, + m_cry_echo = { "echo", "retrigger", "retriggers" }, + m_cry_abstract = { "abstract", "abstracted", "tadc", "theamazingdigitalcircus", "kaufumo" }, --why him? he was the first person we see get abstracted + m_cry_light = { "light" }, + ccd = { "ccd" }, + null = { "nil" }, +} + +Cryptid.load_enhancement_aliases(enh_table) + +local class = { + cry_credits = { + idea = { + "HexaCryonic", + }, + art = { + "HexaCryonic", + }, + code = { + "Math", + }, + }, + dependencies = { + items = { + "set_cry_code", + }, + }, + object_type = "Consumable", + set = "Code", + key = "class", + name = "cry-Class", + atlas = "atlasnotjokers", + pos = { x = 11, y = 1 }, + cost = 4, + order = 421, + config = { max_highlighted = 1, extra = { enteredrank = "" } }, + loc_vars = function(self, info_queue, card) + return { vars = { Cryptid.safe_get(card, "ability", "max_highlighted") or self.config.max_highlighted } } + end, + use = function(self, card, area, copier) + -- Un-use the card + if not card.ability.cry_multiuse or to_big(card.ability.cry_multiuse) <= to_big(1) then + G.GAME.CODE_DESTROY_CARD = copy_card(card) + G.consumeables:emplace(G.GAME.CODE_DESTROY_CARD) + G.GAME.CODE_DESTROY_CARD.ability.cry_multiuse = nil + end + if card.ability.cry_multiuse then + card.ability.cry_multiuse = card.ability.cry_multiuse + 1 + end + G.GAME.USING_CODE = true + G.GAME.USING_CLASS = card.ability.max_highlighted + G.GAME.ACTIVE_CODE_CARD = G.GAME.CODE_DESTROY_CARD or card + G.FUNCS.overlay_menu({ definition = create_UIBox_class() }) + end, + init = function(self) + local ccl = Card.click + function Card:click() + if G.GAME.USING_CLASS then + if not self.debuff then + G.FUNCS.exit_overlay_menu_code() + delay(3) + local cards = Cryptid.get_highlighted_cards({ G.hand }, {}, 1, G.GAME.USING_CLASS or 1) + for i, v in pairs(cards) do + v:flip() + end + delay(1) + for i, v in pairs(cards) do + v:set_ability(G.P_CENTERS[self.config.center.key]) + end + delay(1) + for i, v in pairs(cards) do + v:flip() + end + G.hand:unhighlight_all() + ccl(self) + -- Re-use the card + if G.GAME.ACTIVE_CODE_CARD then + if + not G.GAME.ACTIVE_CODE_CARD.ability.cry_multiuse + or to_big(G.GAME.ACTIVE_CODE_CARD.ability.cry_multiuse) <= to_big(1) + then + G.GAME.ACTIVE_CODE_CARD:start_dissolve() + else + G.GAME.ACTIVE_CODE_CARD.ability.cry_multiuse = + lenient_bignum(to_big(G.GAME.ACTIVE_CODE_CARD.ability.cry_multiuse) - to_big(1)) + end + end + G.GAME.ACTIVE_CODE_CARD = nil + end + else + ccl(self) + end + end + local emplace_ref = CardArea.emplace + function CardArea:emplace(card, ...) + if G.GAME.USING_CLASS or G.GAME.POINTER_SUBMENU == "Enhancement" then + local c = card.config.center + --no class is exclusive to class and no code is just a generic code cards cant create this thing + if c.hidden or c.noe_doe or c.no_collection or c.no_class or c.no_code then + card.debuff = true + end + end + return emplace_ref(self, card, ...) + end + end, + demicoloncompat = true, + force_use = function(self, card, area) + G.CODE_MAX_HIGHLIGHT = card.ability.max_highlighted + local choices = { + "bonus", + "mult", + "wild", + "glass", + "steel", + "stone", + "gold", + "lucky", + "echo", + "light", + "abstract", + } + for i, v in pairs(Cryptid.get_highlighted_cards({ G.hand }, {}, 1, card.ability.max_highlighted or 1)) do + v:set_ability(pseudorandom_element(choices, pseudoseed("forceclass"))) + end + end, +} +-- ://Global +-- Gives a selected card the Global sticker +local global = { + cry_credits = { + idea = { + "HexaCryonic", + }, + art = { + "Card Art: HexaCryonic", + "Sticker Art: Gemstonez", + }, + code = { + "Nova", + }, + }, + dependencies = { + items = { + "set_cry_code", + }, + }, + object_type = "Consumable", + set = "Code", + name = "cry-global", + key = "global", + pos = { x = 7, y = 5 }, + cost = 4, + atlas = "atlasnotjokers", + order = 422, + can_use = function(self, card) + local cards = Cryptid.get_highlighted_cards({ G.hand }, card, 1, 1) + return #cards == 1 + end, + loc_vars = function(self, info_queue, card) + info_queue[#info_queue + 1] = { key = "cry_global_sticker", set = "Other", vars = {} } + end, + use = function(self, card, area, copier) + if area then + area:remove_from_highlighted(card) + end + local cards = Cryptid.get_highlighted_cards({ G.hand }, card, 1, 1) + if cards[1] then + cards[1].ability.cry_global_sticker = true + end + end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, +} +-- Global sticker +-- Always drawn on blind start or when booster pack opened +-- (before hand drawn, also drawn in packs like celestial that you typically wouldn't) +local global_sticker = { + dependencies = { + items = { + "c_cry_global", + "set_cry_code", + }, + }, + object_type = "Sticker", + atlas = "sticker", + pos = { x = 6, y = 5 }, + key = "cry_global_sticker", + no_sticker_sheet = true, + prefix_config = { key = false }, + badge_colour = HEX("14b341"), + order = 608, + draw = function(self, card) --don't draw shine -- i have no idea what any of this does, someone else can do all that (yes i took it from seed how could you tell) + local notilt = nil + if card.area and card.area.config.type == "deck" then + notilt = true + end + if not G.shared_stickers["cry_global_sticker2"] then + G.shared_stickers["cry_global_sticker2"] = + Sprite(0, 0, G.CARD_W, G.CARD_H, G.ASSET_ATLAS["cry_sticker"], { x = 5, y = 5 }) + end -- no matter how late i init this, it's always late, so i'm doing it in the damn draw function + + G.shared_stickers[self.key].role.draw_major = card + G.shared_stickers["cry_global_sticker2"].role.draw_major = card + + G.shared_stickers[self.key]:draw_shader("dissolve", nil, nil, notilt, card.children.center) + + card.hover_tilt = card.hover_tilt / 2 -- call it spaghetti, but it's what hologram does so... + G.shared_stickers["cry_global_sticker2"]:draw_shader("dissolve", nil, nil, notilt, card.children.center) + G.shared_stickers["cry_global_sticker2"]:draw_shader( + "hologram", + nil, + card.ARGS.send_to_shader, + notilt, + card.children.center + ) -- this doesn't really do much tbh, but the slight effect is nice + card.hover_tilt = card.hover_tilt * 2 + end, + calculate = function(self, card, context) + -- Added by IcyEthics + if context.cry_shuffling_area and context.cardarea == G.deck and context.cry_post_shuffle then + local _targetpos = nil + local _selfpos = nil + + -- Iterate through every card in the deck to find both the location + -- of the stickered card, and the highest placed non-stickered card + for i, _playingcard in ipairs(G.deck.cards) do + if _playingcard == card then + _selfpos = i + elseif not _playingcard.ability.cry_global_sticker then + _targetpos = i + end + end + + if _targetpos == nil then + _targetpos = #G.deck.cards + end + if _selfpos == nil then + _selfpos = #G.deck.cards + end + + -- Swaps the positions of the selected cards + G.deck.cards[_selfpos], G.deck.cards[_targetpos] = G.deck.cards[_targetpos], G.deck.cards[_selfpos] + end + end, +} +-- ://Variable +-- Change 2 selected cards' ranks to one of your choosing +local variable = { + cry_credits = { + idea = { + "HexaCryonic", + }, + art = { + "HexaCryonic", + }, + code = { + "AlexZGreat", + }, + }, + dependencies = { + items = { + "set_cry_code", + }, + }, + object_type = "Consumable", + set = "Code", + key = "variable", + name = "cry-Variable", + atlas = "atlasnotjokers", + pos = { x = 9, y = 1 }, + cost = 4, + order = 423, + config = { max_highlighted = 2, extra = { enteredrank = "" } }, + loc_vars = function(self, info_queue, card) + return { vars = { Cryptid.safe_get(card, "ability", "max_highlighted") or self.config.max_highlighted } } + end, + use = function(self, card, area, copier) + -- Un-use the card + if not card.ability.cry_multiuse or to_big(card.ability.cry_multiuse) <= to_big(1) then + G.GAME.CODE_DESTROY_CARD = copy_card(card) + G.consumeables:emplace(G.GAME.CODE_DESTROY_CARD) + G.GAME.CODE_DESTROY_CARD.ability.cry_multiuse = nil + end + if card.ability.cry_multiuse then + card.ability.cry_multiuse = card.ability.cry_multiuse + 1 + end + G.GAME.USING_CODE = true + G.GAME.USING_VARIABLE = card.ability.max_highlighted + G.GAME.ACTIVE_CODE_CARD = G.GAME.CODE_DESTROY_CARD or card + G.FUNCS.overlay_menu({ definition = create_UIBox_variable_code() }) + end, + init = function(self) + local ccl = Card.click + function Card:click() + if G.GAME.USING_VARIABLE then + if not self.debuff then + G.FUNCS.exit_overlay_menu_code() + delay(3) + local cards = Cryptid.get_highlighted_cards({ G.hand }, {}, 1, G.GAME.USING_VARIABLE or 1) + for i, v in pairs(cards) do + v:flip() + end + delay(1) + for i, v in pairs(cards) do + SMODS.change_base(v, v.base.suit, self.base.value) + end + delay(1) + for i, v in pairs(cards) do + v:flip() + end + G.hand:unhighlight_all() + ccl(self) + -- Re-use the card + if G.GAME.ACTIVE_CODE_CARD then + if + not G.GAME.ACTIVE_CODE_CARD.ability.cry_multiuse + or to_big(G.GAME.ACTIVE_CODE_CARD.ability.cry_multiuse) <= to_big(1) + then + G.GAME.ACTIVE_CODE_CARD:start_dissolve() + else + G.GAME.ACTIVE_CODE_CARD.ability.cry_multiuse = + lenient_bignum(to_big(G.GAME.ACTIVE_CODE_CARD.ability.cry_multiuse) - to_big(1)) + end + end + G.GAME.ACTIVE_CODE_CARD = nil + end + else + ccl(self) + end + end + local emplace_ref = CardArea.emplace + function CardArea:emplace(card, ...) + if G.GAME.USING_VARIABLE or G.GAME.POINTER_SUBMENU == "Rank" then + local c = SMODS.Ranks[card.base.value] or {} + if c.hidden or c.noe_doe or c.no_collection or c.no_variable or c.no_code then + card.debuff = true + else + G.E_MANAGER:add_event(Event({ + trigger = "after", + blocking = false, + func = function() + card.debuff = false + return true + end, + })) + end + end + return emplace_ref(self, card, ...) + end + end, + demicoloncompat = true, + force_use = function(self, card, area) + local choices = { "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A" } + for i, v in pairs(Cryptid.get_highlighted_cards({ G.hand }, {}, 1, card.ability.max_highlighted or 2)) do + SMODS.change_base(v, v.base.suit, pseudorandom_element(choices, pseudoseed("forcevariable"))) + end + end, +} +-- ://Log +-- View one of: +-- Next ante's blinds/vouchers, +-- next 5 cards/packs in shop, +-- draw order for current blind (if in blind), +-- Multi-use 2 +local log = { + cry_credits = { + idea = { + "HexaCryonic", + }, + art = { + "HexaCryonic", + }, + code = { + "lord.ruby", + }, + }, + dependencies = { + items = { + "set_cry_code", + }, + }, + object_type = "Consumable", + set = "Code", + name = "cry-Log", + key = "log", + pos = { x = 12, y = 4 }, + cost = 4, + atlas = "atlasnotjokers", + order = 424, + can_use = function(self, card) + return true + end, + use = function(self, card, area, copier) + G.GAME.USING_LOG = true + + G.GAME.USING_CODE = true + G.CHOOSE_CARD = UIBox({ + definition = create_UIBox_log_opts(), + config = { + align = "cm", + offset = { x = 0, y = 10 }, + major = G.ROOM_ATTACH, + bond = "Weak", + instance_type = "POPUP", + }, + }) + G.CHOOSE_CARD.alignment.offset.y = 0 + G.ROOM.jiggle = G.ROOM.jiggle + 1 + G.CHOOSE_CARD:align_to_major() + end, + init = function() + local get_voucherref = SMODS.get_next_vouchers + function SMODS.get_next_vouchers(vouchers) + if G.GAME.LOG_VOUCHER then + local v = copy_table(G.GAME.LOG_VOUCHER) + if not G.GAME.USING_LOG then + G.GAME.LOG_VOUCHER = nil + end + return v + else + return get_voucherref(vouchers) + end + end + function Cryptid.predict_joker(seed) + local _pool, _pool_key = get_current_pool("Joker", nil, nil, seed) + center = pseudorandom_element(_pool, pseudoseed(_pool_key)) + local it = 1 + while center == "UNAVAILABLE" do + it = it + 1 + center = pseudorandom_element(_pool, pseudoseed(_pool_key .. ("_resample" .. it))) + end + + return center + end + function G.FUNCS.log_antevoucher() + G.FUNCS.log_cancel() + local pseudorandom = copy_table(G.GAME.pseudorandom) + G.GAME.round_resets.ante = G.GAME.round_resets.ante + 1 + local bl = get_new_boss() + G.GAME.round_resets.ante = G.GAME.round_resets.ante - 1 + G.GAME.LOG_BOSS = bl + local voucher = SMODS.get_next_vouchers() + G.GAME.LOG_VOUCHER = voucher + G.GAME.pseudorandom = copy_table(pseudorandom) + if bl then + G.GAME.bosses_used[bl] = (G.GAME.bosses_used[bl] or 1) - 1 + end + G.GAME.USING_CODE = true + G.CHOOSE_CARD = UIBox({ + definition = create_UIBox_log({ + bl and G.localization.descriptions.Blind[bl].name or "None", + voucher + and G.P_CENTERS[voucher[1]] + and localize({ type = "name_text", set = G.P_CENTERS[voucher[1]].set, key = voucher[1] }) + or "None", + }, localize("cry_code_antevoucher")), + config = { + align = "cm", + offset = { x = 0, y = 10 }, + major = G.ROOM_ATTACH, + bond = "Weak", + instance_type = "POPUP", + }, + }) + G.CHOOSE_CARD.alignment.offset.y = 0 + G.ROOM.jiggle = G.ROOM.jiggle + 1 + G.CHOOSE_CARD:align_to_major() + G.GAME.USING_LOG = nil + end + function G.FUNCS.log_nextjokers() + G.FUNCS.log_cancel() + local pseudorandom = copy_table(G.GAME.pseudorandom) + local j = {} + for i = 1, 5 do + local key = Cryptid.predict_joker("sho") + local next_joker = G.P_CENTERS[key] + and localize({ type = "name_text", set = G.P_CENTERS[key].set, key = key }) + or "ERROR" + if next_joker == "ERROR" then + local try = (G.localization.descriptions[G.P_CENTERS[key].set] or {})[key] + try = try and try.name or "[ERROR]" + if type(try or "a") == "table" then + try = try[1] + end + next_joker = try + end + j[#j + 1] = next_joker + end + G.GAME.pseudorandom = copy_table(pseudorandom) + G.GAME.USING_CODE = true + G.CHOOSE_CARD = UIBox({ + definition = create_UIBox_log(j, localize("cry_code_nextjokers")), + config = { + align = "cm", + offset = { x = 0, y = 10 }, + major = G.ROOM_ATTACH, + bond = "Weak", + instance_type = "POPUP", + }, + }) + G.CHOOSE_CARD.alignment.offset.y = 0 + G.ROOM.jiggle = G.ROOM.jiggle + 1 + G.CHOOSE_CARD:align_to_major() + G.GAME.USING_LOG = nil + end + function G.FUNCS.log_nextcards() + G.FUNCS.log_cancel() + local j = {} + for i = 1, 10 do + local card = G.deck.cards[#G.deck.cards + 1 - i] + if card then + j[#j + 1] = localize(card.base.value, "ranks") .. " of " .. localize(card.base.suit, "suits_plural") + end + end + G.GAME.USING_CODE = true + G.CHOOSE_CARD = UIBox({ + definition = create_UIBox_log(j, localize("cry_code_nextcards")), + config = { + align = "cm", + offset = { x = 0, y = 10 }, + major = G.ROOM_ATTACH, + bond = "Weak", + instance_type = "POPUP", + }, + }) + G.CHOOSE_CARD.alignment.offset.y = 0 + G.ROOM.jiggle = G.ROOM.jiggle + 1 + G.CHOOSE_CARD:align_to_major() + G.GAME.USING_LOG = nil + end + function create_UIBox_log_opts() + G.E_MANAGER:add_event(Event({ + blockable = false, + func = function() + G.REFRESH_ALERTS = true + return true + end, + })) + local t = create_UIBox_generic_options({ + no_back = true, + colour = HEX("04200c"), + outline_colour = G.C.SECONDARY_SET.Code, + contents = { + { + n = G.UIT.R, + config = { align = "cm" }, + nodes = { + UIBox_button({ + colour = G.C.SECONDARY_SET.Code, + button = "log_antevoucher", + label = { localize("cry_code_antevoucher") }, + minw = 4.5, + focus_args = { snap_to = true }, + }), + }, + }, + { + n = G.UIT.R, + config = { align = "cm" }, + nodes = { + UIBox_button({ + colour = G.C.SECONDARY_SET.Code, + button = "log_nextjokers", + label = { localize("cry_code_nextjokers") }, + minw = 4.5, + focus_args = { snap_to = true }, + }), + }, + }, + G.GAME.blind and G.GAME.blind.in_blind and G.deck and #(G.deck.cards or {}) > 0 and { + n = G.UIT.R, + config = { align = "cm" }, + nodes = { + UIBox_button({ + colour = G.C.SECONDARY_SET.Code, + button = "log_nextcards", + label = { localize("cry_code_nextcards") }, + minw = 4.5, + focus_args = { snap_to = true }, + }), + }, + } or nil, + { + n = G.UIT.R, + config = { align = "cm" }, + nodes = { + UIBox_button({ + colour = G.C.RED, + button = "log_cancel", + label = { localize("cry_code_exit") }, + minw = 4.5, + focus_args = { snap_to = true }, + }), + }, + }, + }, + }) + return t + end + function create_UIBox_log(options, mtype) + G.E_MANAGER:add_event(Event({ + blockable = false, + func = function() + G.REFRESH_ALERTS = true + return true + end, + })) + local contents = {} + contents[#contents + 1] = { + n = G.UIT.R, + config = { align = "cm" }, + nodes = { + { + n = G.UIT.T, + config = { + text = mtype, + lang = G.LANGUAGES["en-us"], + scale = 0.45, + colour = G.C.WHITE, + shadow = true, + }, + }, + }, + } + for i, v in pairs(options) do + contents[#contents + 1] = { + n = G.UIT.R, + config = { align = "cm" }, + nodes = { + { + n = G.UIT.T, + config = { + text = v, + lang = G.LANGUAGES["en-us"], + scale = 0.45, + colour = G.C.WHITE, + shadow = true, + }, + }, + }, + } + end + contents[#contents + 1] = { + n = G.UIT.R, + config = { align = "cm" }, + nodes = { + UIBox_button({ + colour = G.C.RED, + button = "log_cancel", + label = { localize("cry_code_exit") }, + minw = 4.5, + focus_args = { snap_to = true }, + }), + }, + } + local t = create_UIBox_generic_options({ + no_back = true, + colour = HEX("04200c"), + outline_colour = G.C.SECONDARY_SET.Code, + contents = contents, + }) + return t + end + G.FUNCS.log_cancel = function() + if G.CHOOSE_CARD then + G.CHOOSE_CARD:remove() + end + G.GAME.USING_CODE = false + end + end, + -- bulk_use = function(self, card, area, copier, number) + + -- end, +} +-- ://Quantify +-- Jokerize! an object +local quantify = { + cry_credits = { + idea = { + "HexaCryonic", + }, + art = { + "gemstonez", + }, + code = { + "lord.ruby", + }, + }, + dependencies = { + items = { + "set_cry_code", + }, + }, + object_type = "Consumable", + set = "Code", + name = "cry-Quantify", + key = "quantify", + pos = { x = 9, y = 5 }, + cost = 4, + atlas = "atlasnotjokers", + order = 425, + config = { extra = 1 }, + loc_vars = function(self, queue, card) + return { + vars = { + card.ability.extra, + }, + } + end, + can_use = function(self, card) + local h, t = Cryptid.get_quantify(card) + for i, highlighted in pairs(h) do + if highlighted.children.price then + if to_big(G.GAME.dollars - G.GAME.bankrupt_at) < to_big(highlighted.cost) then + return + end + end + end + return t > 0 and t <= card.ability.extra + end, + use = function(self, card) + for i, v in pairs(Cryptid.get_quantify(card)) do + Cryptid.handle_quantify(v) + end + end, + init = function() + local calculate_ref = Card.calculate_joker + function Card:calculate_joker(context) + local ret, post = calculate_ref(self, context) + if not ret and not post then + if context.joker_main or context.forcetrigger then + if self.config.center.key == "c_base" or self.config.center.set == "Enhanced" then + local enhancement = + eval_card(self, { cardarea = G.play, main_scoring = true, scoring_hand = {} }) + local ret2 = {} + local ret3 = {} + if enhancement then + ret2 = enhancement + end + local hand_enhancement = + eval_card(self, { cardarea = G.hand, main_scoring = true, scoring_hand = {} }) + if hand_enhancement then + ret3 = hand_enhancement + end + for _, tbl in pairs(ret2) do + for i, v in pairs(tbl) do + SMODS.calculate_individual_effect({ [i] = v }, self, i, v, false) + end + end + for _, tbl in pairs(ret3) do + for i, v in pairs(tbl) do + SMODS.calculate_individual_effect({ [i] = v }, self, i, v, false) + end + end + end + if self.config.center.set == "Booster" then + local limit = self.ability.extra + local choose = self.ability.choose + local kind = self.config.center.kind + local kindmap = { + ["Standard"] = "Enhanced", + ["Buffoon"] = "Joker", + ["Arcana"] = "Tarot", + } + kind = kindmap[kind] or kind + if not G.P_CENTER_POOLS[kind] then + kind = "Tarot" + end + for i = 1, G.jokers.config.card_limit - #G.jokers.cards do + if to_big(self.ability.choose) > to_big(0) then + self.ability.choose = self.ability.choose - 1 + local tbl = self.config.center.create_card and self.config.center:create_card(self) + or {} + local card = create_card( + kind or tbl.set, + nil, + tbl.legendary, + tbl.rarity, + tbl.skip_materialize, + tbl.soulable, + tbl.forced_key, + "cry_quantify_booster" + ) + if to_big(self.ability.choose) <= to_big(0) then + self:start_dissolve() + end + G.E_MANAGER:add_event(Event({ + trigger = "before", + func = function() + G.jokers:emplace(card) + return true + end, + })) + end + end + end + end + end + return ret, post + end + local debuff_handref = Blind.debuff_hand + function Blind:debuff_hand(cards, hand, handname, check) + local tbl = {} + for i, v in pairs(G.jokers.cards) do + if v.base.nominal and v.base.suit then + tbl[#tbl + 1] = v + end + end + return debuff_handref(self, Cryptid.table_merge(cards, tbl), hand, handname, check) + end + function Cryptid.get_quantify(card) + local highlighted = {} + local total = 0 + for i, v in pairs(G.I.CARD) do + if v.highlighted and v ~= card then + highlighted[#highlighted + 1] = v + total = total + 1 + end + end + return highlighted, total + end + function Cryptid.handle_quantify(target) + if type(target) == "table" and target.calculate_joker then + local highlighted = target + --removing from jokers just to readd to jokers is pointless + if highlighted and highlighted.area ~= G.consumeables or not G.GAME.modifiers.cry_beta then + if highlighted.children.price then + if to_big(G.GAME.dollars - G.GAME.bankrupt_at) < to_big(highlighted.cost) then + return + end + ease_dollars(-highlighted.cost) + highlighted.children.price:remove() + end + highlighted.area:remove_card(highlighted) + highlighted.children.price = nil + if highlighted.children.buy_button then + highlighted.children.buy_button:remove() + end + highlighted.children.buy_button = nil + remove_nils(highlighted.children) + G.E_MANAGER:add_event(Event({ + func = function() + highlighted:highlight() + return true + end, + })) + G.jokers:emplace(highlighted) + return true + end + end + end + end, +} +-- ://Divide, +-- Halves item costs in shop +local divide = { + cry_credits = { + idea = { + "HexaCryonic", + }, + art = { + "HexaCryonic", + }, + code = { + "Math", + }, + }, + dependencies = { + items = { + "set_cry_code", + }, + }, + object_type = "Consumable", + set = "Code", + key = "divide", + name = "cry-Divide", + atlas = "atlasnotjokers", + order = 426, + pos = { x = 9, y = 2 }, + cost = 4, + can_use = function(self, card) + return G.STATE == G.STATES.SHOP + end, + can_bulk_use = true, + use = function(self, card, area, copier) + for i = 1, #G.shop_jokers.cards do + local c = G.shop_jokers.cards[i] + c.misprint_cost_fac = (c.misprint_cost_fac or 1) * 0.5 + c:set_cost() + end + for i = 1, #G.shop_booster.cards do + local c = G.shop_booster.cards[i] + c.misprint_cost_fac = (c.misprint_cost_fac or 1) * 0.5 + c:set_cost() + end + for i = 1, #G.shop_vouchers.cards do + local c = G.shop_vouchers.cards[i] + c.misprint_cost_fac = (c.misprint_cost_fac or 1) * 0.5 + c:set_cost() + end + end, + bulk_use = function(self, card, area, copier, number) + for i = 1, #G.shop_jokers.cards do + local c = G.shop_jokers.cards[i] + c.misprint_cost_fac = (c.misprint_cost_fac or 1) / (2 ^ number) + c:set_cost() + end + for i = 1, #G.shop_booster.cards do + local c = G.shop_booster.cards[i] + c.misprint_cost_fac = (c.misprint_cost_fac or 1) / (2 ^ number) + c:set_cost() + end + for i = 1, #G.shop_vouchers.cards do + local c = G.shop_vouchers.cards[i] + c.misprint_cost_fac = (c.misprint_cost_fac or 1) / (2 ^ number) + c:set_cost() + end + end, +} +-- ://Multiply +-- Doubles a joker's values until the end of the round (exponentially) +local multiply = { + cry_credits = { + idea = { + "HexaCryonic", + }, + art = { + "HexaCryonic", + }, + code = { + "Math", + }, + }, + dependencies = { + items = { + "set_cry_code", + }, + }, + object_type = "Consumable", + set = "Code", + key = "multiply", + name = "cry-Multiply", + atlas = "atlasnotjokers", + order = 427, + pos = { x = 10, y = 2 }, + cost = 4, + can_use = function(self, card) + local cards = Cryptid.get_highlighted_cards({ G.jokers }, card, 1, 1, function(card) + return not Card.no(card, "immutable", true) + end) + return #cards == 1 + end, + use = function(self, card, area, copier) + local cards = Cryptid.get_highlighted_cards({ G.jokers }, card, 1, 1, function(card) + return not Card.no(card, "immutable", true) + end) + if cards[1] and not cards[1].config.cry_multiply then + cards[1].config.cry_multiply = 1 + end + cards[1].config.cry_multiply = cards[1].config.cry_multiply * 2 + Cryptid.manipulate(cards[1], { value = 2 }) + end, + init = function(self) + --reset Jokers at end of round + local er = end_round + function end_round() + er() + for i = 1, #G.jokers.cards do + if G.jokers.cards[i].config.cry_multiply then + m = G.jokers.cards[i].config.cry_multiply + Cryptid.manipulate(G.jokers.cards[i], { value = 1 / m }) + G.jokers.cards[i].config.cry_multiply = nil + end + end + end + end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, +} + +-- ://Delete +-- Banish a selected card in shop; it will no longer appear normally (can still be created via pointer or other means) +local delete = { + cry_credits = { + idea = { + "Mjiojio", + }, + art = { + "HexaCryonic", + }, + code = { + "Math", + "Toneblock", + }, + }, + dependencies = { + items = { + "set_cry_code", + }, + }, + object_type = "Consumable", + set = "Code", + key = "delete", + name = "cry-Delete", + atlas = "atlasnotjokers", + order = 428, + pos = { x = 11, y = 2 }, + cost = 4, + config = { cry_multiuse = 3 }, + loc_vars = function(self, info_queue, card) + return { vars = { Cryptid.safe_get(card, "ability", "cry_multiuse") or self.config.cry_multiuse } } + end, + can_use = function(self, card) + return G.STATE == G.STATES.SHOP + and card.area == (G.GAME.modifiers.cry_beta and G.jokers or G.consumeables) + and #G.shop_jokers.highlighted + #G.shop_booster.highlighted + #G.shop_vouchers.highlighted == 1 + and (G.shop_jokers.highlighted[1] ~= card and not Cryptid.safe_get( + G, + "shop_jokers", + "highlighted", + 1, + "ability", + "eternal" + )) + and (G.shop_booster.highlighted[1] ~= card and not Cryptid.safe_get( + G, + "shop_booster", + "highlighted", + 1, + "ability", + "eternal" + )) + and ( + G.shop_vouchers.highlighted[1] ~= card + and not Cryptid.safe_get(G, "shop_vouchers", "highlighted", 1, "ability", "eternal") + ) + end, + use = function(self, card, area, copier) + if not G.GAME.cry_banned_pcards then + G.GAME.cry_banned_pcards = {} + end + + local c = G.shop_jokers.highlighted[1] or G.shop_booster.highlighted[1] or G.shop_vouchers.highlighted[1] + + if G.shop_vouchers.highlighted[1] and c.shop_voucher then + G.GAME.current_round.voucher.spawn[c.config.center.key] = nil + G.GAME.current_round.cry_voucher_edition = nil + G.GAME.current_round.cry_voucher_stickers = + { eternal = false, perishable = false, rental = false, pinned = false, banana = false } + end + + if c.config.center.rarity == "cry_exotic" then + check_for_unlock({ type = "what_have_you_done" }) + end + + G.GAME.cry_banished_keys[c.config.center.key] = true + + if not not c.base.value then -- is there a case where ~= nil would fail here? + for k, v in pairs(G.P_CARDS) do + -- bans a specific rank AND suit + if v.value == c.base.value and v.suit == c.base.suit then + G.GAME.cry_banned_pcards[k] = true + end + end + end + c:start_dissolve() + end, +} +-- ://Alt-Tab +-- Creates the current blind's Tag local alttab = { cry_credits = { idea = { @@ -3639,12 +4205,9 @@ local alttab = { key = "alttab", name = "cry-Alttab", atlas = "atlasnotjokers", - order = 28, + order = 429, config = {}, - pos = { - x = 11, - y = 4, - }, + pos = { x = 11, y = 4 }, cost = 4, can_bulk_use = true, loc_vars = function(self, info_queue, card) @@ -3658,8 +4221,9 @@ local alttab = { ret = "???" end end - if next(SMODS.find_card("j_cry_kittyprinter")) then - ret = localize({ type = "name_text", key = "tag_cry_cat", set = "Tag" }) + local tag = Cryptid.get_next_tag() + if tag then + ret = localize({ type = "name_text", key = tag, set = "Tag" }) end return { vars = { ret } } end, @@ -3676,8 +4240,9 @@ local alttab = { play_sound("tarot1") local tag = nil local type = G.GAME.blind:get_type() - if next(SMODS.find_card("j_cry_kittyprinter")) then - tag = Tag("tag_cry_cat") + local tag_key = Cryptid.get_next_tag() + if tag_Key then + tag = Tag(tag_key) elseif type == "Boss" then tag = Tag(get_next_tag_key()) else @@ -3701,7 +4266,10 @@ local alttab = { play_sound("tarot1") local tag = nil local type = G.GAME.blind:get_type() - if type == "Boss" then + local tag_key = Cryptid.get_next_tag() + if tag_key then + tag = Tag(tag_key) + elseif type == "Boss" then tag = Tag(get_next_tag_key()) else tag = Tag(G.GAME.round_resets.blind_tags[type]) @@ -3715,7 +4283,292 @@ local alttab = { })) delay(1.1) end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, } +-- ://Ctrl-V +-- Creates a copy of a selected playing card or consumable +local ctrl_v = { + cry_credits = { + idea = { + "ItsFlowwey", + }, + art = { + "HexaCryonic", + }, + code = { + "Foegro", + }, + }, + dependencies = { + items = { + "set_cry_code", + }, + }, + object_type = "Consumable", + set = "Code", + key = "ctrl_v", + name = "cry-Ctrl-V", + atlas = "atlasnotjokers", + order = 430, + config = {}, + pos = { x = 9, y = 4 }, + cost = 4, + can_bulk_use = true, + loc_vars = function(self, info_queue, card) + return {} + end, + can_use = function(self, card) + local cards = Cryptid.get_highlighted_cards({ G.hand, G.consumeables, G.pack_cards }, card, 1, 1, function(card) + return card.area ~= G.pack_Cards or card.ability.set == "Default" or card.ability.set == "Enhanced" + end) + return #cards == 1 + end, + use = function(self, card, area, copier) + local cards = Cryptid.get_highlighted_cards({ G.hand, G.consumeables, G.pack_cards }, card, 1, 1, function(card) + return card.area ~= G.pack_Cards or card.ability.set == "Default" or card.ability.set == "Enhanced" + end) + if cards[1] then + if cards[1].area == G.hand then + G.E_MANAGER:add_event(Event({ + func = function() + local card = copy_card(cards[1]) + card:add_to_deck() + table.insert(G.playing_cards, card) + G.hand:emplace(card) + playing_card_joker_effects({ card }) + return true + end, + })) + elseif cards[1].area == G.consumeables then + G.E_MANAGER:add_event(Event({ + func = function() + local card = copy_card(cards[1]) + if card.ability.name and card.ability.name == "cry-Chambered" then + card.ability.extra.num_copies = 1 + end + card:add_to_deck() + if Incantation then + card:setQty(1) + end + G.consumeables:emplace(card) + return true + end, + })) + elseif cards[1].area == G.pack_cards then + G.E_MANAGER:add_event(Event({ + func = function() + local card = copy_card(cards[1]) + if card.ability.name and card.ability.name == "cry-Chambered" then + card.ability.extra.num_copies = 1 + end + card:add_to_deck() + if Incantation then + card:setQty(1) + end + + -- Edit by IcyEthics: Needed to choose between not allowing copying playing cards or adding them to deck. Made it so they're added to deck. + if card.ability.set == "Default" or card.ability.set == "Enhanced" then + table.insert(G.playing_cards, card) + G.hand:emplace(card) + playing_card_joker_effects({ card }) + else + G.consumeables:emplace(card) + end + return true + end, + })) + end + end + end, + bulk_use = function(self, card, area, copier, number) + local cards = Cryptid.get_highlighted_cards( + { G.hand, G.consumeables, G.pack_cards }, + cards, + 1, + 1, + function(card) + return card.area ~= G.pack_Cards or card.ability.set == "Default" or card.ability.set == "Enhanced" + end + ) + for i = 1, number do + if cards[1] then + if cards[1].area == G.hand then + G.E_MANAGER:add_event(Event({ + func = function() + local card = copy_card(cards[1]) + card:add_to_deck() + table.insert(G.playing_cards, card) + G.hand:emplace(card) + playing_card_joker_effects({ card }) + return true + end, + })) + elseif cards[1].area == G.consumeables then + G.E_MANAGER:add_event(Event({ + func = function() + local card = copy_card(cards[1]) + if card.ability.name and card.ability.name == "cry-Chambered" then + card.ability.extra.num_copies = 1 + end + card:add_to_deck() + if Incantation then + card:setQty(1) + end + G.consumeables:emplace(card) + return true + end, + })) + elseif cards[1].area == G.pacl_cards then + G.E_MANAGER:add_event(Event({ + func = function() + local card = copy_card(cards[1]) + if card.ability.name and card.ability.name == "cry-Chambered" then + card.ability.extra.num_copies = 1 + end + card:add_to_deck() + if Incantation then + card:setQty(1) + end + + -- Edit by IcyEthics: Needed to choose between not allowing copying playing cards or adding them to deck. Made it so they're added to deck. + if card.ability.set == "Default" or card.ability.set == "Enhanced" then + table.insert(G.playing_cards, card) + G.hand:emplace(card) + playing_card_joker_effects({ card }) + else + G.consumeables:emplace(card) + end + return true + end, + })) + end + end + end + end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, +} +-- ://Reboot +-- Shuffle all cards into deck, then reset Hands and Discards to default values +local reboot = { + cry_credits = { + idea = { + "HexaCryonic", + }, + art = { + "HexaCryonic", + }, + code = { + "Math", + }, + }, + dependencies = { + items = { + "set_cry_code", + }, + }, + object_type = "Consumable", + set = "Code", + name = "cry-Reboot", + key = "reboot", + pos = { x = 9, y = 0 }, + config = {}, + cost = 4, + atlas = "atlasnotjokers", + order = 431, + can_use = function(self, card) + return G.STATE == G.STATES.SELECTING_HAND + end, + use = function(self, card, area, copier) + G.FUNCS.draw_from_hand_to_discard() + G.FUNCS.draw_from_discard_to_deck() + ease_discard( + math.max(0, G.GAME.round_resets.discards + G.GAME.round_bonus.discards) - G.GAME.current_round.discards_left + ) + ease_hands_played( + math.max(1, G.GAME.round_resets.hands + G.GAME.round_bonus.next_hands) - G.GAME.current_round.hands_left + ) + for k, v in pairs(G.playing_cards) do + v.ability.wheel_flipped = nil + end + G.E_MANAGER:add_event(Event({ + trigger = "immediate", + func = function() + G.STATE = G.STATES.DRAW_TO_HAND + G.deck:shuffle("cry_reboot" .. G.GAME.round_resets.ante) + G.deck:hard_set_T() + G.STATE_COMPLETE = false + return true + end, + })) + end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, +} +-- ://; +-- Ends the current non-boss blind, skips cash out +local semicolon = { + cry_credits = { + idea = { + "HexaCryonic", + }, + art = { + "HexaCryonic", + }, + code = { + "WilsontheWolf", + }, + }, + dependencies = { + items = { + "set_cry_code", + }, + }, + object_type = "Consumable", + set = "Code", + name = "cry-Semicolon", + key = "semicolon", + pos = { x = 7, y = 1 }, + config = {}, + cost = 4, + atlas = "atlasnotjokers", + order = 432, + can_use = function(self, card) + return G.STATE == G.STATES.SELECTING_HAND and not G.GAME.blind.boss + end, + use = function(self, card, area, copier) + G.E_MANAGER:add_event( + Event({ + trigger = "immediate", + func = function() + if G.STATE ~= G.STATES.SELECTING_HAND then + return false + end + G.GAME.current_round.semicolon = true + G.STATE = G.STATES.HAND_PLAYED + G.STATE_COMPLETE = true + end_round() + return true + end, + }), + "other" + ) + end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, +} + +-- Automaton (Tarot) +-- Creates a random Code card local automaton = { cry_credits = { idea = { @@ -3739,7 +4592,8 @@ local automaton = { key = "automaton", pos = { x = 12, y = 1 }, config = { create = 1 }, - order = 5, + misprintize_caps = { create = 100 }, + order = 602, atlas = "atlasnotjokers", loc_vars = function(self, info_queue, card) return { vars = { Cryptid.safe_get(card, "ability", "create") or self.config.create } } @@ -3748,12 +4602,13 @@ local automaton = { return #G.consumeables.cards < G.consumeables.config.card_limit or card.area == G.consumeables end, use = function(self, card, area, copier) + local forceuse = G.cry_force_use for i = 1, math.min(card.ability.consumeable.create, G.consumeables.config.card_limit - #G.consumeables.cards) do G.E_MANAGER:add_event(Event({ trigger = "after", delay = 0.4, func = function() - if G.consumeables.config.card_limit > #G.consumeables.cards then + if G.consumeables.config.card_limit > #G.consumeables.cards or forceuse then play_sound("timpani") local _card = create_card("Code", G.consumeables, nil, nil, nil, nil, nil, "cry_automaton") _card:add_to_deck() @@ -3766,46 +4621,13 @@ local automaton = { end delay(0.6) end, -} -local green_seal = { - dependencies = { - items = { - "set_cry_code", - }, - }, - object_type = "Seal", - name = "cry-Green-Seal", - key = "green", - badge_colour = HEX("12f254"), --same as code cards - atlas = "cry_misc", - pos = { x = 1, y = 2 }, - - calculate = function(self, card, context) - if context.cardarea == "unscored" and context.main_scoring then - for k, v in ipairs(context.scoring_hand) do - v.cry_green_incompat = true - end - for k, v in ipairs(context.full_hand) do - if not v.cry_green_incompat then - G.E_MANAGER:add_event(Event({ - func = function() - if G.consumeables.config.card_limit > #G.consumeables.cards then - local c = create_card("Code", G.consumeables, nil, nil, nil, nil, nil, "cry_green_seal") - c:add_to_deck() - G.consumeables:emplace(c) - v:juice_up() - end - return true - end, - })) - end - end - for k, v in ipairs(context.scoring_hand) do - v.cry_green_incompat = nil - end - end + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) end, } +-- Source (Spectral) +-- Gives a selected playing card Green Seal local source = { cry_credits = { idea = { @@ -3820,13 +4642,14 @@ local source = { }, dependencies = { items = { + "set_cry_code", "cry_green", }, }, object_type = "Consumable", set = "Spectral", name = "cry-Source", - order = 9, + order = 603, key = "source", config = { -- This will add a tooltip. @@ -3842,9 +4665,14 @@ local source = { cost = 4, atlas = "atlasnotjokers", pos = { x = 2, y = 4 }, + can_use = function(self, card) + local cards = Cryptid.get_highlighted_cards({ G.hand }, card, 1, card.ability.max_highlighted) + return #cards > 0 and #cards <= to_number(card.ability.max_highlighted) + end, use = function(self, card, area, copier) --Good enough - for i = 1, #G.hand.highlighted do - local highlighted = G.hand.highlighted[i] + local cards = Cryptid.get_highlighted_cards({ G.hand }, {}, 1, 1) + for i = 1, #cards do + local highlighted = cards[i] G.E_MANAGER:add_event(Event({ func = function() play_sound("tarot1") @@ -3873,896 +4701,44 @@ local source = { })) end end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, } -local pointer = { - cry_credits = { - idea = { - "HexaCryonic", - }, - art = { - "HexaCryonic", - }, - code = { - "Math", - }, - }, +-- Green Seal +-- Creates a Code card when played and unscoring +local green_seal = { dependencies = { items = { "set_cry_code", }, }, - object_type = "Consumable", - set = "Spectral", - name = "cry-Pointer", - key = "pointer", - pos = { x = 11, y = 3 }, - hidden = true, - soul_set = "Code", - order = 41, - atlas = "atlasnotjokers", - can_use = function(self, card) - return true - end, - loc_vars = function(self, info_queue, center) - return { vars = { (SMODS.Mods["jen"] or {}).can_load and "and OMEGA consumables " or "" } } - end, - use = function(self, card, area, copier) - G.GAME.USING_CODE = true - G.GAME.USING_POINTER = true - G.ENTERED_CARD = "" - G.CHOOSE_CARD = UIBox({ - definition = create_UIBox_pointer(card), - config = { - align = "cm", - offset = { x = 0, y = 10 }, - major = G.ROOM_ATTACH, - bond = "Weak", - instance_type = "POPUP", - }, - }) - G.CHOOSE_CARD.alignment.offset.y = 0 - G.ROOM.jiggle = G.ROOM.jiggle + 1 - G.CHOOSE_CARD:align_to_major() - check_for_unlock({ cry_used_consumable = "c_cry_pointer" }) - end, - init = function(self) - function create_UIBox_pointer(card) + object_type = "Seal", + name = "cry-Green-Seal", + key = "green", + badge_colour = HEX("12f254"), --same as code cards + atlas = "cry_misc", + pos = { x = 1, y = 2 }, + order = 604, + calculate = function(self, card, context) + if context.cardarea == "unscored" and context.main_scoring then G.E_MANAGER:add_event(Event({ - blockable = false, func = function() - G.REFRESH_ALERTS = true + if G.consumeables.config.card_limit > #G.consumeables.cards then + local c = create_card("Code", G.consumeables, nil, nil, nil, nil, nil, "cry_green_seal") + c:add_to_deck() + G.consumeables:emplace(c) + card:juice_up() + end return true end, })) - local t = create_UIBox_generic_options({ - no_back = true, - colour = HEX("04200c"), - outline_colour = G.C.SECONDARY_SET.Code, - contents = { - { - n = G.UIT.R, - nodes = { - create_text_input({ - colour = G.C.SET.Code, - hooked_colour = darken(copy_table(G.C.SET.Code), 0.3), - w = 4.5, - h = 1, - max_length = 100, - extended_corpus = true, - prompt_text = localize("cry_code_enter_card"), - ref_table = G, - ref_value = "ENTERED_CARD", - keyboard_offset = 1, - }), - }, - }, - { - n = G.UIT.R, - config = { align = "cm" }, - nodes = { - UIBox_button({ - colour = G.C.SET.Code, - button = "pointer_apply", - label = { localize("cry_code_create") }, - minw = 4.5, - focus_args = { snap_to = true }, - }), - }, - }, - { - n = G.UIT.R, - config = { align = "cm" }, - nodes = { - UIBox_button({ - colour = G.C.SET.Code, - button = "your_collection", - label = { localize("b_collection_cap") }, - minw = 4.5, - focus_args = { snap_to = true }, - }), - }, - }, - { - n = G.UIT.R, - config = { align = "cm" }, - nodes = { - UIBox_button({ - colour = G.C.RED, - button = "pointer_apply_previous", - label = { localize("cry_code_create_previous") }, - minw = 4.5, - focus_args = { snap_to = true }, - }), - }, - }, - { - n = G.UIT.R, - config = { align = "cm" }, - nodes = { - UIBox_button({ - colour = G.C.RED, - button = "pointer_cancel", - label = { localize("cry_code_cancel") }, - minw = 4.5, - focus_args = { snap_to = true }, - }), - }, - }, - }, - }) - return t - end - G.FUNCS.pointer_cancel = function() - G.CHOOSE_CARD:remove() - G.GAME.USING_CODE = false - G.GAME.USING_POINTER = false - G.DEBUG_POINTER = false - end - G.FUNCS.pointer_apply_previous = function() - if G.PREVIOUS_ENTERED_CARD then - G.ENTERED_CARD = G.PREVIOUS_ENTERED_CARD or "" - end - G.FUNCS.pointer_apply() - end - local aliases = { - -- Vanilla Jokers - jimbo = "joker", - ["gary mccready"] = "joker", - greedy = "greedy joker", - lusty = "lusty joker", - wrathful = "wrathful joker", - gluttonous = "gluttonous joker", - jolly = "jolly joker", - zany = "zany joker", - mad = "mad joker", - crazy = "crazy joker", - droll = "droll joker", - sly = "sly joker", - wily = "wily joker", - clever = "clever joker", - devious = "devious joker", - crafty = "crafty joker", - half = "half joker", - stencil = "joker stencil", - dagger = "ceremonial dagger", - chaos = "chaos the clown", - fib = "fibonacci", - scary = "scary face", - abstract = "abstract joker", - delayedgrat = "delayed gratification", - banana = "gros michel", - steven = "even steven", - todd = "odd todd", - bus = "ride the bus", - faceless = "faceless joker", - todo = "to do list", - ["to-do"] = "to do list", - square = "square joker", - seance = "séance", - riffraff = "riff-raff", - cloudnine = "cloud 9", - trousers = "spare trousers", - ancient = "ancient joker", - mrbones = "mr. bones", - smeared = "smeared joker", - wee = "wee joker", - oopsall6s = "oops! all 6s", - all6s = "oops! all 6s", - oa6 = "oops! all 6s", - idol = "the idol", - duo = "the duo", - trio = "the trio", - family = "the family", - order = "the order", - tribe = "the tribe", - invisible = "invisible joker", - driverslicense = "driver's license", - burnt = "burnt joker", - caino = "canio", - -- Cryptid Jokers - house = "happy house", - queensgambit = "queen's gambit", - weefib = "weebonacci", - interest = "compound interest", - whip = "the whip", - triplet = "triplet rhythm", - pepper = "chili pepper", - krusty = "krusty the clown", - blurred = "blurred joker", - gofp = "garden of forking paths", - lutn = "light up the night", - nsnm = "no sound, no memory", - nosoundnomemory = "no sound, no memory", - lath = "...like antennas to heaven", - likeantennastoheaven = "...like antennas to heaven", - consumeable = "consume-able", - error = "j_cry_error", - ap = "ap joker", - rng = "rnjoker", - filler = "the filler", - duos = "the duos", - home = "the home", - nuts = "the nuts", - quintet = "the quintet", - unity = "the unity", - swarm = "the swarm", - crypto = "crypto coin", - googol = "googol play card", - googolplay = "googol play card", - google = "googol play card", - googleplay = "googol play card", - googleplaycard = "googol play card", - nostalgicgoogol = "nostalgic googol play card", - nostalgicgoogolplay = "nostalgic googol play card", - nostalgicgoogle = "nostalgic googol play card", - nostalgicgoogleplay = "nostalgic googol play card", - nostalgicgoogleplaycard = "nostalgic googol play card", - oldgoogol = "nostalgic googol play card", - oldgoogolplay = "nostalgic googol play card", - oldgoogle = "nostalgic googol play card", - oldgoogleplay = "nostalgic googol play card", - oldgoogleplaycard = "nostalgic googol play card", - ngpc = "nostalgic googol play card", - localthunk = "supercell", - ["1fa"] = "one for all", - ["jolly?"] = "jolly joker?", - scrabble = "scrabble tile", - oldcandy = "nostalgic candy", - jimbo9000 = "jimbo-tron 9000", - jimbotron9000 = "jimbo-tron 9000", - magnet = "fridge magnet", - weeb = "weebonacci", - potofgreed = "pot of jokes", - flipside = "on the flip side", - bonkers = "bonkers joker", - fuckedup = "fucked-up joker", - foolhardy = "foolhardy joker", - adroit = "adroit joker", - penetrating = "penetrating joker", - treacherous = "treacherous joker", - stronghold = "the stronghold", - thefuck = "the fuck!?", - ["tf!?"] = "the fuck!?", - wtf = "the fuck!?", - clash = "the clash", - astral = "astral in a bottle", - smoothie = "tropical smoothie", - chocodie = "chocolate die", - chocodice = "chocolate die", - chocolatedice = "chocolate die", - cookie = "clicked cookie", - lebronjames = "lebaron james", - lebron = "lebaron james", - lebaron = "lebaron james", - hunting = "hunting season", - clockwork = "clockwork joker", - monopoly = "monopoly money", - notebook = "the motebook", - motebook = "the motebook", - mcdonalds = "fast food m", - code = "code joker", - copypaste = "copy/paste", - translucent = "translucent joker", - circulus = "circulus pistoris", - macabre = "macabre joker", - cat_owl = "cat owl", - --Vouchers - ["overstock+"] = "overstock plus", - directorscut = "director's cut", - ["3rs"] = "the 3 rs", - -- Vanilla Tarots - fool = "the fool", - magician = "the magician", - priestess = "the high priestess", - highpriestess = "the high priestess", - empress = "the empress", - emperor = "the emperor", - hierophant = "the hierophant", - lovers = "the lovers", - chariot = "the chariot", - hermit = "the hermit", - wheeloffortune = "the wheel of fortune", - hangedman = "the hanged man", - devil = "the devil", - tower = "the tower", - star = "the star", - moon = "the moon", - sun = "the sun", - world = "the world", - -- Cryptid Tarots - automaton = "the automaton", - eclipse = "c_cry_eclipse", - -- Planets - x = "planet x", - X = "planet x", - -- Code Cards - pointer = "pointer://", - payload = "://payload", - reboot = "://reboot", - revert = "://revert", - crash = "://crash", - semicolon = ";//", - [";"] = ";//", - malware = "://malware", - seed = "://seed", - variable = "://variable", - class = "://class", - commit = "://commit", - merge = "://merge", - multiply = "://multiply", - divide = "://divide", - delete = "://delete", - machinecode = "://machinecode", - run = "://run", - exploit = "://exploit", - offbyone = "://offbyone", - rework = "://rework", - patch = "://patch", - ctrlv = "://ctrl+v", - ["ctrl+v"] = "://ctrl+v", - ["ctrl v"] = "://ctrl+v", - hook = "hook://", - instantiate = "://INSTANTIATE", - inst = "://INSTANTIATE", - spaghetti = "://spaghetti", - alttab = "://alttab", - -- Tags - topuptag = "top-up tag", - gamblerstag = "gambler's tag", - -- Blinds - ox = "the ox", - wall = "the wall", - wheel = "the wheel", - arm = "the arm", - club = "the club", - fish = "the fish", - psychic = "the psychic", - goad = "the goad", - water = "the water", - window = "the window", - manacle = "the manacle", - eye = "the eye", - mouth = "the mouth", - plant = "the plant", - serpent = "the serpent", - pillar = "the pillar", - needle = "the needle", - head = "the head", - tooth = "the tooth", - flint = "the flint", - mark = "the mark", - oldox = "nostalgic ox", - oldhouse = "nostalgic house", - oldarm = "nostalgic arm", - oldfish = "nostalgic fish", - oldmanacle = "nostalgic manacle", - oldserpent = "nostalgic serpent", - oldpillar = "nostalgic pillar", - oldflint = "nostalgic flint", - oldmark = "nostalgic mark", - tax = "the tax", - trick = "the trick", - joke = "the joke", - hammer = "the hammer", - box = "the box", - windmill = "the windmill", - clock = "the clock", - } - for k, v in pairs(aliases) do - Cryptid.aliases[k] = v - end - G.FUNCS.pointer_apply = function() - local function apply_lower(str) - -- Remove content within {} and any remaining spaces - str = str:gsub("%b{}", ""):gsub("%s+", "") - --this weirdness allows you to get m and M separately - if string.len(str) == 1 then - return str - end - return string.lower(str) - end - local current_card - local entered_card = G.ENTERED_CARD - G.PREVIOUS_ENTERED_CARD = G.ENTERED_CARD - local aliases = Cryptid.aliases - if aliases[apply_lower(entered_card)] then - entered_card = aliases[apply_lower(entered_card)] - end - for i, v in pairs(G.P_CENTERS) do - if v.name and apply_lower(entered_card) == apply_lower(v.name) then - current_card = i - end - if apply_lower(entered_card) == apply_lower(i) then - current_card = i - end - if apply_lower(entered_card) == apply_lower(localize({ type = "name_text", set = v.set, key = i })) then - current_card = i - end - end - if current_card then - local created = false - if - G.P_CENTERS[current_card].set == "Joker" - and ( - G.DEBUG_POINTER - or ( - G.P_CENTERS[current_card].unlocked - and #G.jokers.cards + G.GAME.joker_buffer < G.jokers.config.card_limit - and not G.GAME.banned_keys[current_card] - and (G.P_CENTERS[current_card].rarity ~= "cry_exotic" or #SMODS.find_card("j_jen_p03") > 0) - and not (Jen and Jen.overpowered(G.P_CENTERS[current_card].rarity)) - ) - ) - then - local card = create_card("Joker", G.jokers, nil, nil, nil, nil, current_card) - card:add_to_deck() - G.jokers:emplace(card) - created = true - end - if - G.P_CENTERS[current_card].consumeable - and ( - G.DEBUG_POINTER - or ( - G.P_CENTERS[current_card].set ~= "jen_omegaconsumable" - and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit - and not G.GAME.banned_keys[current_card] - ) - ) - then - local card = create_card("Consumeable", G.consumeables, nil, nil, nil, nil, current_card) - if card.ability.name and card.ability.name == "cry-Chambered" then - card.ability.extra.num_copies = 1 - end - card:add_to_deck() - G.consumeables:emplace(card) - created = true - end - if - G.P_CENTERS[current_card].set == "Voucher" and G.DEBUG_POINTER - or (G.P_CENTERS[current_card].unlocked and not G.GAME.banned_keys[current_card]) - then - local area - if G.STATE == G.STATES.HAND_PLAYED then - if not G.redeemed_vouchers_during_hand then - G.redeemed_vouchers_during_hand = CardArea( - G.play.T.x, - G.play.T.y, - G.play.T.w, - G.play.T.h, - { type = "play", card_limit = 5 } - ) - end - area = G.redeemed_vouchers_during_hand - else - area = G.play - end - local card = create_card("Voucher", area, nil, nil, nil, nil, current_card) - card:start_materialize() - area:emplace(card) - card.cost = 0 - card.shop_voucher = false - local current_round_voucher = G.GAME.current_round.voucher - card:redeem() - G.GAME.current_round.voucher = current_round_voucher - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0, - func = function() - card:start_dissolve() - return true - end, - })) - created = true - end - if - G.P_CENTERS[current_card].set == "Booster" - and (G.DEBUG_POINTER or (not G.GAME.banned_keys[current_card] and (G.P_CENTERS[current_card].name ~= "Exotic Buffoon Pack" or #SMODS.find_card( - "j_jen_p03" - ) ~= 0))) - and G.STATE ~= G.STATES.TAROT_PACK - and G.STATE ~= G.STATES.SPECTRAL_PACK - and G.STATE ~= G.STATES.STANDARD_PACK - and G.STATE ~= G.STATES.BUFFOON_PACK - and G.STATE ~= G.STATES.PLANET_PACK - and G.STATE ~= G.STATES.SMODS_BOOSTER_OPENED - then - local card = create_card("Booster", G.hand, nil, nil, nil, nil, current_card) - card.cost = 0 - card.from_tag = true - G.FUNCS.use_card({ config = { ref_table = card } }) - card:start_materialize() - created = true - end - if created then - G.CHOOSE_CARD:remove() - G.GAME.USING_CODE = false - G.GAME.USING_POINTER = false - G.DEBUG_POINTER = false - return - end - end - for i, v in pairs(G.P_TAGS) do - if v.name and apply_lower(entered_card) == apply_lower(v.name) then - current_card = i - end - if apply_lower(entered_card) == apply_lower(i) then - current_card = i - end - if apply_lower(entered_card) == apply_lower(localize({ type = "name_text", set = v.set, key = i })) then - current_card = i - end - end - if - current_card - and (G.DEBUG_POINTER or (not G.P_CENTERS[current_card] and not G.GAME.banned_keys[current_card])) - then - local created = false - local t = Tag(current_card, nil, "Big") - add_tag(t) - if current_card == "tag_orbital" then - local _poker_hands = {} - for k, v in pairs(G.GAME.hands) do - if v.visible then - _poker_hands[#_poker_hands + 1] = k - end - end - t.ability.orbital_hand = pseudorandom_element(_poker_hands, pseudoseed("cry_pointer_orbital")) - end - if current_card == "tag_cry_rework" then - --tbh this is the most unbalanced part of the card - t.ability.rework_edition = - pseudorandom_element(G.P_CENTER_POOLS.Edition, pseudoseed("cry_pointer_edition")).key - t.ability.rework_key = - pseudorandom_element(G.P_CENTER_POOLS.Joker, pseudoseed("cry_pointer_joker")).key - end - G.CHOOSE_CARD:remove() - G.GAME.USING_CODE = false - G.GAME.USING_POINTER = false - G.DEBUG_POINTER = false - return - end - for i, v in pairs(G.P_BLINDS) do - if v.name and apply_lower(entered_card) == apply_lower(v.name) then - current_card = i - end - if apply_lower(entered_card) == apply_lower(i) then - current_card = i - end - if - apply_lower(entered_card) == apply_lower(localize({ type = "name_text", set = "Blind", key = i })) - then - current_card = i - end - end - if - current_card - and not G.P_CENTERS[current_card] - and not G.P_TAGS[current_card] - and (G.DEBUG_POINTER or not G.GAME.banned_keys[current_card]) - then - local created = false - if not G.GAME.blind or (G.GAME.blind.name == "" or not G.GAME.blind.blind_set) then - --from debugplus - local par = G.blind_select_opts.boss.parent - G.GAME.round_resets.blind_choices.Boss = current_card - - G.blind_select_opts.boss:remove() - G.blind_select_opts.boss = UIBox({ - T = { par.T.x, 0, 0, 0 }, - definition = { - n = G.UIT.ROOT, - config = { - align = "cm", - colour = G.C.CLEAR, - }, - nodes = { - UIBox_dyn_container( - { create_UIBox_blind_choice("Boss") }, - false, - get_blind_main_colour("Boss"), - mix_colours(G.C.BLACK, get_blind_main_colour("Boss"), 0.8) - ), - }, - }, - config = { - align = "bmi", - offset = { - x = 0, - y = G.ROOM.T.y + 9, - }, - major = par, - xy_bond = "Weak", - }, - }) - par.config.object = G.blind_select_opts.boss - par.config.object:recalculate() - G.blind_select_opts.boss.parent = par - G.blind_select_opts.boss.alignment.offset.y = 0 - - for i = 1, #G.GAME.tags do - if G.GAME.tags[i]:apply_to_run({ - type = "new_blind_choice", - }) then - break - end - end - created = true - else - G.GAME.blind:set_blind(G.P_BLINDS[current_card]) - ease_background_colour_blind(G.STATE) - created = true - end - if created then - G.CHOOSE_CARD:remove() - G.GAME.USING_CODE = false - G.GAME.USING_POINTER = false - G.DEBUG_POINTER = false - end - end - if not current_card then -- if card isn't created yet, try playing cards - local words = {} - for i in string.gmatch(string.lower(entered_card), "%S+") do -- not using apply_lower because we actually want the spaces here - table.insert(words, i) - end - - local rank_table = { - { "stone" }, - { "2", "Two", "II" }, - { "3", "Three", "III" }, - { "4", "Four", "IV" }, - { "5", "Five", "V" }, - { "6", "Six", "VI" }, - { "7", "Seven", "VII" }, - { "8", "Eight", "VIII" }, - { "9", "Nine", "IX" }, - { "10", "1O", "Ten", "X", "T" }, - { "J", "Jack" }, - { "Q", "Queen" }, - { "K", "King" }, - { "A", "Ace", "One", "1", "I" }, - } -- ty variable - local _rank = nil - for m = #words, 1, -1 do -- the legendary TRIPLE LOOP, checking from end since rank is most likely near the end - for i, v in pairs(rank_table) do - for j, k in pairs(v) do - if words[m] == string.lower(k) then - _rank = i - break - end - end - if _rank then - break - end - end - if _rank then - break - end - end - if _rank then -- a playing card is going to get created at this point, but we can find additional descriptors - local suit_table = { - ["Spades"] = { "spades" }, - ["Hearts"] = { "hearts" }, - ["Clubs"] = { "clubs" }, - ["Diamonds"] = { "diamonds" }, - } - for k, v in pairs(SMODS.Suits) do - local index = v.key - local current_name = G.localization.misc.suits_plural[index] - if not suit_table[v.key] then - suit_table[v.key] = { string.lower(current_name) } - end - end - -- i'd rather be pedantic and not forgive stuff like "spade", there's gonna be a lot of checks - -- can change that if need be - local enh_table = { - ["m_lucky"] = { "lucky" }, - ["m_mult"] = { "mult" }, - ["m_bonus"] = { "bonus" }, - ["m_wild"] = { "wild" }, - ["m_steel"] = { "steel" }, - ["m_glass"] = { "glass" }, - ["m_gold"] = { "gold" }, - ["m_stone"] = { "stone" }, - ["m_cry_echo"] = { "echo" }, - } - for k, v in pairs(G.P_CENTER_POOLS.Enhanced) do - local index = v.key - local current_name = G.localization.descriptions.Enhanced[index].name - current_name = current_name:gsub(" Card$", "") - if not enh_table[v.key] then - enh_table[v.key] = { string.lower(current_name) } - end - end - local ed_table = { - ["e_base"] = { "base" }, - ["e_foil"] = { "foil" }, - ["e_holo"] = { "holo" }, - ["e_polychrome"] = { "polychrome" }, - ["e_negative"] = { "negative" }, - ["e_cry_mosaic"] = { "mosaic" }, - ["e_cry_oversat"] = { "oversat" }, - ["e_cry_glitched"] = { "glitched" }, - ["e_cry_astral"] = { "astral" }, - ["e_cry_blur"] = { "blurred" }, - ["e_cry_gold"] = { "golden" }, - ["e_cry_glass"] = { "fragile" }, - ["e_cry_m"] = { "jolly" }, - ["e_cry_noisy"] = { "noisy" }, - ["e_cry_double_sided"] = { "double-sided", "double_sided", "double" }, -- uhhh sure - } - for k, v in pairs(G.P_CENTER_POOLS.Edition) do - local index = v.key - local current_name = G.localization.descriptions.Edition[index].name - if not ed_table[v.key] then - ed_table[v.key] = { string.lower(current_name) } - end - end - local seal_table = { - ["Red"] = { "red" }, - ["Blue"] = { "blue" }, - ["Purple"] = { "purple" }, - ["Gold"] = { "gold", "golden" }, -- don't worry we're handling seals differently - ["cry_azure"] = { "azure" }, - ["cry_green"] = { "green" }, - } - local sticker_table = { - ["eternal"] = { "eternal" }, - ["perishable"] = { "perishable" }, - ["rental"] = { "rental" }, - ["pinned"] = { "pinned" }, - ["banana"] = { "banana" }, -- no idea why this evades prefixing - ["cry_rigged"] = { "rigged" }, - ["cry_flickering"] = { "flickering" }, - ["cry_possessed"] = { "possessed" }, - ["cry_absolute"] = { "absolute" }, - } - local function parsley(_table, _word) - for i, v in pairs(_table) do - for j, k in pairs(v) do - if _word == string.lower(k) then - return i - end - end - end - return "" - end - local function to_rank(rrank) - if rrank <= 10 then - return tostring(rrank) - elseif rrank == 11 then - return "Jack" - elseif rrank == 12 then - return "Queen" - elseif rrank == 13 then - return "King" - elseif rrank == 14 then - return "Ace" - end - end - - -- ok with all that fluff out the way now we can figure out what on earth we're creating - - local _seal_att = false - local _suit = "" - local _enh = "" - local _ed = "" - local _seal = "" - local _stickers = {} - for m = #words, 1, -1 do - -- we have a word. figure out what that word is - -- this is dodgy spaghetti but w/ever - local wword = words[m] - if _suit == "" then - _suit = parsley(suit_table, wword) - end - if _enh == "" then - _enh = parsley(enh_table, wword) - if _enh == "m_gold" and _seal_att == true then - _enh = "" - end - end - if _ed == "" then - _ed = parsley(ed_table, wword) - if _ed == "e_cry_gold" and _seal_att == true then - _ed = "" - end - end - if _seal == "" then - _seal = parsley(seal_table, wword) - if _seal == "Gold" and _seal_att == false then - _seal = "" - end - end - local _st = parsley(sticker_table, wword) - if _st then - _stickers[#_stickers + 1] = _st - end - if wword == "seal" or wword == "sealed" then - _seal_att = true - else - _seal_att = false - end -- from end so the next word should describe the seal - end - - -- now to construct the playing card - -- i'm doing this by applying everything but maybe it's a bit janky? - - G.CHOOSE_CARD:remove() - G.GAME.USING_CODE = false - G.GAME.USING_POINTER = false - G.DEBUG_POINTER = false - - G.E_MANAGER:add_event(Event({ - func = function() - G.playing_card = (G.playing_card and G.playing_card + 1) or 1 - local _card = create_card("Base", G.play, nil, nil, nil, nil, nil, "pointer") - SMODS.change_base( - _card, - _suit ~= "" and _suit - or pseudorandom_element( - { "Spades", "Hearts", "Diamonds", "Clubs" }, - pseudoseed("sigil") - ), - _rank > 1 and to_rank(_rank) or nil - ) - if _enh ~= "" then - _card:set_ability(G.P_CENTERS[_enh]) - end - if _rank == 1 then - _card:set_ability(G.P_CENTERS["m_stone"]) - end - if _seal ~= "" then - _card:set_seal(_seal, true, true) - end - if _ed ~= "" then - _card:set_edition(_ed, true, true) - end - for i = 1, #_stickers do - _card.ability[_stickers[i]] = true - if _stickers[i] == "pinned" then - _card.pinned = true - end - end - _card:start_materialize() - G.play:emplace(_card) - table.insert(G.playing_cards, _card) - playing_card_joker_effects({ _card }) - return true - end, - })) - G.E_MANAGER:add_event(Event({ - func = function() - G.deck.config.card_limit = G.deck.config.card_limit + 1 - return true - end, - })) - draw_card(G.play, G.deck, 90, "up", nil) - end - end end end, } +-- Encoded Deck +-- Start with Code Joker and Copy/Paste, all cards in shop are Code cards local encoded = { cry_credits = { idea = { @@ -4785,13 +4761,13 @@ local encoded = { object_type = "Back", name = "cry-Encoded", key = "encoded", - order = 11, + order = 2515, pos = { x = 2, y = 5 }, atlas = "atlasdeck", apply = function(self) - G.GAME.joker_rate = 0 - G.GAME.planet_rate = 0 - G.GAME.tarot_rate = 0 + G.GAME.joker_rate = 1 + G.GAME.planet_rate = 1 + G.GAME.tarot_rate = 1 G.GAME.code_rate = 1e100 G.E_MANAGER:add_event(Event({ func = function() @@ -4832,6 +4808,8 @@ local encoded = { end end, } +-- Code Joker +-- Creates a Negative Code card when starting blind local CodeJoker = { dependencies = { items = { @@ -4850,8 +4828,9 @@ local CodeJoker = { extra_gamesets = { "exp_modest" }, rarity = "cry_epic", cost = 11, - order = 109, + order = 301, blueprint_compat = true, + demicoloncompat = true, atlas = "atlasepic", calculate = function(self, card, context) if @@ -4869,6 +4848,17 @@ local CodeJoker = { card:juice_up(0.3, 0.5) return nil, true end + if context.forcetrigger then + play_sound("timpani") + local card = create_card("Code", G.consumeables, nil, nil, nil, nil) + card:set_edition({ + negative = true, + }) + card:add_to_deck() + G.consumeables:emplace(card) + card:juice_up(0.3, 0.5) + return nil, true + end end, cry_credits = { idea = { @@ -4905,6 +4895,8 @@ local CodeJoker = { end end, } +-- Copy/Paste +-- When a Code card is used, create a copy (once/round modest/mainline) local copypaste = { dependencies = { items = { @@ -4916,22 +4908,19 @@ local copypaste = { name = "cry-copypaste", key = "copypaste", pos = { x = 3, y = 4 }, - order = 110, - immune_to_chemach = true, - config = { extra = { odds = 2, ckt = nil } }, -- what is a ckt + order = 302, + config = { + extra = { + odds = 2, + ckt = nil, + }, + }, -- what is a ckt rarity = "cry_epic", cost = 14, blueprint_compat = true, loc_vars = function(self, info_queue, card) return { - vars = { - card and cry_prob( - math.min(card.ability.extra.odds / 2, card.ability.cry_prob or 1), - card.ability.extra.odds, - card.ability.cry_rigged - ) or 1, - card and card.ability.extra.odds or 2, - }, -- this effectively prevents a copypaste from ever initially misprinting at above 50% odds. still allows rigging/oops + vars = { SMODS.get_probability_vars(card, 1, card.ability.extra.odds, "Copy/Paste") }, key = Cryptid.gameset_loc(self, { madness = "madness", exp_modest = "modest" }), } end, @@ -4970,13 +4959,13 @@ local copypaste = { then if #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then if - pseudorandom("cry_copypaste_joker") - < cry_prob( - math.min(card.ability.extra.odds / 2, card.ability.cry_prob), - card.ability.extra.odds, - card.ability.cry_rigged - ) - / card.ability.extra.odds + SMODS.pseudorandom_probability( + card, + "cry_copypaste_joker", + 1, + card.ability.extra.odds, + "Copy/Paste" + ) then G.E_MANAGER:add_event(Event({ func = function() @@ -5024,23 +5013,30 @@ local copypaste = { }, }, } +-- Cut +-- Destroys a Code card and gains 0.5 Xmult when leaving shop local cut = { dependencies = { items = { "set_cry_code", - "set_cry_misc_joker", }, }, object_type = "Joker", name = "cry-cut", key = "cut", - config = { extra = { Xmult = 1, Xmult_mod = 0.5 } }, + config = { + extra = { + Xmult = 1, + Xmult_mod = 0.5, + }, + }, pos = { x = 2, y = 2 }, rarity = 2, cost = 7, - order = 108, + order = 303, blueprint_compat = true, perishable_compat = false, + demicoloncompat = true, atlas = "atlasthree", calculate = function(self, card, context) if context.ending_shop then @@ -5049,7 +5045,7 @@ local cut = { if G.consumeables.cards[i].ability.set == "Code" and not G.consumeables.cards[i].getting_sliced - and not G.consumeables.cards[i].ability.eternal + and not SMODS.is_eternal(G.consumeables.cards[i]) then destructable_codecard[#destructable_codecard + 1] = G.consumeables.cards[i] end @@ -5060,7 +5056,13 @@ local cut = { if codecard_to_destroy then codecard_to_destroy.getting_sliced = true - card.ability.extra.Xmult = card.ability.extra.Xmult + card.ability.extra.Xmult_mod + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "Xmult", + scalar_value = "Xmult_mod", + message_key = "a_xmult", + colour = G.C.RED, + }) G.E_MANAGER:add_event(Event({ func = function() (context.blueprint_card or card):juice_up(0.8, 0.8) @@ -5068,9 +5070,9 @@ local cut = { return true end, })) - if not (context.blueprint_card or self).getting_sliced then + if not (context.blueprint_card or self).getting_sliced and (not msg or type(msg) == "string") then card_eval_status_text((context.blueprint_card or card), "extra", nil, nil, nil, { - message = localize({ + message = msg or localize({ type = "variable", key = "a_xmult", vars = { number_format(to_big(card.ability.extra.Xmult)) }, @@ -5093,9 +5095,27 @@ local cut = { colour = G.C.MULT, } end + if context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "Xmult", + scalar_value = "Xmult_mod", + message_key = "a_xmult", + colour = G.C.RED, + }) + return { + Xmult_mod = card.ability.extra.Xmult, + colour = G.C.MULT, + } + end end, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.Xmult_mod, center.ability.extra.Xmult } } + return { + vars = { + number_format(center.ability.extra.Xmult_mod), + number_format(center.ability.extra.Xmult), + }, + } end, cry_credits = { idea = { @@ -5109,11 +5129,12 @@ local cut = { }, }, } +-- Blender +-- Creates a random Consumeable when Code card used local blender = { dependencies = { items = { "set_cry_code", - "set_cry_misc_joker", }, }, object_type = "Joker", @@ -5123,8 +5144,9 @@ local blender = { rarity = 1, cost = 5, blueprint_compat = true, + demicoloncompat = true, atlas = "atlasthree", - order = 111, + order = 304, calculate = function(self, card, context) if context.using_consumeable @@ -5137,6 +5159,11 @@ local blender = { G.consumeables:emplace(card) end end + if context.forcetrigger then + local card = create_card("Consumeables", G.consumeables, nil, nil, nil, nil, nil, "cry_blender") + card:add_to_deck() + G.consumeables:emplace(card) + end end, cry_credits = { idea = { @@ -5150,41 +5177,54 @@ local blender = { }, }, } +-- Python +-- Gains 0.15 Xmult when Code card used local python = { dependencies = { items = { "set_cry_code", - "set_cry_misc_joker", }, }, object_type = "Joker", name = "cry-python", key = "python", - config = { extra = { Xmult = 1, Xmult_mod = 0.15 } }, + config = { + extra = { + Xmult = 1, + Xmult_mod = 0.15, + }, + }, pos = { x = 4, y = 2 }, rarity = 2, cost = 7, blueprint_compat = true, perishable_compat = false, + demicoloncompat = true, atlas = "atlasthree", - order = 112, + order = 305, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.Xmult_mod, center.ability.extra.Xmult } } + return { + vars = { + number_format(center.ability.extra.Xmult_mod), + number_format(center.ability.extra.Xmult), + }, + } end, calculate = function(self, card, context) if context.using_consumeable and context.consumeable.ability.set == "Code" and not context.consumeable.beginning_end + and not context.blueprint then - card.ability.extra.Xmult = card.ability.extra.Xmult + card.ability.extra.Xmult_mod + card.ability.extra.Xmult = lenient_bignum(to_big(card.ability.extra.Xmult) + card.ability.extra.Xmult_mod) G.E_MANAGER:add_event(Event({ func = function() card_eval_status_text(card, "extra", nil, nil, nil, { message = localize({ type = "variable", key = "a_xmult", - vars = { card.ability.extra.Xmult }, + vars = { number_format(card.ability.extra.Xmult) }, }), }) return true @@ -5194,8 +5234,23 @@ local python = { end if context.joker_main and (to_big(card.ability.extra.Xmult) > to_big(1)) then return { - message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.Xmult } }), - Xmult_mod = card.ability.extra.Xmult, + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), + } + end + if context.forcetrigger then + card.ability.extra.Xmult = lenient_bignum(to_big(card.ability.extra.Xmult) + card.ability.extra.Xmult_mod) + return { + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), } end end, @@ -5213,49 +5268,61 @@ local python = { } local code_cards = { code, + --packs pack1, pack2, packJ, packM, console, + --not codes automaton, green_seal, source, - pointer, cut, blender, python, - payload, - reboot, - revert, - crash, - semicolon, - malware, - seed, - rigged, - --hook, - hooked, - variable, - class, - commit, - merge, - multiply, - divide, - delete, - machinecode, - run, - exploit, - oboe, - rework, - rework_tag, - patch, - ctrl_v, - inst, - alttab, - encoded, - spaghetti, CodeJoker, copypaste, + encoded, + --codes + crash, + keygen, + payload, + exploit, + malware, + crynperror, + rework, + rework_tag, + merge, + commit, + machinecode, + spaghetti, + seed, + rigged, + patch, + hook, + hooked, + oboe, + assemble, + inst, + revert, + cryfunction, + function_sticker, + run, + declare, + class, + global, + global_sticker, + variable, + log, + quantify, + divide, + multiply, + delete, + alttab, + ctrl_v, + reboot, + semicolon, } return { name = "Code Cards", diff --git a/Cryptid/items/deck.lua b/Cryptid/items/deck.lua index 05eee87..cfc49f7 100644 --- a/Cryptid/items/deck.lua +++ b/Cryptid/items/deck.lua @@ -55,34 +55,6 @@ local equilibrium = { apply = function(self) G.GAME.modifiers.cry_equilibrium = true end, - init = function(self) - local gp = get_pack - function get_pack(k, t) - if G.GAME.modifiers.cry_equilibrium then - if not P_CRY_ITEMS then - P_CRY_ITEMS = {} - local valid_pools = { "Joker", "Consumeables", "Voucher", "Booster" } - for _, id in ipairs(valid_pools) do - for k, v in pairs(G.P_CENTER_POOLS[id]) do - if not Cryptid.no(v, "doe", k) then - P_CRY_ITEMS[#P_CRY_ITEMS + 1] = v.key - end - end - end - for k, v in pairs(G.P_CARDS) do - if not Cryptid.no(v, "doe", k) then - P_CRY_ITEMS[#P_CRY_ITEMS + 1] = v.key - end - end - end - return G.P_CENTERS[pseudorandom_element( - P_CRY_ITEMS, - pseudoseed("cry_equipackbrium" .. G.GAME.round_resets.ante) - )] - end - return gp(k, t) - end - end, unlocked = false, check_for_unlock = function(self, args) if Cryptid.safe_get(G, "jokers") then @@ -147,13 +119,22 @@ local infinite = { name = "cry-Infinite", key = "infinite", order = 2, - config = { cry_highlight_limit = 1e20, hand_size = 1 }, + config = { hand_size = 1 }, pos = { x = 3, y = 0 }, atlas = "atlasdeck", - apply = function(self) - G.GAME.modifiers.cry_highlight_limit = self.config.cry_highlight_limit - end, unlocked = false, + apply = function(self) + G.GAME.infinitedeck = true + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.7, + func = function() + SMODS.change_play_limit(1e6) + SMODS.change_discard_limit(1e6) + return true + end, + })) + end, check_for_unlock = function(self, args) if args.type == "hand_contents" then if #args.cards >= 6 then @@ -377,17 +358,26 @@ local legendary = { }, name = "cry-Legendary", key = "legendary", - config = { cry_legendary = true, cry_legendary_rate = 0.2 }, + config = { cry_legendary = true, cry_legendary_rate = 5 }, pos = { x = 0, y = 6 }, atlas = "atlasdeck", order = 15, + loc_vars = function(self, info_queue, center) + return { vars = { SMODS.get_probability_vars(self, 1, self.config.cry_legendary_rate, "Legendary Deck") } } + end, calculate = function(self, back, context) if context.context == "eval" and Cryptid.safe_get(G.GAME, "last_blind", "boss") then if G.jokers then if #G.jokers.cards < G.jokers.config.card_limit then - local legendary_poll = pseudorandom(pseudoseed("cry_legendary")) - legendary_poll = legendary_poll / (G.GAME.probabilities.normal or 1) - if legendary_poll < self.config.cry_legendary_rate then + if + SMODS.pseudorandom_probability( + self, + "cry_legendary", + 1, + self.config.cry_legendary_rate, + "Legendary Deck" + ) + then local card = create_card("Joker", G.jokers, true, 4, nil, nil, nil, "") card:add_to_deck() card:start_materialize() @@ -460,18 +450,21 @@ local critical = { name = "cry-Critical", key = "critical", order = 10, - config = { cry_crit_rate = 0.25, cry_crit_miss_rate = 0.125 }, + config = { cry_crit_rate = 4, cry_crit_miss_rate = 8 }, pos = { x = 4, y = 5 }, atlas = "atlasdeck", loc_vars = function(self, info_queue, center) - return { vars = { G.GAME.probabilities.normal or 1 } } + local _, aaa = SMODS.get_probability_vars(self, 1, self.config.cry_crit_miss_rate, "Critical Deck") + return { vars = { SMODS.get_probability_vars(self, 1, self.config.cry_crit_rate, "Critical Deck"), aaa } } end, calculate = function(self, card, context) if context.final_scoring_step then + local aaa = + SMODS.pseudorandom_probability(self, "cry_critical", 1, self.config.cry_crit_rate, "Critical Deck") + local bbb = + SMODS.pseudorandom_probability(self, "cry_critical", 1, self.config.cry_crit_miss_rate, "Critical Deck") local check - local crit_poll = pseudorandom(pseudoseed("cry_critical")) - crit_poll = crit_poll / (G.GAME.probabilities.normal or 1) - if crit_poll < self.config.cry_crit_rate then + if aaa then check = 2 G.E_MANAGER:add_event(Event({ func = function() @@ -487,7 +480,7 @@ local critical = { return true end, })) - elseif crit_poll < self.config.cry_crit_rate + self.config.cry_crit_miss_rate then + elseif bbb then check = 0.5 G.E_MANAGER:add_event(Event({ func = function() @@ -552,9 +545,7 @@ local glowing = { if context.context == "eval" and Cryptid.safe_get(G.GAME, "last_blind", "boss") then for i = 1, #G.jokers.cards do if not Card.no(G.jokers.cards[i], "immutable", true) then - Cryptid.with_deck_effects(G.jokers.cards[i], function(card) - Cryptid.misprintize(card, { min = 1.25, max = 1.25 }, nil, true) - end) + Cryptid.manipulate(G.jokers.cards[i], { value = 1.25 }) end end end @@ -697,8 +688,8 @@ local antimatter = { key = "antimatter", config = { cry_antimatter = true, - cry_crit_rate = 0.25, --Critical Deck - cry_legendary_rate = 0.2, --Legendary Deck + cry_crit_rate = 4, --Critical Deck + cry_legendary_rate = 5, --Legendary Deck -- Enhanced Decks cry_force_enhancement = "random", cry_force_edition = "random", @@ -882,7 +873,16 @@ local antimatter = { ~= 0 or skip then - G.GAME.modifiers.cry_highlight_limit = 1e20 + G.GAME.infinitedeck = true + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.7, + func = function() + SMODS.change_play_limit(1e6) + SMODS.change_discard_limit(1e6) + return true + end, + })) G.GAME.starting_params.hand_size = G.GAME.starting_params.hand_size + 1 end -- Wormhole deck @@ -986,8 +986,6 @@ local antimatter = { function Cryptid.antimatter_trigger_final_scoring(self, context, skip) if context.context == "final_scoring_step" then - local crit_poll = pseudorandom(pseudoseed("cry_critical")) - crit_poll = crit_poll / (G.GAME.probabilities.normal or 1) --Critical Deck if ( @@ -997,7 +995,15 @@ local antimatter = { ~= 0 or skip then - if crit_poll < self.config.cry_crit_rate then + if + SMODS.pseudorandom_probability( + self, + "cry_critical", + 1, + self.config.cry_crit_rate, + "Antimatter Deck" + ) + then context.mult = context.mult ^ 2 update_hand_text({ delay = 0 }, { mult = context.mult, chips = context.chips }) G.E_MANAGER:add_event(Event({ @@ -1090,9 +1096,7 @@ local antimatter = { or skip then for i = 1, #G.jokers.cards do - Cryptid.with_deck_effects(G.jokers.cards[i], function(card) - Cryptid.misprintize(card, { min = 1.25, max = 1.25 }, nil, true) - end) + Cryptid.manipulate(G.jokers.cards[i], { value = 1.25 }) end end --Legendary Deck @@ -1112,9 +1116,15 @@ local antimatter = { or skip then if #G.jokers.cards < G.jokers.config.card_limit then - local legendary_poll = pseudorandom(pseudoseed("cry_legendary")) - legendary_poll = legendary_poll / (G.GAME.probabilities.normal or 1) - if legendary_poll < self.config.cry_legendary_rate then + if + SMODS.pseudorandom_probability( + self, + "cry_legendary", + 1, + self.config.cry_legendary_rate, + "Antimatter Deck" + ) + then local card = create_card("Joker", G.jokers, true, 4, nil, nil, nil, "") card:add_to_deck() card:start_materialize() @@ -1234,7 +1244,7 @@ local antimatter = { unlocked = false, check_for_unlock = function(self, args) if args.type == "win_deck" then - if get_deck_win_stake("b_cry_blank") > 0 and get_deck_win_stake() >= 8 then + if get_deck_win_stake("b_cry_blank") >= 8 then unlock_card(self) end end diff --git a/Cryptid/items/enhanced.lua b/Cryptid/items/enhanced.lua index 8c75dbb..cde6151 100644 --- a/Cryptid/items/enhanced.lua +++ b/Cryptid/items/enhanced.lua @@ -1,5 +1,3 @@ ---Move all the stuff in here into atlasdeck.png later ---Also a lot of the edition decks have wrong proportions so those also need to get fixed local atlasedition = { object_type = "Atlas", key = "atlaseditiondeck", @@ -78,7 +76,7 @@ Cryptid.edeck_atlas_update = function(self) if not sprite then error(self.edeck_type) end - local enh_info = { Cryptid.enhanced_deck_info(self) } + local enh_info = { Cryptid.enhanced_deck_info(G.cry_edeck_center and self or {}) } sprite = sprite[enh_info[sprite.order]] or sprite.default self.atlas, self.pos = sprite.atlas, sprite.pos return sprite @@ -96,13 +94,13 @@ local e_deck = { order = 17, pos = { x = 5, y = 2 }, loc_vars = function(self, info_queue, center) - local aaa = Cryptid.enhanced_deck_info(self) + local aaa = Cryptid.enhanced_deck_info(G.cry_edeck_center and self or {}) return { vars = { localize({ type = "name_text", set = "Edition", key = "e_" .. aaa }) } } end, edeck_type = "edition", config = { cry_no_edition_price = true }, apply = function(self) - local aaa = Cryptid.enhanced_deck_info(self) + local aaa = Cryptid.enhanced_deck_info({}) G.GAME.modifiers.cry_force_edition = aaa --Ban Edition tags (They will never redeem) for k, v in pairs(G.P_TAGS) do @@ -327,20 +325,7 @@ return { init = function() local sa = Card.set_ability function Card:set_ability(center, y, z) - --adding immutable to cards because - -- A they are hardcoded and unaffected by misprintize but still have a description that changes because of it - -- B so they ignore misprintize in order to keep vanilla descripton accurate (ex hack shouldn't be able to trigger more than once) - -- C so Gemini doesn't say they are compatible when they are not - -- D Invisible Joker - - if - center - and center.name - == ("Fortune Teller" or "Shoot the Moon" or "Riff-raff" or "Chaos the Clown" or "Dusk" or "Mime" or "Hack" or "Sock and Buskin" or "Invisible Joker" or "Swashbuckler" or "Smeared Joker" or "Certificate" or "Mr. Bones" or "Diet Cola" or "Luchador" or "Midas Mask" or "Shortcut" or "Seance" or "Superposition" or "Sixth Sense" or "DNA" or "Splash" or "Supernova" or "Pareidolia" or "Raised Fist" or "Marble Joker" or "Four Fingers" or "Joker Stencil" or "Showman" or "Blueprint" or "Oops! All 6s" or "Brainstorm" or "Cartomancer" or "Astronomer" or "Burnt Joker" or "Chicot" or "Perkeo") - then - self.config.center.immutable = true - end - if Cryptid.safe_get(center, "name") == "Default Base" then -- scuffed + if not G.SETTINGS.paused and Cryptid.safe_get(center, "name") == "Default Base" then -- scuffed return sa( self, (not self.no_forced_enhancement and G.GAME.modifiers.cry_force_enhancement) @@ -355,7 +340,7 @@ return { end local se = Card.set_edition function Card:set_edition(edition, y, z, force) - if not force then + if not force and not G.SETTINGS.paused then return se( self, (not self.no_forced_edition and G.GAME.modifiers.cry_force_edition) @@ -369,11 +354,19 @@ return { end local ss = Card.set_seal function Card:set_seal(seal, y, z) - return ss(self, not self.no_forced_seal and G.GAME.modifiers.cry_force_seal or seal, y, z) + return ss( + self, + not self.no_forced_seal and not G.SETTINGS.paused and G.GAME.modifiers.cry_force_seal or seal, + y, + z + ) end local cs = Card.change_suit function Card:change_suit(new_suit) - return cs(self, not self.no_forced_suit and G.GAME.modifiers.cry_force_suit or new_suit) + return cs( + self, + not self.no_forced_suit and not G.SETTINGS.paused and G.GAME.modifiers.cry_force_suit or new_suit + ) end local ccl = Card.click function Card:click() @@ -391,8 +384,9 @@ return { and (Cryptid.safe_get(G.GAME, "viewed_back", "effect", "center", "edeck_type") and (self.back == "viewed_back" or self.edeck_select)) then if not G.cry_edeck_select then - Cryptid.enhancement_config_UI(Galdur and self.config.center or G.GAME.viewed_back.effect.center) G.cry_edeck_select = true + G.cry_edeck_center = Galdur and self.config.center or G.GAME.viewed_back.effect.center + Cryptid.enhancement_config_UI(Galdur and self.config.center or G.GAME.viewed_back.effect.center, 1) else if self.edeck_select then G.PROFILES[G.SETTINGS.profile]["cry_edeck_" .. self.config.center.edeck_type] = @@ -402,10 +396,12 @@ return { definition = G.UIDEF.run_setup("main_menu_play"), }) G.cry_edeck_select = nil + G.cry_edeck_center = nil end end end - function Cryptid.enhancement_config_UI(center) + function Cryptid.enhancement_config_UI(center, actual_page) + local count_per_page = 6 if not center.edeck_type then return end @@ -434,18 +430,30 @@ return { seal = G.P_SEALS, } local editions = {} - for _, v in pairs(pool_table[center.edeck_type]) do + for i, v in pairs(pool_table[center.edeck_type]) do if v.key ~= "e_base" and not v.no_edeck then - editions[#editions + 1] = (center.edeck_type == "edition" and v.key:sub(3)) or v.key + editions[#editions + 1] = + { index = i, center = (center.edeck_type == "edition" and v.key:sub(3)) or v.key } end end - - for i = 1, #editions do + local page = (actual_page and actual_page * count_per_page or count_per_page) - (count_per_page - 1) + local max_pages = math.floor(#editions / count_per_page) + if max_pages * count_per_page < #editions then --idk why this is needed but it is + max_pages = max_pages + 1 + end + local modification_options = {} + for i = 1, max_pages do + table.insert( + modification_options, + localize("k_page") .. " " .. tostring(i) .. "/" .. tostring(max_pages) + ) + end + for i = page, math.min(page + count_per_page - 1, #editions) do local _center = Cryptid.deep_copy(center) - _center.config["cry_force_" .. center.edeck_type] = editions[i] + _center.config["cry_force_" .. center.edeck_type] = editions[i].center Cryptid.edeck_atlas_update(_center) local card = Cryptid.generic_card(_center) - card.edeck_select = editions[i] + card.edeck_select = editions[i].center G.your_collection[1]:emplace(card) end @@ -461,12 +469,31 @@ return { config = { align = "cm", minw = 2.5, padding = 0.1, r = 0.1, colour = G.C.BLACK, emboss = 0.05 }, nodes = { deck_tables }, }, + { + n = G.UIT.R, + config = { align = "cm" }, + nodes = { + create_option_cycle({ + options = modification_options, + w = 4.5, + cycle_shoulders = true, + opt_callback = "edeck_page", + current_option = actual_page, + colour = G.C.RED, + no_pips = true, + focus_args = { snap_to = true, nav = "wide" }, + }), + }, + }, }, }) G.FUNCS.overlay_menu({ definition = t, }) end + G.FUNCS.edeck_page = function(args) + Cryptid.enhancement_config_UI(G.cry_edeck_center, args.cycle_config.current_option) + end end, items = { e_deck, et_deck, sk_deck, st_deck, sl_deck, atlasedition }, } diff --git a/Cryptid/items/epic.lua b/Cryptid/items/epic.lua index 831664d..04e46c8 100644 --- a/Cryptid/items/epic.lua +++ b/Cryptid/items/epic.lua @@ -21,7 +21,13 @@ local supercell = { object_type = "Joker", name = "cry-supercell", key = "supercell", - config = { extra = { stat1 = 15, stat2 = 2, money = 3 } }, + config = { + extra = { + stat1 = 15, + stat2 = 2, + money = 3, + }, + }, dependencies = { items = { "set_cry_epic", @@ -32,37 +38,52 @@ local supercell = { cost = 14, order = 64, blueprint_compat = true, + demicoloncompat = true, atlas = "atlasepic", loc_vars = function(self, info_queue, center) return { key = Cryptid.gameset_loc(self, { modest = "balanced" }), - vars = { center.ability.extra.stat1, center.ability.extra.stat2, center.ability.extra.money }, + vars = { + number_format(center.ability.extra.stat1), + number_format(center.ability.extra.stat2), + number_format(center.ability.extra.money), + }, } end, calculate = function(self, card, context) if context.joker_main then - if card.ability.extra.stat2 > 1 then --misprint deck moment + if to_big(card.ability.extra.stat2) > to_big(1) then --misprint deck moment if Card.get_gameset(card) ~= "modest" then return { message = localize("cry_gaming_ex"), - chip_mod = card.ability.extra.stat1, - mult_mod = card.ability.extra.stat1, - Xchip_mod = card.ability.extra.stat2, - Xmult_mod = card.ability.extra.stat2, + chip_mod = lenient_bignum(card.ability.extra.stat1), + mult_mod = lenient_bignum(card.ability.extra.stat1), + Xchip_mod = lenient_bignum(card.ability.extra.stat2), + Xmult_mod = lenient_bignum(card.ability.extra.stat2), } else return { message = localize("cry_gaming_ex"), - Xchip_mod = card.ability.extra.stat2, - Xmult_mod = card.ability.extra.stat2, + Xchip_mod = lenient_bignum(card.ability.extra.stat2), + Xmult_mod = lenient_bignum(card.ability.extra.stat2), } end end end + if context.forcetrigger then + ease_dollars(lenient_bignum(card.ability.extra.money)) + return { + message = localize("cry_gaming_ex"), + chip_mod = lenient_bignum(card.ability.extra.stat1), + mult_mod = lenient_bignum(card.ability.extra.stat1), + Xchip_mod = lenient_bignum(card.ability.extra.stat2), + Xmult_mod = lenient_bignum(card.ability.extra.stat2), + } + end end, calc_dollar_bonus = function(self, card) - if card.ability.extra.money > 0 then - return card.ability.extra.money + if to_big(card.ability.extra.money) > to_big(0) then + return lenient_bignum(card.ability.extra.money) end end, add_to_deck = function(self, card, from_debuff) @@ -89,9 +110,16 @@ local membershipcardtwo = { object_type = "Joker", name = "cry-membershipcardtwo", key = "membershipcardtwo", - config = { extra = { chips = 1 } }, + config = { + extra = { chips = 1 }, + immutable = { chips_mod = 1 }, + }, gameset_config = { - modest = { cost = 20, center = { rarity = 4 } }, + modest = { + cost = 20, + center = { rarity = 4 }, + immutable = { chips_mod = 8 }, + }, }, dependencies = { items = { @@ -103,33 +131,50 @@ local membershipcardtwo = { cost = 17, order = 50, blueprint_compat = true, + demicoloncompat = true, atlas = "atlasepic", loc_vars = function(self, info_queue, card) - local a = 1 - if Card.get_gameset(card) == "modest" then - a = 8 + local aaa + if not Cryptid_config.HTTPS then + if G.localization.descriptions.Other.cry_https_disabled then + aaa = {} + localize({ type = "other", key = "cry_https_disabled", nodes = aaa, vars = {} }) + aaa = aaa[1] + end end return { key = Cryptid.gameset_loc(self, { modest = "balanced" }), vars = { - card.ability.extra.chips, - card.ability.extra.chips * math.floor(Cryptid.member_count / a), + number_format(card.ability.extra.chips), + number_format( + lenient_bignum( + to_big(card.ability.extra.chips) + * math.floor(Cryptid.member_count / card.ability.immutable.chips_mod) + ) + ), }, + main_end = aaa, } end, calculate = function(self, card, context) - if context.joker_main and card.ability.extra.chips > 0 then - local a = 1 - if Card.get_gameset(card) == "modest" then - a = 8 - end + if (context.joker_main and to_big(card.ability.extra.chips) > to_big(0)) or context.forcetrigger then return { message = localize({ type = "variable", key = "a_chips", - vars = { card.ability.extra.chips * math.floor(Cryptid.member_count / a) }, + vars = { + number_format( + lenient_bignum( + to_big(card.ability.extra.chips) + * math.floor(Cryptid.member_count / card.ability.immutable.chips_mod) + ) + ), + }, }), - chip_mod = card.ability.extra.chips * math.floor(Cryptid.member_count / a), + chip_mod = lenient_bignum( + to_big(card.ability.extra.chips) + * math.floor(Cryptid.member_count / card.ability.immutable.chips_mod) + ), } end end, @@ -152,7 +197,12 @@ local googol_play = { object_type = "Joker", name = "cry-Googol Play Card", key = "googol_play", - config = { extra = { Xmult = 1e100, odds = 8 } }, + config = { + extra = { + Xmult = 1e100, + odds = 8, + }, + }, dependencies = { items = { "set_cry_epic", @@ -166,26 +216,41 @@ local googol_play = { cost = 10, order = 14, blueprint_compat = true, + demicoloncompat = true, atlas = "atlasepic", soul_pos = { x = 10, y = 0, extra = { x = 4, y = 0 } }, loc_vars = function(self, info_queue, card) + local aaa, bbb = SMODS.get_probability_vars(card, 1, card.ability.extra.odds, "Googol Play Card") return { vars = { - cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged), - card.ability.extra.odds, - card.ability.extra.Xmult, + aaa, + bbb, + number_format(card.ability.extra.Xmult), }, } end, calculate = function(self, card, context) if context.joker_main - and pseudorandom("cry_googol_play") - < cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged) / card.ability.extra.odds + and SMODS.pseudorandom_probability(card, "cry_googol_play", 1, card.ability.extra.odds, "Googol Play Card") then return { - message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.Xmult } }), - Xmult_mod = card.ability.extra.Xmult, + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), + } + end + if context.forcetrigger then + return { + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), } end end, @@ -226,45 +291,23 @@ local sync_catalyst = { }, }, gameset_config = { - modest = { cost = 20, center = { rarity = 4 } }, + modest = { + cost = 20, + center = { rarity = 4 }, + }, }, pos = { x = 5, y = 2 }, rarity = "cry_epic", cost = 12, order = 54, blueprint_compat = true, + demicoloncompat = true, immutable = true, atlas = "atlasepic", calculate = function(self, card, context) - if context.joker_main and not context.debuffed_hand and hand_chips and mult then - local tot = hand_chips + mult - if not tot.array or #tot.array < 2 or tot.array[2] < 2 then --below eXeY notation - hand_chips = mod_chips(math.floor(tot / 2)) - mult = mod_mult(math.floor(tot / 2)) - else - if hand_chips > mult then - tot = hand_chips - else - tot = mult - end - hand_chips = mod_chips(tot) - mult = mod_chips(tot) - end - update_hand_text({ delay = 0 }, { mult = mult, chips = hand_chips }) + if (context.joker_main and not context.debuffed_hand) or context.forcetrigger then return { - message = localize("k_balanced"), - colour = { 0.8, 0.45, 0.85, 1 }, - func = function() - G.E_MANAGER:add_event(Event({ - trigger = "after", - func = function() - play_sound("gong", 0.94, 0.3) - play_sound("gong", 0.94 * 1.5, 0.2) - play_sound("tarot1", 1.5) - return true - end, - })) - end, + balance = true, } end end, @@ -274,6 +317,7 @@ local sync_catalyst = { }, art = { "Ein13", + "George The Rat", }, code = { "Math", @@ -289,7 +333,14 @@ local negative = { name = "cry-Negative Joker", key = "negative", pos = { x = 1, y = 3 }, - config = { extra = 4 }, + config = { + extra = { + slots = 4, + }, + immutable = { + max_slots = 100, + }, + }, dependencies = { items = { "set_cry_epic", @@ -303,13 +354,16 @@ local negative = { order = 70, atlas = "atlasepic", loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra } } + return { vars = { number_format(center.ability.extra.slots) } } end, add_to_deck = function(self, card, from_debuff) - G.jokers.config.card_limit = G.jokers.config.card_limit + card.ability.extra + if card.ability.extra.slots > card.ability.immutable.max_slots then + card.ability.extra.slots = card.ability.immutable.max_slots + end + G.jokers.config.card_limit = lenient_bignum(G.jokers.config.card_limit + to_big(card.ability.extra.slots)) end, remove_from_deck = function(self, card, from_debuff) - G.jokers.config.card_limit = G.jokers.config.card_limit - card.ability.extra + G.jokers.config.card_limit = lenient_bignum(G.jokers.config.card_limit - to_big(card.ability.extra.slots)) end, cry_credits = { idea = { @@ -358,7 +412,11 @@ local canvas = { num_retriggers = num_retriggers + 1 end end - if card.T.x + card.T.w / 2 > context.other_card.T.x + context.other_card.T.w / 2 then + if + card.T + and context.other_card.T + and (card.T.x + card.T.w / 2 > context.other_card.T.x + context.other_card.T.w / 2) + then return { message = localize("k_again_ex"), repetitions = Card.get_gameset(card) ~= "modest" and num_retriggers or math.min(2, num_retriggers), @@ -372,7 +430,7 @@ local canvas = { "Mystic Misclick", }, art = { - "Mystic Misclick", + "Lil. Mr. Slipstream", }, code = { "Math", @@ -390,7 +448,12 @@ local error_joker = { name = "cry-Error", key = "error", pos = { x = 4, y = 2 }, - config = { extra = { sell_rounds = 0, active = false } }, + config = { + extra = { + sell_rounds = 0, + active = false, + }, + }, dependencies = { items = { -- Note: This currently does not have a dependency on Glitched because there's a fallback. @@ -536,7 +599,7 @@ local error_joker = { "Fetch", }, art = { - "Mystic Misclick", + "mold spores", }, code = { "Math", @@ -657,13 +720,24 @@ local m = { name = "cry-m", key = "m", pos = { x = 3, y = 1 }, - config = { extra = { extra = 13, x_mult = 1 } }, + config = { + extra = { + extra = 13, + x_mult = 1, + }, + }, gameset_config = { - modest = { extra = { extra = 1, x_mult = 1 } }, + modest = { + extra = { + extra = 1, + x_mult = 1, + }, + }, }, dependencies = { items = { "set_cry_epic", + "set_cry_meme", -- Note: This isn't in the M Joker content set due to being added separately }, }, @@ -674,35 +748,50 @@ local m = { effect = "M Joker", perishable_compat = false, blueprint_compat = true, + demicoloncompat = true, loc_vars = function(self, info_queue, center) info_queue[#info_queue + 1] = G.P_CENTERS.j_jolly - return { vars = { center.ability.extra.extra, center.ability.extra.x_mult } } + return { + vars = { + number_format(center.ability.extra.extra), + number_format(center.ability.extra.x_mult), + }, + } end, atlas = "atlasepic", calculate = function(self, card, context) if context.joker_main and (to_big(card.ability.extra.x_mult) > to_big(1)) then return { - message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.x_mult } }), + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.x_mult) }, + }), Xmult_mod = card.ability.extra.x_mult, } end if context.selling_card and context.card:is_jolly() and not context.blueprint then - card.ability.extra.x_mult = card.ability.extra.x_mult + card.ability.extra.extra - if not context.retrigger_joker then - --This doesn't display the correct amount of mult if retriggered it display the amount from the first retrigger instead of the final one - --But I would rather have this than constant card_eval_status_text spam - --If anyone knows a solution feel free to do a pr xd - card_eval_status_text( - card, - "extra", - nil, - nil, - nil, - { message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.x_mult } }) } - ) - end + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "x_mult", + scalar_value = "extra", + message_key = "a_xmult", + message_colour = G.C.RED, + }) return nil, true end + if context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "x_mult", + scalar_value = "extra", + message_key = "a_xmult", + message_colour = G.C.RED, + }) + return { + Xmult_mod = card.ability.extra.x_mult, + } + end end, cry_credits = { idea = { @@ -736,6 +825,7 @@ local M = { cost = 13, immutable = true, blueprint_compat = true, + demicoloncompat = true, loc_vars = function(self, info_queue, center) info_queue[#info_queue + 1] = G.P_CENTERS.j_jolly if not center.edition or (center.edition and not center.edition.negative) then @@ -744,7 +834,7 @@ local M = { end, atlas = "atlasepic", calculate = function(self, card, context) - if context.setting_blind and not (context.blueprint_card or self).getting_sliced then + if (context.setting_blind and not (context.blueprint_card or self).getting_sliced) or context.forcetrigger then local card = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_jolly") card:set_edition({ negative = true, @@ -779,6 +869,7 @@ local boredom = { dependencies = { items = { "set_cry_epic", + "set_cry_meme", }, }, gameset_config = { @@ -790,21 +881,23 @@ local boredom = { cost = 14, blueprint_compat = true, loc_vars = function(self, info_queue, card) + local num, denom = SMODS.get_probability_vars(card, 1, card.ability.extra.odds, "Boredom") + return { vars = { - cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged), - card.ability.extra.odds, + num, + denom, }, } end, atlas = "atlasepic", calculate = function(self, card, context) - if context.retrigger_joker_check and not context.retrigger_joker and context.other_card ~= self then - if - pseudorandom("cry_boredom_joker") - < cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged) - / card.ability.extra.odds - then + if + context.retrigger_joker_check + and not context.retrigger_joker + and not (context.other_card.ability and context.other_card.ability.name == "cry-Boredom") + then + if SMODS.pseudorandom_probability(card, "cry_boredom_joker", 1, card.ability.extra.odds, "Boredom") then return { message = localize("k_again_ex"), repetitions = 1, @@ -817,8 +910,7 @@ local boredom = { if context.repetition and context.cardarea == G.play - and pseudorandom("cry_boredom_card") - < cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged) / card.ability.extra.odds + and SMODS.pseudorandom_probability(card, "cry_boredom_joker", 1, card.ability.extra.odds, "Boredom") then return { message = localize("k_again_ex"), @@ -846,7 +938,12 @@ local number_blocks = { object_type = "Joker", name = "cry-Number Blocks", key = "number_blocks", - config = { extra = { money_mod = 1, money = 1 } }, + config = { + extra = { + money_mod = 1, + money = 1, + }, + }, dependencies = { items = { "set_cry_epic", @@ -860,8 +957,8 @@ local number_blocks = { loc_vars = function(self, info_queue, center) return { vars = { - center.ability.extra.money, - center.ability.extra.money_mod, + number_format(center.ability.extra.money), + number_format(center.ability.extra.money_mod), localize(Cryptid.safe_get(G.GAME, "current_round", "cry_nb_card", "rank") or "Ace", "ranks"), }, } @@ -883,15 +980,18 @@ local number_blocks = { card = card, } else - card.ability.extra.money = card.ability.extra.money + card.ability.extra.money_mod - card_eval_status_text(card, "extra", nil, nil, nil, { message = localize("k_upgrade_ex") }) + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "money", + scalar_value = "money_mod", + }) return nil, true end end end, calc_dollar_bonus = function(self, card) - if card.ability.extra.money > 0 then - return card.ability.extra.money + if to_big(card.ability.extra.money) > to_big(0) then + return lenient_bignum(card.ability.extra.money) end end, cry_credits = { @@ -899,7 +999,7 @@ local number_blocks = { "Jevonn", }, art = { - "Jevonn", + "George The Rat", }, code = { "Math", @@ -921,7 +1021,10 @@ local double_scale = { }, }, gameset_config = { - modest = { cost = 20, center = { rarity = 4 } }, + modest = { + cost = 20, + center = { rarity = 4 }, + }, exp_modest = { cost = 11 }, }, extra_gamesets = { "exp_modest" }, @@ -933,19 +1036,35 @@ local double_scale = { cost = 18, immutable = true, atlas = "atlasepic", - --todo: support jokers that scale multiple variables - cry_scale_mod = function(self, card, joker, orig_scale_scale, true_base, orig_scale_base, new_scale_base) - if Cryptid.gameset(self) == "exp_modest" then - return true_base * 2 + calc_scaling = function(self, card, other, current_scaling, current_scalar, args) + if not G.GAME.cryptid_base_scales then + G.GAME.cryptid_base_scales = {} end - return orig_scale_scale + true_base + if not G.GAME.cryptid_base_scales[other.config.center.key] then + G.GAME.cryptid_base_scales[other.config.center.key] = {} + end + if not G.GAME.cryptid_base_scales[other.config.center.key][args.scalar_value] then + G.GAME.cryptid_base_scales[other.config.center.key][args.scalar_value] = current_scalar + end + local true_base = G.GAME.cryptid_base_scales[other.config.center.key][args.scalar_value] + local orig_scale_scale = current_scaling + if Cryptid.gameset(self) == "exp_modest" then + return { + scalar_value = lenient_bignum(to_big(true_base) * 2), + message = localize("k_upgrade_ex"), + } + end + args.scalar_table[args.scalar_value] = new_scale + return { + message = localize("k_upgrade_ex"), + } end, cry_credits = { idea = { "Mystic Misclick", }, art = { - "AlezZGreat", + "lord.ruby", }, code = { "Math", @@ -962,7 +1081,10 @@ local oldcandy = { key = "oldcandy", pos = { x = 4, y = 1 }, order = 43, - config = { extra = { hand_size = 3 } }, + config = { + extra = { hand_size = 3 }, + immutable = { max_hand_size_mod = 1000 }, + }, gameset_config = { modest = { extra = { hand_size = 1 } }, }, @@ -973,15 +1095,29 @@ local oldcandy = { }, pools = { ["Food"] = true }, loc_vars = function(self, info_queue, center) - return { vars = { math.max(1, math.floor(center.ability.extra.hand_size)) } } + return { + vars = { + math.min( + center.ability.immutable.max_hand_size_mod, + math.max(1, math.floor(center.ability.extra.hand_size)) + ), + }, + } end, rarity = "cry_epic", cost = 9, + blueprint_compat = true, eternal_compat = false, + demicoloncompat = true, atlas = "atlasepic", calculate = function(self, card, context) - if context.selling_self and not context.blueprint then - G.hand:change_size(math.max(1, math.floor(card.ability.extra.hand_size))) + if context.selling_self or context.forcetrigger then + G.hand:change_size( + math.min( + card.ability.immutable.max_hand_size_mod, + math.max(1, math.floor(card.ability.extra.hand_size)) + ) + ) return nil, true end end, @@ -1005,7 +1141,7 @@ local circus = { name = "cry-circus", key = "circus", pos = { x = 4, y = 4 }, - config = { extra = { Xmult = 1 } }, + config = {}, dependencies = { items = { "set_cry_epic", @@ -1013,22 +1149,61 @@ local circus = { }, atlas = "atlasepic", order = 33, + loc_vars = function(self, info_queue, center) + local extra_rarities = {} + local mults = {} + Cryptid.circus_rarities["exotic"].colour = G.C.CRY_EXOTIC + for i, v in pairs(Cryptid.circus_rarities) do + extra_rarities[#extra_rarities + 1] = v + end + table.sort(extra_rarities, function(a, b) + return a.order < b.order + end) + mults.colours = {} + for i, v in pairs(extra_rarities) do + if not v.hidden then + mults[#mults + 1] = number_format(center.ability.extra[tostring(v.rarity) .. "_mult_mod"]) + mults.colours[#mults.colours + 1] = v.colour + end + end return { - vars = { - (math.max(1, center.ability.extra.Xmult) * 2), - (math.max(1, center.ability.extra.Xmult) * 3), - (math.max(1, center.ability.extra.Xmult) * 4), - (math.max(1, center.ability.extra.Xmult) * 20), - }, + vars = mults, } end, + set_ability = function(self, center) + local extra_rarities = {} + local mults = {} + local mult_numbers = {} + for i, v in pairs(Cryptid.circus_rarities) do + extra_rarities[#extra_rarities + 1] = v + end + table.sort(extra_rarities, function(a, b) + return a.order < b.order + end) + for i, v in pairs(extra_rarities) do + mult_numbers[tostring(v.rarity) .. "_mult_mod"] = v.base_mult + mults[v.rarity] = tostring(v.rarity) .. "_mult_mod" + end + if not self.config.extra then + self.config.extra = mult_numbers + center.ability.extra = mult_numbers + self.config.immutable = { + rarity_map = mults, + } + center.ability.immutable = { + rarity_map = mults, + } + end + end, rarity = "cry_epic", cost = 16, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) if context.other_joker and card ~= context.other_joker then - if context.other_joker.config.center.rarity == 3 then --Rare + local mod_key = card.ability.immutable.rarity_map[context.other_joker.config.center.rarity] + if mod_key and card.ability.extra[mod_key] and to_big(card.ability.extra[mod_key]) > to_big(1) then if not Talisman.config_file.disable_anims then G.E_MANAGER:add_event(Event({ func = function() @@ -1037,67 +1212,28 @@ local circus = { end, })) end + local xmult = card.ability.extra[mod_key] return { message = localize({ type = "variable", key = "a_xmult", - vars = { (math.max(1, card.ability.extra.Xmult) * 2) }, + vars = { number_format(xmult) }, }), - Xmult_mod = (math.max(1, card.ability.extra.Xmult) * 2), - } - elseif context.other_joker.config.center.rarity == 4 then --Legendary - if not Talisman.config_file.disable_anims then - G.E_MANAGER:add_event(Event({ - func = function() - context.other_joker:juice_up(0.5, 0.5) - return true - end, - })) - end - return { - message = localize({ - type = "variable", - key = "a_xmult", - vars = { (math.max(1, card.ability.extra.Xmult) * 4) }, - }), - Xmult_mod = (math.max(1, card.ability.extra.Xmult) * 4), - } - elseif context.other_joker.config.center.rarity == "cry_epic" then --Epic - if not Talisman.config_file.disable_anims then - G.E_MANAGER:add_event(Event({ - func = function() - context.other_joker:juice_up(0.5, 0.5) - return true - end, - })) - end - return { - message = localize({ - type = "variable", - key = "a_xmult", - vars = { (math.max(1, card.ability.extra.Xmult) * 3) }, - }), - Xmult_mod = (math.max(1, card.ability.extra.Xmult) * 3), - } - elseif context.other_joker.config.center.rarity == "cry_exotic" then --Exotic - if not Talisman.config_file.disable_anims then - G.E_MANAGER:add_event(Event({ - func = function() - context.other_joker:juice_up(0.5, 0.5) - return true - end, - })) - end - return { - message = localize({ - type = "variable", - key = "a_xmult", - vars = { (math.max(1, card.ability.extra.Xmult) * 20) }, - }), - Xmult_mod = (math.max(1, card.ability.extra.Xmult) * 20), + Xmult_mod = xmult, } end end + if context.forcetrigger then + local total = 1 + for i, v in pairs(card.ability.extra) do + if type(v) == "number" or (type(v) == "table" and v.tetrate) then + total = total * v + end + end + return { + Xmult_mod = total, + } + end end, cry_credits = { idea = { @@ -1108,6 +1244,7 @@ local circus = { }, code = { "Jevonn", + "BobJoe400", }, }, } @@ -1118,7 +1255,12 @@ local caramel = { object_type = "Joker", name = "cry-caramel", key = "caramel", - config = { extra = { x_mult = 1.75, rounds_remaining = 11 } }, + config = { + extra = { + x_mult = 1.75, + rounds_remaining = 11, + }, + }, dependencies = { items = { "set_cry_epic", @@ -1129,20 +1271,31 @@ local caramel = { cost = 12, order = 106, gameset_config = { - modest = { extra = { x_mult = 1.5, rounds_remaining = 6 } }, + modest = { + extra = { + x_mult = 1.5, + rounds_remaining = 6, + }, + }, }, pools = { ["Food"] = true }, blueprint_compat = true, eternal_compat = false, + demicoloncompat = true, atlas = "atlasepic", loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.x_mult, center.ability.extra.rounds_remaining } } + return { + vars = { + number_format(center.ability.extra.x_mult), + number_format(center.ability.extra.rounds_remaining), + }, + } end, calculate = function(self, card, context) if context.individual then if context.cardarea == G.play then return { - x_mult = card.ability.extra.x_mult, + x_mult = lenient_bignum(card.ability.extra.x_mult), colour = G.C.RED, card = card, } @@ -1155,8 +1308,8 @@ local caramel = { and not context.repetition and not context.retrigger_joker then - card.ability.extra.rounds_remaining = card.ability.extra.rounds_remaining - 1 - if card.ability.extra.rounds_remaining > 0 then + card.ability.extra.rounds_remaining = lenient_bignum(to_big(card.ability.extra.rounds_remaining) - 1) + if to_big(card.ability.extra.rounds_remaining) > to_big(0) then return { message = { localize("cry_minus_round") }, colour = G.C.FILTER, @@ -1189,6 +1342,15 @@ local caramel = { } end end + if context.forcetrigger then + card.ability.extra.rounds_remaining = lenient_bignum(to_big(card.ability.extra.rounds_remaining) - 1) + card.ability.extra.rounds_remaining = math.max(card.ability.extra.rounds_remaining, 0) + return { + Xmult_mod = lenient_bignum(card.ability.extra.x_mult), + colour = G.C.RED, + card = card, + } + end end, cry_credits = { idea = { @@ -1218,16 +1380,21 @@ local curse_sob = { dependencies = { items = { "set_cry_epic", + "set_cry_meme", }, }, gameset_config = { - modest = { cost = 20, center = { rarity = 4 } }, + modest = { + cost = 20, + center = { rarity = 4 }, + }, }, rarity = "cry_epic", cost = 9, order = 82, immutable = true, perishable_compat = true, + demicoloncompat = true, atlas = "atlasepic", calculate = function(self, card, context) if @@ -1239,20 +1406,20 @@ local curse_sob = { return {} elseif ( -- Compacting all the elseifs into one block for space and readability also maintablity - context.selling_self - or context.discard - or context.reroll_shop --Yes - or context.buying_card - or context.skip_blind - or context.using_consumeable - or context.selling_card - or context.setting_blind - or context.skipping_booster - or context.open_booster - ) - and #G.jokers.cards + G.GAME.joker_buffer < (context.selling_self and (G.jokers.config.card_limit + 1) or G.jokers.config.card_limit) - and not context.retrigger_joker - and not context.blueprint + context.selling_self + or context.discard + or context.reroll_shop --Yes + or context.buying_card + or context.skip_blind + or context.using_consumeable + or context.selling_card + or context.setting_blind + or context.skipping_booster + or context.open_booster + or context.forcetrigger + ) + and (#G.jokers.cards + G.GAME.joker_buffer < (context.selling_self and (G.jokers.config.card_limit + 1) or G.jokers.config.card_limit)) + or context.forcetrigger and not context.retrigger_joker and not context.blueprint then local createjoker = math.min(1, G.jokers.config.card_limit - (#G.jokers.cards + G.GAME.joker_buffer)) G.GAME.joker_buffer = G.GAME.joker_buffer + createjoker @@ -1298,7 +1465,7 @@ local curse_sob = { check_for_unlock = function(self, args) if Cryptid.safe_get(G, "jokers") then for i = 1, #G.jokers.cards do - if G.jokers.cards[i].config.center.key == "j_obelisk" and G.jokers.cards[i].ability.eternal then + if G.jokers.cards[i].config.center.key == "j_obelisk" and SMODS.is_eternal(G.jokers.cards[i]) then unlock_card(self) end end @@ -1320,25 +1487,33 @@ local bonusjoker = { name = "cry-Bonus Joker", key = "bonusjoker", pos = { x = 3, y = 2 }, - config = { extra = { odds = 8, check = 0, add = 1 } }, + config = { + extra = { + odds = 8, + add = 1, + }, + immutable = { check = 0, max = 100 }, + }, dependencies = { items = { "set_cry_epic", }, }, - immutable = true, + immutable = false, rarity = "cry_epic", cost = 11, order = 75, blueprint_compat = true, + demicoloncompat = true, enhancement_gate = "m_bonus", loc_vars = function(self, info_queue, card) info_queue[#info_queue + 1] = G.P_CENTERS.m_bonus + local aaa, bbb = SMODS.get_probability_vars(card, 1, card.ability.extra.odds, "Bonus Joker") return { vars = { - cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged), - card.ability.extra.odds, - card.ability.extra.add, + aaa, + bbb, + number_format(math.min(card.ability.extra.add, card.ability.immutable.max)), }, } end, @@ -1347,22 +1522,26 @@ local bonusjoker = { if context.individual and context.cardarea == G.play then if SMODS.has_enhancement(context.other_card, "m_bonus") then if - pseudorandom("bonusjoker") - < cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged) / card.ability.extra.odds - and card.ability.extra.check < 2 + SMODS.pseudorandom_probability(card, "bonusjoker", 1, card.ability.extra.odds, "Bonus Joker") + and card.ability.immutable.check < 2 and not context.retrigger_joker then local option = pseudorandom_element({ 1, 2 }, pseudoseed("bonusjoker")) if option == 1 then if not context.blueprint then - card.ability.extra.check = card.ability.extra.check + 1 + card.ability.immutable.check = lenient_bignum(card.ability.immutable.check + 1) end - G.jokers.config.card_limit = G.jokers.config.card_limit + card.ability.extra.add + G.jokers.config.card_limit = lenient_bignum( + G.jokers.config.card_limit + math.min(card.ability.extra.add, card.ability.immutable.max) + ) else if not context.blueprint then - card.ability.extra.check = card.ability.extra.check + 1 + card.ability.immutable.check = lenient_bignum(card.ability.immutable.check + 1) end - G.consumeables.config.card_limit = G.consumeables.config.card_limit + card.ability.extra.add + G.consumeables.config.card_limit = lenient_bignum( + G.consumeables.config.card_limit + + to_big(math.min(card.ability.extra.add, card.ability.immutable.max)) + ) end return { extra = { focus = card, message = localize("k_upgrade_ex") }, @@ -1374,18 +1553,42 @@ local bonusjoker = { end if context.end_of_round - and card.ability.extra.check ~= 0 + and card.ability.immutable.check ~= 0 and not context.blueprint and not context.retrigger_joker and not context.individual and not context.repetition then - card.ability.extra.check = 0 + card.ability.immutable.check = 0 return { message = localize("k_reset"), card = card, } end + if context.forcetrigger then + local option = pseudorandom_element({ 1, 2 }, pseudoseed("bonusjoker")) + if option == 1 then + if not context.blueprint then + card.ability.immutable.check = lenient_bignum(card.ability.immutable.check + 1) + end + G.jokers.config.card_limit = lenient_bignum( + G.jokers.config.card_limit + cmath.min(card.ability.extra.add, card.ability.immutable.max) + ) + else + if not context.blueprint then + card.ability.immutable.check = lenient_bignum(card.ability.immutable.check + 1) + end + G.consumeables.config.card_limit = lenient_bignum( + G.consumeables.config.card_limit + + to_big(math.min(card.ability.extra.add, card.ability.immutable.max)) + ) + end + return { + extra = { focus = card, message = localize("k_upgrade_ex") }, + card = card, + colour = G.C.MONEY, + } + end end, cry_credits = { idea = { @@ -1417,15 +1620,13 @@ local multjoker = { order = 99, cost = 11, blueprint_compat = true, + demicoloncompat = true, enhancement_gate = "m_mult", loc_vars = function(self, info_queue, card) info_queue[#info_queue + 1] = G.P_CENTERS.m_mult info_queue[#info_queue + 1] = G.P_CENTERS.c_cryptid return { - vars = { - cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged), - card.ability.extra.odds, - }, + vars = { SMODS.get_probability_vars(card, 1, card.ability.extra.odds, "Mult Joker") }, } end, atlas = "atlasepic", @@ -1435,11 +1636,7 @@ local multjoker = { SMODS.has_enhancement(context.other_card, "m_mult") and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then - if - pseudorandom("multjoker") - < cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged) - / card.ability.extra.odds - then + if SMODS.pseudorandom_probability(card, "multjoker", 1, card.ability.extra.odds, "Mult Joker") then G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1 G.E_MANAGER:add_event(Event({ func = function() @@ -1463,6 +1660,19 @@ local multjoker = { end end end + if context.forcetrigger then + G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1 + G.E_MANAGER:add_event(Event({ + func = function() + local new_card = + create_card("Spectral", G.consumeables, nil, nil, nil, nil, "c_cryptid", "multjoker") + new_card:add_to_deck() + G.consumeables:emplace(new_card) + G.GAME.consumeable_buffer = 0 + return true + end, + })) + end end, cry_credits = { idea = { @@ -1483,7 +1693,12 @@ local goldjoker = { object_type = "Joker", name = "cry-gold Joker", key = "goldjoker", - config = { extra = { percent_mod = 2, percent = 0 } }, + config = { + extra = { + percent_mod = 2, + percent = 0, + }, + }, dependencies = { items = { "set_cry_epic", @@ -1498,33 +1713,37 @@ local goldjoker = { atlas = "atlasepic", loc_vars = function(self, info_queue, center) info_queue[#info_queue + 1] = G.P_CENTERS.m_gold - return { vars = { center.ability.extra.percent, center.ability.extra.percent_mod } } + return { + vars = { + number_format(center.ability.extra.percent), + number_format(center.ability.extra.percent_mod), + }, + } end, calculate = function(self, card, context) if context.cardarea == G.play and context.individual and not context.blueprint then if SMODS.has_enhancement(context.other_card, "m_gold") then - card.ability.extra.percent = card.ability.extra.percent + card.ability.extra.percent_mod - return { - extra = { focus = card, message = localize("k_upgrade_ex") }, - card = card, - colour = G.C.MONEY, - } + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "percent", + scalar_value = "percent_mod", + }) end end if context.individual and context.cardarea == G.play then if SMODS.has_enhancement(context.other_card, "m_gold") then - card.ability.extra.percent = card.ability.extra.percent + card.ability.extra.percent_mod - return { - message = localize("k_upgrade_ex"), - card = card, - colour = G.C.CHIPS, - } + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "percent", + scalar_value = "percent_mod", + }) end end end, calc_dollar_bonus = function(self, card) - local bonus = math.max(0, math.floor(0.01 * card.ability.extra.percent * (G.GAME.dollars or 0))) - if bonus > to_big(0) then + local bonus = + lenient_bignum(math.max(0, math.floor(0.01 * to_big(card.ability.extra.percent) * (G.GAME.dollars or 0)))) + if to_big(bonus) > to_big(0) then return bonus end end, @@ -1560,19 +1779,30 @@ local altgoogol = { order = 60, blueprint_compat = false, eternal_compat = false, + demicoloncompat = true, atlas = "atlasepic", soul_pos = { x = 10, y = 0, extra = { x = 5, y = 3 } }, + config = { copies = 2 }, gameset_config = { - modest = { cost = 15, copies = 1 }, + modest = { + cost = 15, + copies = 1, + }, mainline = { copies = 2 }, - madness = { center = { blueprint_compat = true }, copies = 2 }, + madness = { + center = { blueprint_compat = true }, + copies = 2, + }, }, loc_vars = function(self, info_queue, center) return { key = Cryptid.gameset_loc(self, { modest = "balanced" }), vars = { center.ability.copies } } end, calculate = function(self, card, context) local gameset = Card.get_gameset(card) - if context.selling_self and not context.retrigger_joker and (gameset == "madness" or not context.blueprint) then + if + (context.selling_self and not context.retrigger_joker and (gameset == "madness" or not context.blueprint)) + or context.forcetrigger + then local jokers = {} for i = 1, #G.jokers.cards do if G.jokers.cards[i] ~= card then @@ -1688,7 +1918,8 @@ local soccer = { "Mjiojio", }, art = { - "HexaCryonic", + "Ein13", + "George The Rat", }, code = { "Jevonn", @@ -1791,7 +2022,7 @@ local fleshpanopticon = { return true end, })) - if not card.ability.eternal then + if not SMODS.is_eternal(card) then G.E_MANAGER:add_event(Event({ func = function() play_sound("tarot1") @@ -1836,7 +2067,10 @@ local spectrogram = { name = "cry-Spectrogram", key = "spectrogram", pos = { x = 1, y = 5 }, - config = { extra = { echonum = 0 } }, + config = { + extra = {}, + immutable = { echonum = 0 }, + }, rarity = "cry_epic", cost = 9, order = 133, @@ -1853,10 +2087,10 @@ local spectrogram = { end, calculate = function(self, card, context) if context.before and context.cardarea == G.jokers then - card.ability.extra.echonum = 0 + card.ability.immutable.echonum = 0 for i, v in pairs(context.scoring_hand) do if v.config.center_key == "m_cry_echo" and not v.debuff then - card.ability.extra.echonum = card.ability.extra.echonum + 1 + card.ability.immutable.echonum = card.ability.immutable.echonum + 1 end end end @@ -1867,10 +2101,10 @@ local spectrogram = { and context.other_card == G.jokers.cards[#G.jokers.cards] and context.other_card ~= self then - if card.ability.extra.echonum and card.ability.extra.echonum > 0 then + if card.ability.immutable.echonum and card.ability.immutable.echonum > 0 then return { message = localize("k_again_ex"), - repetitions = card.ability.extra.echonum, + repetitions = card.ability.immutable.echonum, card = card, } end @@ -1881,7 +2115,7 @@ local spectrogram = { "AlexZGreat", }, art = { - "SMG9000", + "Ein13", }, code = { "AlexZGreat", @@ -1897,30 +2131,54 @@ local jtron = { }, name = "cry-jtron", key = "jtron", - config = { extra = { bonus = 1, current = 0 } }, + config = { + extra = { bonus = 1 }, + immutable = { current = 0 }, + }, rarity = "cry_epic", cost = 14, order = 64, blueprint_compat = true, + demicoloncompat = true, atlas = "atlasepic", pos = { x = 2, y = 5 }, loc_vars = function(self, info_queue, center) info_queue[#info_queue + 1] = G.P_CENTERS.j_joker - center.ability.extra.current = 1 + center.ability.extra.bonus * #SMODS.find_card("j_joker") - return { vars = { center.ability.extra.bonus, center.ability.extra.current } } + center.ability.immutable.current = + lenient_bignum(1 + to_big(center.ability.extra.bonus) * #SMODS.find_card("j_joker")) + return { + vars = { + number_format(center.ability.extra.bonus), + number_format(center.ability.immutable.current), + }, + } end, calculate = function(self, card, context) - card.ability.extra.current = 1 + card.ability.extra.bonus * #SMODS.find_card("j_joker") + card.ability.immutable.current = + lenient_bignum(1 + to_big(card.ability.extra.bonus) * #SMODS.find_card("j_joker")) if context.cardarea == G.jokers and context.joker_main then return { message = localize({ type = "variable", key = "a_powmult", vars = { - number_format(card.ability.extra.current), + number_format(card.ability.immutable.current), }, }), - Emult_mod = card.ability.extra.current, + Emult_mod = lenient_bignum(card.ability.immutable.current), + colour = G.C.DARK_EDITION, + } + end + if context.forcetrigger then + return { + message = localize({ + type = "variable", + key = "a_powmult", + vars = { + number_format(1 + to_big(card.ability.extra.bonus)), + }, + }), + Emult_mod = lenient_bignum(1 + to_big(card.ability.extra.bonus)), colour = G.C.DARK_EDITION, } end @@ -1943,9 +2201,26 @@ local clockwork = { -- Steel Support: The Joker key = "clockwork", pos = { x = 5, y = 5 }, config = { - limits = { l1 = 2, l2 = 3, l3 = 5, l4 = 7 }, - counters = { c1 = 0, c2 = 0, c3 = 0, c4 = 0 }, - extra = { xmult = 1, xmult_mod = 0.25, steelenhc = 1, steel_mod = 0.1 }, + extra = { + xmult = 1, + xmult_mod = 0.25, + steelenhc = 1, + steel_mod = 0.1, + }, + immutable = { + limits = { + l1 = 2, + l2 = 3, + l3 = 5, + l4 = 7, + }, + counters = { + c1 = 0, + c2 = 0, + c3 = 0, + c4 = 0, + }, + }, }, order = 135, immutable = false, @@ -1963,18 +2238,18 @@ local clockwork = { -- Steel Support: The Joker end return { vars = { - process_var(center.ability.counters.c1, center.ability.limits.l1), - process_var(center.ability.counters.c2, center.ability.limits.l2), - process_var(center.ability.counters.c3, center.ability.limits.l3), - process_var(center.ability.counters.c4, center.ability.limits.l4), - center.ability.extra.xmult, - center.ability.extra.xmult_mod, - center.ability.extra.steelenhc, - center.ability.extra.steel_mod, - center.ability.limits.l1, - center.ability.limits.l2, - center.ability.limits.l3, - center.ability.limits.l4, + process_var(center.ability.immutable.counters.c1, center.ability.immutable.limits.l1), + process_var(center.ability.immutable.counters.c2, center.ability.immutable.limits.l2), + process_var(center.ability.immutable.counters.c3, center.ability.immutable.limits.l3), + process_var(center.ability.immutable.counters.c4, center.ability.immutable.limits.l4), + number_format(center.ability.extra.xmult), + number_format(center.ability.extra.xmult_mod), + number_format(center.ability.extra.steelenhc), + number_format(center.ability.extra.steel_mod), + center.ability.immutable.limits.l1, + center.ability.immutable.limits.l2, + center.ability.immutable.limits.l3, + center.ability.immutable.limits.l4, }, } end, @@ -1988,21 +2263,27 @@ local clockwork = { -- Steel Support: The Joker return m end - card.ability.counters.c1 = clamp(card.ability.counters.c1, card.ability.limits.l1) -- ticker 1 + card.ability.immutable.counters.c1 = + clamp(card.ability.immutable.counters.c1, card.ability.immutable.limits.l1) -- ticker 1 - card.ability.counters.c2 = clamp(card.ability.counters.c2, card.ability.limits.l2) -- ticker 2 - if card.ability.counters.c2 == 0 then - card.ability.extra.xmult = card.ability.extra.xmult + card.ability.extra.xmult_mod + card.ability.immutable.counters.c2 = + clamp(card.ability.immutable.counters.c2, card.ability.immutable.limits.l2) -- ticker 2 + if card.ability.immutable.counters.c2 == 0 then + card.ability.extra.xmult = + lenient_bignum(to_big(card.ability.extra.xmult) + card.ability.extra.xmult_mod) end - card.ability.counters.c3 = clamp(card.ability.counters.c3, card.ability.limits.l3) -- ticker 3 + card.ability.immutable.counters.c3 = + clamp(card.ability.immutable.counters.c3, card.ability.immutable.limits.l3) -- ticker 3 - card.ability.counters.c4 = clamp(card.ability.counters.c4, card.ability.limits.l4) -- ticker 4 - if card.ability.counters.c4 == 0 then - card.ability.extra.steelenhc = card.ability.extra.steelenhc + card.ability.extra.steel_mod + card.ability.immutable.counters.c4 = + clamp(card.ability.immutable.counters.c4, card.ability.immutable.limits.l4) -- ticker 4 + if card.ability.immutable.counters.c4 == 0 then + card.ability.extra.steelenhc = + lenient_bignum(to_big(card.ability.extra.steelenhc) + card.ability.extra.steel_mod) end end - if context.repetition and context.cardarea == G.hand and card.ability.counters.c1 == 0 then -- effect 1 + if context.repetition and context.cardarea == G.hand and card.ability.immutable.counters.c1 == 0 then -- effect 1 if SMODS.has_enhancement(context.other_card, "m_steel") then return { message = localize("k_again_ex"), @@ -2021,7 +2302,8 @@ local clockwork = { -- Steel Support: The Joker and context.cardarea == G.jokers and not context.blueprint_card and not context.retrigger_joker - and card.ability.counters.c3 == 0 + and card.ability.immutable.counters.c3 == 0 + and context.full_hand[1] then -- effect 3 context.full_hand[1]:set_ability(G.P_CENTERS["m_steel"], nil, true) end @@ -2030,7 +2312,7 @@ local clockwork = { -- Steel Support: The Joker and context.cardarea == G.hand and not context.end_of_round and SMODS.has_enhancement(context.other_card, "m_steel") - and card.ability.extra.steelenhc ~= 1 + and to_big(card.ability.extra.steelenhc) ~= to_big(1) then if context.other_card.debuff then return { @@ -2039,7 +2321,7 @@ local clockwork = { -- Steel Support: The Joker card = card, } else -- effect 4 - return { xmult = card.ability.extra.steelenhc } + return { xmult = lenient_bignum(card.ability.extra.steelenhc) } end end --imo this secret effect can be madness only -Math @@ -2050,10 +2332,10 @@ local clockwork = { -- Steel Support: The Joker and not context.retrigger_joker then -- The Clockwork Joker is canonically a non-binary self-replicating machine amoeba, that self replicates every 21 minutes. Their pronouns are any/all; they are several billion tiny jokers if -- in a trench coat, constantly ticking in an almost perfect yet flawed mechanism. Its only purpose is the strengthening and spreading of the steel world; everything else is meaningless to it. - card.ability.counters.c1 == 0 -- lore by nova :3 - and card.ability.counters.c2 == 0 - and card.ability.counters.c3 == 0 - and card.ability.counters.c4 == 0 + card.ability.immutable.counters.c1 == 0 -- lore by nova :3 + and card.ability.immutable.counters.c2 == 0 + and card.ability.immutable.counters.c3 == 0 + and card.ability.immutable.counters.c4 == 0 then G.E_MANAGER:add_event(Event({ func = function() @@ -2071,10 +2353,14 @@ local clockwork = { -- Steel Support: The Joker end end, set_ability = function(self, card, initial, delay_sprites) - card.ability.counters.c1 = math.floor(pseudorandom("Clockwork1") * (card.ability.limits.l1 - 1) + 0.5) - card.ability.counters.c2 = math.floor(pseudorandom("Clockwork2") * (card.ability.limits.l2 - 1) + 0.5) - card.ability.counters.c3 = math.floor(pseudorandom("Clockwork3") * (card.ability.limits.l3 - 1) + 0.5) - card.ability.counters.c4 = math.floor(pseudorandom("Clockwork4") * (card.ability.limits.l4 - 1) + 0.5) + card.ability.immutable.counters.c1 = + math.floor(pseudorandom("Clockwork1") * (card.ability.immutable.limits.l1 - 1) + 0.5) + card.ability.immutable.counters.c2 = + math.floor(pseudorandom("Clockwork2") * (card.ability.immutable.limits.l2 - 1) + 0.5) + card.ability.immutable.counters.c3 = + math.floor(pseudorandom("Clockwork3") * (card.ability.immutable.limits.l3 - 1) + 0.5) + card.ability.immutable.counters.c4 = + math.floor(pseudorandom("Clockwork4") * (card.ability.immutable.limits.l4 - 1) + 0.5) end, cry_credits = { idea = { @@ -2089,6 +2375,249 @@ local clockwork = { -- Steel Support: The Joker }, }, } +-- Force-triggers the rightmost joker during context.joker_main +local demicolon = { + object_type = "Joker", + gameset_config = { + modest = { disabled = true }, + mainline = { disabled = true }, + madness = { disabled = false }, + experimental = { disabled = false }, + }, + dependencies = { + items = { + "set_cry_epic", + }, + }, + name = "cry-demicolon", + key = "demicolon", + rarity = "cry_epic", + cost = 14, + order = 299, + blueprint_compat = false, + demicoloncompat = true, + atlas = "atlasepic", + pos = { x = 3, y = 5 }, + config = { check = nil }, + immutable = true, + loc_vars = function(self, info_queue, card) + card.ability.demicoloncompat_ui = card.ability.demicoloncompat_ui or "" + card.ability.demicoloncompat_ui_check = nil + local check = card.ability.check + return { + main_end = (card.area and card.area == G.jokers) + and { + { + n = G.UIT.C, + config = { align = "bm", minh = 0.4 }, + nodes = { + { + n = G.UIT.C, + config = { + ref_table = card, + align = "m", + -- colour = (check and G.C.cry_epic or G.C.JOKER_GREY), + colour = card.ability.colour, + r = 0.05, + padding = 0.08, + func = "blueprint_compat", + }, + nodes = { + { + n = G.UIT.T, + config = { + ref_table = card.ability, + ref_value = "demicoloncompat", + colour = G.C.UI.TEXT_LIGHT, + scale = 0.32 * 0.8, + }, + }, + }, + }, + }, + }, + } + or nil, + } + end, + update = function(self, card, front) + local other_joker = nil + if G.STAGE == G.STAGES.RUN then + for i = 1, #G.jokers.cards do + if G.jokers.cards[i] == card then + other_joker = G.jokers.cards[i + 1] + end + end + local m = Cryptid.demicolonGetTriggerable(other_joker) + if m[1] and not m[2] then + card.ability.demicoloncompat = "Compatible" + card.ability.check = true + card.ability.colour = G.C.SECONDARY_SET.Enhanced + elseif m[2] then + card.ability.demicoloncompat = "Dangerous!" + card.ability.check = true + card.ability.colour = G.C.MULT + else + card.ability.demicoloncompat = "Incompatible" + card.ability.check = false + card.ability.colour = G.C.SUITS.Spades + end + end + end, + calculate = function(self, card, context) + if context.joker_main and not context.blueprint then + for i = 1, #G.jokers.cards do + if G.jokers.cards[i] == card then + if Cryptid.demicolonGetTriggerable(G.jokers.cards[i + 1])[1] then + local results = Cryptid.forcetrigger(G.jokers.cards[i + 1], context) + if results and results.jokers then + results.jokers.message = localize("cry_demicolon") + results.jokers.colour = G.C.RARITY.cry_epic + results.jokers.sound = "cry_demitrigger" + return results.jokers + end + return { + message = localize("cry_demicolon"), + colour = G.C.RARITY.cry_epic, + sound = "cry_demitrigger", + } + end + end + end + end + end, + cry_credits = { + idea = { "HexaCryonic" }, + art = { "HexaCryonic" }, + code = { "Nova" }, + }, +} + +local starfruit = { + object_type = "Joker", + dependencies = { + items = { + "set_cry_epic", + }, + }, + name = "cry-starfruit", + key = "starfruit", + rarity = "cry_epic", + cost = 14, + order = 300, + blueprint_compat = true, + demicoloncompat = true, + atlas = "atlasepic", + pos = { x = 4, y = 5 }, + config = { emult = 2, emult_mod = 0.2 }, + pools = { ["Food"] = true }, + calculate = function(self, card, context) + if context.joker_main or context.forcetrigger then + return { + message = localize({ + type = "variable", + key = "a_powmult", + vars = { + number_format(card.ability.emult), + }, + }), + Emult_mod = lenient_bignum(card.ability.emult), + colour = G.C.DARK_EDITION, + } + end + if context.reroll_shop or context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability, + ref_value = "emult", + scalar_value = "emult_mod", + operation = "-", + no_message = true, + }) + --floating point precision can kiss my ass istg + if to_number(card.ability.emult) <= 1.00000001 then + G.E_MANAGER:add_event(Event({ + func = function() + play_sound("tarot1") + card.T.r = -0.2 + card:juice_up(0.3, 0.4) + card.states.drag.is = true + card.children.center.pinch.x = true + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.3, + blockable = false, + func = function() + G.jokers:remove_card(card) + card:remove() + card = nil + return true + end, + })) + return true + end, + })) + return { + message = localize("k_eaten_ex"), + colour = G.C.RARITY.cry_epic, + } + else + if not msg or type(msg) == "string" then + return { + message = msg or localize({ + type = "variable", + key = "a_powmult_minus", + vars = { + number_format(card.ability.emult_mod), + }, + }), + colour = G.C.RARITY.cry_epic, + } + end + end + end + end, + loc_vars = function(self, queue, card) + return { + vars = { + number_format(card.ability.emult), + number_format(card.ability.emult_mod), + }, + } + end, + cry_credits = { + art = { "lord.ruby" }, + code = { "lord.ruby" }, + idea = { "NinjaBanana" }, + }, + check_for_unlock = function(self, args) + if args.type == "foods_destroyed" and to_big(args.destroyed) >= 2 then + unlock_card(self) + end + if args.type == "cry_lock_all" then + lock_card(self) + end + if args.type == "cry_unlock_all" then + unlock_card(self) + end + end, + init = function() + local card_remove_ref = Card.remove + function Card:remove(...) + if self:is_food() and self.area == G.jokers and not G.SETTINGS.paused then + G.cry_foods_eaten = (G.cry_foods_eaten or 0) + 1 + check_for_unlock({ type = "foods_destroyed", destroyed = G.cry_foods_eaten }) + G.E_MANAGER:add_event(Event({ + func = function() + G.cry_foods_eaten = nil + return true + end, + })) + end + return card_remove_ref(self, ...) + end + end, +} + return { name = "Epic Jokers", items = { @@ -2117,5 +2646,7 @@ return { spectrogram, jtron, clockwork, + demicolon, + starfruit, }, } diff --git a/Cryptid/items/exotic.lua b/Cryptid/items/exotic.lua index 6724f34..7c78ac4 100644 --- a/Cryptid/items/exotic.lua +++ b/Cryptid/items/exotic.lua @@ -17,37 +17,31 @@ local gateway = { order = 90, hidden = true, --default soul_set and soul_rate of 0.3% in spectral packs is used can_use = function(self, card) - if (#SMODS.find_card("j_jen_saint") + #SMODS.find_card("j_jen_saint_attuned")) > 0 then - return #G.jokers.cards < G.jokers.config.card_limit - else - --Don't allow use if everything is eternal and there is no room - return #Cryptid.advanced_find_joker(nil, nil, nil, { "eternal" }, true, "j") < G.jokers.config.card_limit - end + --Don't allow use if everything is eternal and there is no room + return #Cryptid.advanced_find_joker(nil, nil, nil, { "eternal" }, true, "j") < G.jokers.config.card_limit end, use = function(self, card, area, copier) - if (#SMODS.find_card("j_jen_saint") + #SMODS.find_card("j_jen_saint_attuned")) <= 0 then - local deletable_jokers = {} - for k, v in pairs(G.jokers.cards) do - if not v.ability.eternal then - deletable_jokers[#deletable_jokers + 1] = v - end + local deletable_jokers = {} + for k, v in pairs(G.jokers.cards) do + if not SMODS.is_eternal(v) then + deletable_jokers[#deletable_jokers + 1] = v end - local _first_dissolve = nil - G.E_MANAGER:add_event(Event({ - trigger = "before", - delay = 0.75, - func = function() - for k, v in pairs(deletable_jokers) do - if v.config.center.rarity == "cry_exotic" then - check_for_unlock({ type = "what_have_you_done" }) - end - v:start_dissolve(nil, _first_dissolve) - _first_dissolve = true - end - return true - end, - })) end + local _first_dissolve = nil + G.E_MANAGER:add_event(Event({ + trigger = "before", + delay = 0.75, + func = function() + for k, v in pairs(deletable_jokers) do + if v.config.center.rarity == "cry_exotic" then + check_for_unlock({ type = "what_have_you_done" }) + end + v:start_dissolve(nil, _first_dissolve) + _first_dissolve = true + end + return true + end, + })) G.E_MANAGER:add_event(Event({ trigger = "after", delay = 0.4, @@ -62,6 +56,10 @@ local gateway = { })) delay(0.6) end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, } local iterum = { dependencies = { @@ -73,23 +71,40 @@ local iterum = { object_type = "Joker", name = "cry-Iterum", key = "iterum", - config = { extra = { x_mult = 2, repetitions = 1 } }, + config = { + extra = { + x_mult = 2, + repetitions = 1, + }, + immutable = { + max_repetitions = 40, + }, + }, pos = { x = 0, y = 1 }, rarity = "cry_exotic", order = 500, cost = 50, blueprint_compat = true, + demicoloncompat = true, atlas = "atlasexotic", soul_pos = { x = 1, y = 1, extra = { x = 2, y = 1 } }, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.x_mult, math.min(40, center.ability.extra.repetitions) } } + return { + vars = { + number_format(center.ability.extra.x_mult), + math.min(center.ability.immutable.max_repetitions, center.ability.extra.repetitions), + center.ability.immutable.max_repetitions, + }, + } end, calculate = function(self, card, context) if context.repetition then if context.cardarea == G.play then return { message = localize("k_again_ex"), - repetitions = math.min(40, card.ability.extra.repetitions), + repetitions = to_number( + math.min(card.ability.immutable.max_repetitions, card.ability.extra.repetitions) + ), card = card, } end @@ -102,9 +117,16 @@ local iterum = { } end end + if context.forcetrigger then + return { + x_mult = card.ability.extra.x_mult, + colour = G.C.RED, + card = card, + } + end end, cry_credits = { - idea = { "Math" }, + idea = { "Math", "Project666" }, art = { "Ein13" }, code = { "Math" }, }, @@ -128,12 +150,12 @@ local universum = { atlas = "atlasexotic", soul_pos = { x = 4, y = 3, extra = { x = 5, y = 3 } }, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra } } + return { vars = { number_format(center.ability.extra) } } end, calculate = function(self, card, context) if context.cry_universum then return { - mod = to_big(card.ability.extra), + mod = lenient_bignum(card.ability.extra), colour = G.C.DARK_EDITION, message = localize("k_upgrade_ex"), } @@ -220,7 +242,7 @@ local universum = { .. tostring(vals.level) if is_number(vals.level) then G.hand_text_area.hand_level.config.colour = - G.C.HAND_LEVELS[to_big(math.min(vals.level, 7)):to_number()] + G.C.HAND_LEVELS[to_number(math.min(vals.level, 7))] else G.hand_text_area.hand_level.config.colour = G.C.HAND_LEVELS[1] end @@ -252,7 +274,7 @@ local universum = { end, })) play_sound("tarot2", 1, 0.4) - end + end -- hi return true end, })) @@ -278,6 +300,7 @@ local exponentia = { cost = 50, blueprint_compat = true, perishable_compat = false, + demicoloncompat = true, atlas = "atlasexotic", order = 503, soul_pos = { x = 2, y = 0, extra = { x = 1, y = 0 } }, @@ -291,17 +314,35 @@ local exponentia = { number_format(card.ability.extra.Emult), }, }), - Emult_mod = card.ability.extra.Emult, + Emult_mod = lenient_bignum(card.ability.extra.Emult), colour = G.C.DARK_EDITION, } end + if context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "Emult", + scalar_value = "Emult_mod", + message_key = "a_powmult", + message_colour = G.C.DARK_EDITION, + }) + return { + Emult_mod = lenient_bignum(card.ability.extra.Emult), + } + end end, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.Emult_mod, center.ability.extra.Emult } } + return { + vars = { + number_format(center.ability.extra.Emult_mod), + number_format(center.ability.extra.Emult), + }, + } end, cry_credits = { idea = { "Enemui" }, - art = { "Jevonn" }, + art = { "Lil Mr. Slipstream" }, + art = { "George the Rat" }, code = { "Math" }, }, init = function(self) @@ -309,18 +350,27 @@ local exponentia = { local scie = SMODS.calculate_individual_effect function SMODS.calculate_individual_effect(effect, scored_card, key, amount, from_edition) local ret = scie(effect, scored_card, key, amount, from_edition) - if (key == "x_mult" or key == "xmult" or key == "x_mult_mod" or key == "Xmult_mod") and amount ~= 1 then + if + ( + key == "x_mult" + or key == "xmult" + or key == "Xmult" + or key == "x_mult_mod" + or key == "xmult_mod" + or key == "Xmult_mod" + ) + and amount ~= 1 + and mult + then for _, v in pairs(find_joker("cry-Exponentia")) do local old = v.ability.extra.Emult - v.ability.extra.Emult = v.ability.extra.Emult + v.ability.extra.Emult_mod - card_eval_status_text(v, "extra", nil, nil, nil, { - message = localize({ - type = "variable", - key = "a_powmult", - vars = { number_format(to_big(v.ability.extra.Emult)) }, - }), + SMODS.scale_card(v, { + ref_table = v.ability.extra, + ref_value = "Emult", + scalar_value = "Emult_mod", + message_key = "a_powmult", + message_colour = G.C.DARK_EDITION, }) - Cryptid.exponentia_scale_mod(v, v.ability.extra.Emult_mod, old, v.ability.extra.Emult) end end return ret @@ -341,6 +391,7 @@ local speculo = { rarity = "cry_exotic", cost = 50, blueprint_compat = true, + demicoloncompat = true, immutable = true, atlas = "atlasexotic", order = 504, @@ -351,7 +402,7 @@ local speculo = { end end, calculate = function(self, card, context) - if context.ending_shop then + if context.ending_shop or context.forcetrigger then local eligibleJokers = {} for i = 1, #G.jokers.cards do if G.jokers.cards[i].ability.name ~= card.ability.name and G.jokers.cards[i].ability.set == "Joker" then @@ -401,10 +452,10 @@ local redeo = { loc_vars = function(self, info_queue, center) return { vars = { - center.ability.extra.ante_reduction, - center.ability.extra.money_req, - center.ability.extra.money_remaining, - center.ability.extra.money_mod, + number_format(center.ability.extra.ante_reduction), + number_format(center.ability.extra.money_req), + number_format(center.ability.extra.money_remaining), + number_format(center.ability.extra.money_mod), }, } end, @@ -414,21 +465,28 @@ local redeo = { order = 506, atlas = "atlasexotic", soul_pos = { x = 4, y = 0, extra = { x = 5, y = 0 } }, + demicoloncompat = true, calculate = function(self, card, context) if context.cry_ease_dollars and to_big(context.cry_ease_dollars) < to_big(0) and not context.blueprint then - card.ability.extra.money_remaining = card.ability.extra.money_remaining - context.cry_ease_dollars + card.ability.extra.money_remaining = + lenient_bignum(to_big(card.ability.extra.money_remaining) - context.cry_ease_dollars) local ante_mod = 0 while to_big(card.ability.extra.money_remaining) >= to_big(card.ability.extra.money_req) do - card.ability.extra.money_remaining = card.ability.extra.money_remaining - card.ability.extra.money_req - card.ability.extra.money_req = card.ability.extra.money_req + card.ability.extra.money_mod - card.ability.extra.money_mod = math.min(1e300, math.ceil(card.ability.extra.money_mod * 1.06)) - ante_mod = ante_mod - card.ability.extra.ante_reduction + card.ability.extra.money_remaining = + lenient_bignum(to_big(card.ability.extra.money_remaining) - card.ability.extra.money_req) + card.ability.extra.money_req = + lenient_bignum(to_big(card.ability.extra.money_req) + card.ability.extra.money_mod) + card.ability.extra.money_mod = lenient_bignum(math.ceil(to_big(card.ability.extra.money_mod) * 1.06)) + ante_mod = lenient_bignum(ante_mod - to_big(card.ability.extra.ante_reduction)) end if ante_mod < 0 then ease_ante(ante_mod) end return nil, true end + if context.forcetrigger then + ease_ante(card.ability.extra.ante_reduction) + end end, cry_credits = { idea = { "Enemui" }, @@ -457,22 +515,48 @@ local tenebris = { key = "tenebris", pos = { x = 3, y = 2 }, soul_pos = { x = 4, y = 2, extra = { x = 5, y = 2 } }, - config = { extra = { slots = 25, money = 25 } }, + config = { + extra = { + slots = 25, + money = 25, + }, + immutable = { + max_slots = 100, + }, + }, rarity = "cry_exotic", cost = 50, order = 507, atlas = "atlasexotic", + demicoloncompat = true, calc_dollar_bonus = function(self, card) - return card.ability.extra.money + return lenient_bignum(card.ability.extra.money) end, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.slots, center.ability.extra.money } } + return { + vars = { + number_format(math.min(center.ability.immutable.max_slots, center.ability.extra.slots)), + number_format(center.ability.extra.money), + }, + } + end, + calculate = function(self, card, context) + if context.forcetrigger then + return { + dollars = lenient_bignum(card.ability.extra.money), + card = card, + } + end end, add_to_deck = function(self, card, from_debuff) - G.jokers.config.card_limit = G.jokers.config.card_limit + card.ability.extra.slots + G.jokers.config.card_limit = lenient_bignum( + G.jokers.config.card_limit + math.min(card.ability.immutable.max_slots, to_big(card.ability.extra.slots)) + ) end, remove_from_deck = function(self, card, from_debuff) - G.jokers.config.card_limit = G.jokers.config.card_limit - card.ability.extra.slots + G.jokers.config.card_limit = lenient_bignum( + G.jokers.config.card_limit - math.min(card.ability.immutable.max_slots, to_big(card.ability.extra.slots)) + ) end, cry_credits = { idea = { "Gold" }, @@ -498,9 +582,10 @@ local effarcire = { order = 505, atlas = "effarcire", rarity = "cry_exotic", + demicoloncompat = true, calculate = function(self, card, context) - if not context.blueprint and not context.retrigger_joker then - if context.first_hand_drawn then + if not context.blueprint and not context.retrigger_joker or context.forcetrigger then + if context.first_hand_drawn or context.forcetrigger then G.FUNCS.draw_from_deck_to_hand(#G.deck.cards) return nil, true elseif G.hand.config.card_limit < 1 then @@ -531,7 +616,12 @@ local crustulum = { object_type = "Joker", name = "cry-crustulum", key = "crustulum", - config = { extra = { chips = 0, chip_mod = 4 } }, + config = { + extra = { + chips = 0, + chip_mod = 4, + }, + }, pos = { x = 0, y = 2 }, soul_pos = { x = 2, y = 2, extra = { x = 1, y = 2 } }, rarity = "cry_exotic", @@ -540,22 +630,46 @@ local crustulum = { atlas = "atlasexotic", blueprint_compat = true, perishable_compat = false, + demicoloncompat = true, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.chips, center.ability.extra.chip_mod } } + return { + vars = { + number_format(center.ability.extra.chips), + number_format(center.ability.extra.chip_mod), + }, + } end, calculate = function(self, card, context) if context.reroll_shop and not context.blueprint then - card.ability.extra.chips = card.ability.extra.chips + card.ability.extra.chip_mod - card_eval_status_text(card, "extra", nil, nil, nil, { - message = localize({ type = "variable", key = "a_chips", vars = { card.ability.extra.chips } }), + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "chips", + scalar_value = "chip_mod", + message_key = "a_chips", colour = G.C.CHIPS, }) return nil, true end if context.joker_main and to_big(card.ability.extra.chips) > to_big(0) then return { - message = localize({ type = "variable", key = "a_chips", vars = { card.ability.extra.chips } }), - chip_mod = card.ability.extra.chips, + message = localize({ + type = "variable", + key = "a_chips", + vars = { number_format(card.ability.extra.chips) }, + }), + chip_mod = lenient_bignum(card.ability.extra.chips), + } + end + if context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "chips", + scalar_value = "chip_mod", + message_key = "a_chips", + colour = G.C.CHIPS, + }) + return { + chip_mod = lenient_bignum(card.ability.extra.chips), } end end, @@ -584,13 +698,19 @@ local primus = { object_type = "Joker", name = "cry-primus", key = "primus", - config = { extra = { Emult = 1.01, Emult_mod = 0.17 } }, + config = { + extra = { + Emult = 1.01, + Emult_mod = 0.17, + }, + }, pos = { x = 0, y = 4 }, rarity = "cry_exotic", cost = 53, order = 510, blueprint_compat = true, perishable_compat = false, + demicoloncompat = true, atlas = "atlasexotic", soul_pos = { x = 2, y = 4, extra = { x = 1, y = 4 } }, calculate = function(self, card, context) @@ -613,16 +733,17 @@ local primus = { end end if check then - card.ability.extra.Emult = card.ability.extra.Emult + card.ability.extra.Emult_mod - return { - card_eval_status_text(card, "extra", nil, nil, nil, { - message = localize("k_upgrade_ex"), - colour = G.C.DARK_EDITION, - }), - } + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "Emult", + scalar_value = "Emult_mod", + message_colour = G.C.DARK_EDITION, + }) + card.children.floating_sprite:set_sprite_pos({ x = 8, y = 6 }) end end if context.joker_main and (to_big(card.ability.extra.Emult) > to_big(1)) then + card.children.floating_sprite:set_sprite_pos({ x = 8, y = 6 }) return { message = localize({ type = "variable", @@ -631,17 +752,37 @@ local primus = { number_format(card.ability.extra.Emult), }, }), - Emult_mod = card.ability.extra.Emult, + Emult_mod = lenient_bignum(card.ability.extra.Emult), + colour = G.C.DARK_EDITION, + } + end + if context.end_of_round then + card.children.floating_sprite:set_sprite_pos({ x = 2, y = 4 }) + end + if context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "Emult", + scalar_value = "Emult_mod", + message_colour = G.C.DARK_EDITION, + }) + return { + Emult_mod = lenient_bignum(card.ability.extra.Emult), colour = G.C.DARK_EDITION, } end end, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.Emult_mod, center.ability.extra.Emult } } + return { + vars = { + number_format(center.ability.extra.Emult_mod), + number_format(center.ability.extra.Emult), + }, + } end, cry_credits = { idea = { "Jevonn" }, - art = { "Jevonn" }, + art = { "George the Rat" }, code = { "Jevonn" }, }, } @@ -662,50 +803,53 @@ local scalae = { cost = 50, atlas = "atlasexotic", order = 311, - config = { extra = { scale = 1, scale_mod = 1, shadow_scale = 1, shadow_scale_mod = 1 } }, - --todo: support jokers that scale multiple variables + config = { extra = { scale = 1, scale_mod = 1 } }, + demicoloncompat = true, calculate = function(self, card, context) - --initialize tracking object - card.ability.extra.scale = to_big(card.ability.extra.scale) - card.ability.extra.scale_mod = to_big(card.ability.extra.scale_mod) - card.ability.extra.shadow_scale = to_big(card.ability.extra.shadow_scale) - card.ability.extra.shadow_scale_mod = to_big(card.ability.extra.shadow_scale_mod) - if context.end_of_round and not context.individual and not context.repetition and not context.blueprint then - card.ability.extra.scale = card.ability.extra.scale + card.ability.extra.scale_mod - card.ability.extra.shadow_scale = card.ability.extra.scale - card.ability.extra.scale = card.ability.extra.shadow_scale - card.ability.extra.scale_mod = card.ability.extra.shadow_scale_mod - return { - message = localize("k_upgrade_ex"), - colour = G.C.DARK_EDITION, - } + if + (context.end_of_round and not context.individual and not context.repetition and not context.blueprint) + or context.forcetrigger + then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "scale", + scalar_value = "scale_mod", + message_colour = G.C.DARK_EDITION, + }) end - card.ability.extra.scale = card.ability.extra.shadow_scale - card.ability.extra.scale_mod = card.ability.extra.shadow_scale_mod - return end, - cry_scale_mod = function(self, card, joker, orig_scale_scale, true_base, orig_scale_base, new_scale_base) - if joker.ability.name ~= "cry-Scalae" then - local new_scale = ( - to_big(true_base) - * ( - ( - 1 - + ( - (to_big(orig_scale_scale) / to_big(true_base)) - ^ (to_big(1) / to_big(card.ability.extra.scale)) - ) - ) ^ card.ability.extra.scale - ) - ) - if (new_scale < to_big(1e100)) or not Cryptid.is_card_big(joker) then - if new_scale >= to_big(1e300) then - new_scale = 1e300 - else - new_scale = to_number(new_scale) - end + calc_scaling = function(self, card, other, current_scaling, current_scalar, args) + if other.ability.name ~= "cry-Scalae" then + if not G.GAME.cryptid_base_scales then + G.GAME.cryptid_base_scales = {} end - return new_scale + if not G.GAME.cryptid_base_scales[other.config.center.key] then + G.GAME.cryptid_base_scales[other.config.center.key] = {} + end + if not G.GAME.cryptid_base_scales[other.config.center.key][args.scalar_value] then + G.GAME.cryptid_base_scales[other.config.center.key][args.scalar_value] = current_scalar + end + local true_base = G.GAME.cryptid_base_scales[other.config.center.key][args.scalar_value] + local orig_scale_scale = current_scaling + local new_scale = lenient_bignum( + to_big(true_base) + * ( + ( + 1 + + ( + (to_big(orig_scale_scale) / to_big(true_base)) + ^ (to_big(1) / to_big(card.ability.extra.scale)) + ) + ) ^ to_big(card.ability.extra.scale) + ) + ) + if not Cryptid.is_card_big(other) and to_big(new_scale) >= to_big(1e300) then + new_scale = 1e300 + end + return { + scalar_value = new_scale, + message = localize("k_upgrade_ex"), + } end end, loc_vars = function(self, info_queue, card) @@ -739,24 +883,30 @@ local stella_mortis = { object_type = "Joker", name = "cry-Stella Mortis", key = "stella_mortis", - config = { extra = { Emult = 1, Emult_mod = 0.4 } }, + config = { + extra = { + Emult = 1, + Emult_mod = 0.4, + }, + }, pos = { x = 3, y = 5 }, rarity = "cry_exotic", cost = 50, order = 502, blueprint_compat = true, perishable_compat = false, + demicoloncompat = true, atlas = "atlasexotic", soul_pos = { x = 5, y = 5, extra = { x = 4, y = 5 } }, calculate = function(self, card, context) - if context.ending_shop then + if (context.ending_shop and not context.blueprint) or context.forcetrigger then local destructable_planet = {} local quota = 1 for i = 1, #G.consumeables.cards do if G.consumeables.cards[i].ability.set == "Planet" and not G.consumeables.cards[i].getting_sliced - and not G.consumeables.cards[i].ability.eternal + and not SMODS.is_eternal(G.consumeables.cards[i]) then destructable_planet[#destructable_planet + 1] = G.consumeables.cards[i] end @@ -769,8 +919,19 @@ local stella_mortis = { if Incantation then quota = planet_to_destroy:getEvalQty() end + if Overflow then + quaota = planet_to_destroy.ability.immutable and planet_to_destroy.ability.immutable.overflow_amount + end planet_to_destroy.getting_sliced = true - card.ability.extra.Emult = card.ability.extra.Emult + card.ability.extra.Emult_mod * quota + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "Emult", + scalar_value = "Emult_mod", + operation = function(ref_table, ref_value, initial, change) + ref_table[ref_value] = initial + change * quota + end, + message_key = "a_powmult", + }) G.E_MANAGER:add_event(Event({ func = function() (context.blueprint_card or card):juice_up(0.8, 0.8) @@ -778,21 +939,11 @@ local stella_mortis = { return true end, })) - if not (context.blueprint_card or self).getting_sliced then - card_eval_status_text((context.blueprint_card or card), "extra", nil, nil, nil, { - message = localize({ - type = "variable", - key = "a_powmult", - vars = { - number_format(to_big(card.ability.extra.Emult)), - }, - }), - }) - end + planet_to_destroy.dissolve = 0 --timing issues related to crossmod stuff return nil, true end end - if context.joker_main and (to_big(card.ability.extra.Emult) > to_big(1)) then + if (context.joker_main and (to_big(card.ability.extra.Emult) > to_big(1))) or context.forcetrigger then return { message = localize({ type = "variable", @@ -801,13 +952,18 @@ local stella_mortis = { number_format(card.ability.extra.Emult), }, }), - Emult_mod = card.ability.extra.Emult, + Emult_mod = lenient_bignum(card.ability.extra.Emult), colour = G.C.DARK_EDITION, } end end, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.Emult_mod, center.ability.extra.Emult } } + return { + vars = { + number_format(center.ability.extra.Emult_mod), + number_format(center.ability.extra.Emult), + }, + } end, cry_credits = { idea = { "SMG9000" }, @@ -825,12 +981,19 @@ local circulus_pistoris = { object_type = "Joker", name = "cry-Circulus Pistoris", key = "circulus_pistoris", - config = { extra = { Emult = math.pi, Echips = math.pi, hands_remaining = 3 } }, + config = { + extra = { + Emult = math.pi, + Echips = math.pi, + hands_remaining = 3, + }, + }, pos = { x = 0, y = 3 }, rarity = "cry_exotic", cost = 10 * math.pi, order = 509, blueprint_compat = true, + demicoloncompat = true, immutable = true, atlas = "atlasexotic", soul_pos = { x = 2, y = 3, extra = { x = 1, y = 3 } }, @@ -844,11 +1007,13 @@ local circulus_pistoris = { end, calculate = function(self, card, context) if - context.joker_main - and ( - G.GAME.current_round.hands_left >= card.ability.extra.hands_remaining - and G.GAME.current_round.hands_left < card.ability.extra.hands_remaining + 1 - ) + ( + context.joker_main + and ( + G.GAME.current_round.hands_left >= card.ability.extra.hands_remaining + and G.GAME.current_round.hands_left < card.ability.extra.hands_remaining + 1 + ) + ) or context.forcetrigger then local pi = math.pi if Cryptid.safe_get(card, "edition", "cry_oversat") then @@ -882,7 +1047,12 @@ local aequilibrium = { object_type = "Joker", name = "Ace Aequilibrium", key = "equilib", - config = { extra = { jokers = 2, card = nil } }, + config = { + extra = { + jokers = 2, + card = nil, + }, + }, rarity = "cry_exotic", pos = { x = 7, y = 0 }, soul_pos = { x = 6, y = 0, extra = { x = 8, y = 0 } }, @@ -892,6 +1062,8 @@ local aequilibrium = { blueprint_compat = true, eternal_compat = true, perishable_compat = true, + demicoloncompat = true, + immutable = true, loc_vars = function(self, info_queue, center) if not center.edition or (center.edition and not center.edition.negative) then info_queue[#info_queue + 1] = G.P_CENTERS.e_negative @@ -907,7 +1079,9 @@ local aequilibrium = { return { vars = { math.floor(math.min(25, center.ability.extra.jokers)), joker_generated } } end, calculate = function(self, card, context) - if context.cardarea == G.jokers and context.before and not context.retrigger_joker then + if + (context.cardarea == G.jokers and context.before and not context.retrigger_joker) or context.forcetrigger + then for i = 1, math.floor(math.min(25, card.ability.extra.jokers)) do local newcard = create_card("Joker", G.jokers, nil, nil, nil, nil, nil) newcard:add_to_deck() @@ -933,41 +1107,64 @@ local facile = { object_type = "Joker", name = "cry-facile", key = "facile", - config = { extra = { Emult = 3, check = 10, check2 = 0 } }, + config = { + extra = { + Emult = 3, + check = 10, + }, + immutable = { + check2 = 0, + }, + }, pos = { x = 6, y = 2 }, soul_pos = { x = 8, y = 2, extra = { x = 7, y = 2 } }, rarity = "cry_exotic", cost = 50, order = 513, blueprint_compat = true, + demicoloncompat = true, atlas = "atlasexotic", loc_vars = function(self, info_queue, center) return { - vars = { center.ability.extra.Emult, center.ability.extra.check }, + vars = { + number_format(center.ability.extra.Emult), + number_format(center.ability.extra.check), + }, } end, calculate = function(self, card, context) if context.individual then if context.cardarea == G.play then - card.ability.extra.check2 = card.ability.extra.check2 + 1 + card.ability.immutable.check2 = lenient_bignum(card.ability.immutable.check2 + 1) end end if context.joker_main and (to_big(card.ability.extra.Emult) > to_big(1)) then - if card.ability.extra.check2 <= card.ability.extra.check then - card.ability.extra.check2 = 0 + if to_big(card.ability.immutable.check2) <= to_big(card.ability.extra.check) then + card.ability.immutable.check2 = 0 return { message = localize({ type = "variable", key = "a_powmult", vars = { number_format(card.ability.extra.Emult) }, }), - Emult_mod = card.ability.extra.Emult, + Emult_mod = lenient_bignum(card.ability.extra.Emult), colour = G.C.DARK_EDITION, } else - card.ability.extra.check2 = 0 + card.ability.immutable.check2 = 0 end end + if context.forcetrigger then + return { + message = localize({ + type = "variable", + key = "a_powmult", + vars = { number_format(card.ability.extra.Emult) }, + }), + Emult_mod = lenient_bignum(card.ability.extra.Emult), + colour = G.C.DARK_EDITION, + } + end end, cry_credits = { idea = { "Enemui" }, @@ -998,6 +1195,7 @@ local gemino = { }, rarity = "cry_exotic", blueprint_compat = true, + demicoloncompat = true, cost = 50, order = 515, atlas = "atlasexotic", @@ -1048,13 +1246,11 @@ local gemino = { end end, calculate = function(self, card2, context) - if context.end_of_round and not context.repetition and not context.individual then + if (context.end_of_round and not context.repetition and not context.individual) or context.forcetrigger then local check = false local card = G.jokers.cards[1] if not Card.no(G.jokers.cards[1], "immutable", true) then - Cryptid.with_deck_effects(G.jokers.cards[1], function(card) - Cryptid.misprintize(card, { min = 2, max = 2 }, nil, true) - end) + Cryptid.manipulate(G.jokers.cards[1], { value = 2 }) check = true end if check then @@ -1083,34 +1279,61 @@ local energia = { key = "energia", pos = { x = 6, y = 3 }, soul_pos = { x = 8, y = 3, extra = { x = 7, y = 3 } }, - blueprint_compat = false, + blueprint_compat = true, perishable_compat = false, + demicoloncompat = true, order = 514, - config = { extra = { tags = 1, tag_mod = 1 } }, + config = { + extra = { tags = 1, tag_mod = 1 }, + immutable = { max_tags = 40 }, + }, loc_vars = function(self, info_queue, center) return { - vars = { math.min(center.ability.extra.tags, 40), center.ability.extra.tag_mod }, + vars = { + math.min(center.ability.extra.tags, center.ability.immutable.max_tags), + center.ability.extra.tag_mod, + }, } end, rarity = "cry_exotic", cost = 50, atlas = "atlasexotic", calculate = function(self, card, context) - if context.cry_add_tag then - local value = #G.GAME.tags or 0 - local t = math.min(40 - value, card.ability.extra.tags) - card.ability.extra.tags = card.ability.extra.tags + card.ability.extra.tag_mod - if t > 0 then - card_eval_status_text(card, "extra", nil, nil, nil, { + if context.tag_added and not context.tag_added.from_energia then + -- Don't add tags if there are more then 40 (lag) + local added_tags = + math.max(math.min(card.ability.immutable.max_tags - #G.GAME.tags, card.ability.extra.tags), 0) + print(added_tags) + if added_tags > 0 then + for i = 1, added_tags do + local ab = copy_table(context.tag_added.ability) + local new_tag = Tag(context.tag_added.key) + new_tag.from_energia = true + add_tag(new_tag) + new_tag.from_energia = nil + new_tag.ability = ab + end + end + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "tags", + scalar_value = "tag_mod", + scaling_message = { message = localize({ type = "variable", key = card.ability.extra.tags == 1 and "a_tag" or "a_tags", - vars = { t }, + vars = { added_tags }, })[1], colour = G.C.DARK_EDITION, - }) - end - return { tags = math.max(t, 0) } + }, + }) + elseif context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "tags", + scalar_value = "tag_mod", + no_message = true, + }) end end, cry_credits = { @@ -1136,88 +1359,59 @@ local verisimile = { rarity = "cry_exotic", cost = 50, order = 516, - immutable = true, + + -- "i'm not making this compatible" - nova + -- "well i am" - invalid, writing this comment + demicoloncompat = true, blueprint_compat = true, + atlas = "placeholders", loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.xmult } } + return { vars = { number_format(center.ability.extra.xmult) } } end, calculate = function(self, card, context) - if context.post_trigger and not context.blueprint then - --Todo: Gros Michel, Cavendish, Planet.lua - --Bus driver is ignored because it always triggers anyway - if - context.other_joker.ability.name == "8 Ball" - or context.other_joker.ability.name == "Space Joker" - or context.other_joker.ability.name == "Business Card" - or context.other_joker.ability.name == "Hallucination" - then - local variable = context.other_joker - card.ability.extra.xmult = card.ability.extra.xmult + variable.ability.extra - card_eval_status_text( - card, - "extra", - nil, - nil, - nil, - { message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.xmult } }) } - ) - elseif - context.other_joker.ability.name == "Reserved Parking" - or context.other_joker.ability.name == "Bloodstone" - or context.other_joker.ability.name == "cry-Googol Play Card" - or context.other_joker.ability.name == "cry-Boredom" - or context.other_joker.ability.name == "cry-bonusjoker" - or context.other_joker.ability.name == "cry-multjoker" - or context.other_joker.ability.name == "cry-scrabble" - then - local variable = context.other_joker - card.ability.extra.xmult = card.ability.extra.xmult + variable.ability.extra.odds - card_eval_status_text( - card, - "extra", - nil, - nil, - nil, - { message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.xmult } }) } - ) - elseif context.other_joker.ability.name == "cry-notebook" then - --This also triggers at notebook's end of round which isn't intentional but i'm not bothered enough about this to find a workaround - local variable = context.other_joker - card.ability.extra.xmult = card.ability.extra.xmult + variable.ability.extra.odds - card_eval_status_text( - card, - "extra", - nil, - nil, - nil, - { message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.xmult } }) } - ) - end - return nil, true - elseif context.consumeable and not context.blueprint then - if context.consumeable.ability.name == "The Wheel of Fortune" and context.consumeable.cry_wheel_success then - local variable = context.consumeable - card.ability.extra.xmult = card.ability.extra.xmult + variable.ability.extra --Doesn't account for misprintizing for some reason - card_eval_status_text( - card, - "extra", - nil, - nil, - nil, - { message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.xmult } }) } - ) - end - elseif context.joker_main and (to_big(card.ability.extra.xmult) > to_big(1)) then + if context.pseudorandom_result and context.result then + -- implementation that doesn't use SMODS.scale_card; use if scale_card causes weird or unexpected behavior + --[[ + card.ability.extra.xmult = lenient_bignum(card.ability.extra.xmult + context.denominator) return { - message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.xmult } }), - Xmult_mod = card.ability.extra.xmult, + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.xmult) }, + }) + } + ]] + + SMODS.scale_card(card, { + -- this should not affect the probability in the context table + block_overrides = { + scalar = true, + }, + + ref_table = card.ability.extra, + ref_value = "xmult", + scalar_table = context, + scalar_value = "denominator", + scaling_message = { + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.xmult) }, + }), + }, + }) + + -- forcetriggers won't scale non verisimile, because how much would you scale it by + elseif context.joker_main or context.forcetrigger then + return { + xmult = lenient_bignum(card.ability.extra.xmult), } end end, cry_credits = { idea = { "Enemui" }, - code = { "Jevonn" }, + code = { "Jevonn", "invalidOS" }, }, } local duplicare = { @@ -1237,24 +1431,42 @@ local duplicare = { cost = 50, order = 517, blueprint_compat = true, + demicoloncompat = true, atlas = "atlasexotic", loc_vars = function(self, info_queue, center) return { - vars = { center.ability.extra.Xmult, center.ability.extra.Xmult_mod }, + vars = { + number_format(center.ability.extra.Xmult), + number_format(center.ability.extra.Xmult_mod), + }, } end, calculate = function(self, card, context) if not context.blueprint and ( - (context.post_trigger and context.other_joker ~= card) - or (context.individual and context.cardarea == G.play) + ( + context.post_trigger + and context.other_joker ~= card + and Cryptid.isNonRollProbabilityContext(context.other_context) + ) or (context.individual and context.cardarea == G.play) ) then - card.ability.extra.Xmult = card.ability.extra.Xmult + card.ability.extra.Xmult_mod - card_eval_status_text(card, "extra", nil, nil, nil, { message = localize("k_upgrade_ex") }) + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "Xmult", + scalar_value = "Xmult_mod", + }) end - if context.joker_main and (to_big(card.ability.extra.Xmult) > to_big(1)) then + if (context.joker_main and (to_big(card.ability.extra.Xmult) > to_big(1))) or context.forcetrigger then + if context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "Xmult", + scalar_value = "Xmult_mod", + no_message = true, + }) + end return { message = localize({ type = "variable", @@ -1263,7 +1475,7 @@ local duplicare = { number_format(card.ability.extra.Xmult), }, }), - Xmult_mod = card.ability.extra.Xmult, + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), colour = G.C.MULT, } end @@ -1350,10 +1562,23 @@ local formidiulosus = { pos = { x = 6, y = 4 }, soul_pos = { x = 8, y = 4, extra = { x = 7, y = 4 } }, blueprint_compat = true, - config = { extra = { candy = 3, Emult_mod = 0.01, Emult = 1 } }, + demicoloncompat = true, + config = { + extra = { + Emult_mod = 0.01, + Emult = 1, + }, + immutable = { + num_candies = 3, + }, + }, loc_vars = function(self, info_queue, center) return { - vars = { 3, center.ability.extra.Emult_mod, center.ability.extra.Emult }, + vars = { + center.ability.immutable.num_candies, + center.ability.extra.Emult_mod, + center.ability.extra.Emult, + }, } end, rarity = "cry_exotic", @@ -1362,8 +1587,9 @@ local formidiulosus = { atlas = "atlasexotic", no_dbl = true, update = function(self, card, front) - card.ability.extra.Emult = 1 - + (card.ability.extra.Emult_mod * #Cryptid.advanced_find_joker(nil, "cry_candy", nil, nil, true)) + card.ability.extra.Emult = lenient_bignum( + 1 + (card.ability.extra.Emult_mod * #Cryptid.advanced_find_joker(nil, "cry_candy", nil, nil, true)) + ) end, calculate = function(self, card, context) if @@ -1385,7 +1611,7 @@ local formidiulosus = { })) end if context.ending_shop then - for i = 1, 3 do + for i = 1, card.ability.immutable.num_candies do local card = create_card("Joker", G.jokers, nil, "cry_candy", nil, nil, nil, "cry_trick_candy") card:set_edition({ negative = true }, true) card:add_to_deck() @@ -1401,7 +1627,26 @@ local formidiulosus = { number_format(card.ability.extra.Emult), }, }), - Emult_mod = card.ability.extra.Emult, + Emult_mod = lenient_bignum(card.ability.extra.Emult), + colour = G.C.DARK_EDITION, + } + end + if context.forcetrigger then + for i = 1, card.ability.immutable.num_candies do + local card = create_card("Joker", G.jokers, nil, "cry_candy", nil, nil, nil, "cry_trick_candy") + card:set_edition({ negative = true }, true) + card:add_to_deck() + G.jokers:emplace(card) + end + return { + message = localize({ + type = "variable", + key = "a_powmult", + vars = { + number_format(card.ability.extra.Emult), + }, + }), + Emult_mod = lenient_bignum(card.ability.extra.Emult), colour = G.C.DARK_EDITION, } end @@ -1419,7 +1664,7 @@ local items = { exponentia, speculo, redeo, - tenebris, + tenebris, -- disabled due to bignum crash, possibly fixed? effarcire, effarcire_sprite, crustulum, @@ -1434,7 +1679,7 @@ local items = { --verisimile, WHY IS THIS AN EXOTIC???????????????????? --rescribere, [NEEDS REFACTOR] duplicare, - formidiulosus, + formidiulosus, -- see tenebris } return { name = "Exotic Jokers", diff --git a/Cryptid/items/joker_display.lua b/Cryptid/items/joker_display.lua index 0fa5313..28bef2f 100644 --- a/Cryptid/items/joker_display.lua +++ b/Cryptid/items/joker_display.lua @@ -141,6 +141,7 @@ --Penetrating Joker --Treacherous Joker +--[[ if JokerDisplay then --Side note: I Don't think retrigger type exp gives a correct value with Emult jokers, but ehhhhh ig I can live with that (It's good enough) @@ -1374,9 +1375,9 @@ if JokerDisplay then { ref_table = "card.joker_display_values", ref_value = "localized_text" }, }, calc_function = function(card) - local is_active = card.ability.extra.score >= card.ability.extra.req + local is_active = card.ability.immutable.score >= card.ability.extra.req card.joker_display_values.localized_text = "(" - .. (is_active and localize("k_active_ex") or (card.ability.extra.score .. "/" .. card.ability.extra.req)) + .. (is_active and localize("k_active_ex") or (card.ability.immutable.score .. "/" .. card.ability.extra.req)) .. ")" end, } @@ -2041,4 +2042,6 @@ if JokerDisplay then --end of Jokerdisplays end +]] +-- return { name = "JokerDisplay" } diff --git a/Cryptid/items/m.lua b/Cryptid/items/m.lua index 952f144..29ed86c 100644 --- a/Cryptid/items/m.lua +++ b/Cryptid/items/m.lua @@ -4,12 +4,18 @@ local jollysus = { name = "cry-jollysus Joker", key = "jollysus", pos = { x = 3, y = 1 }, - config = { extra = { spawn = true, active = localize("k_active_ex") } }, + config = { + extra = { + spawn = true, + active = localize("k_active_ex"), + }, + }, rarity = 1, cost = 4, order = 267, blueprint_compat = true, eternal_compat = false, + demicoloncompat = true, dependencies = { items = { "set_cry_m" }, }, @@ -71,6 +77,21 @@ local jollysus = { }), } end + if context.forcetrigger then + local card = create_card("Joker", G.jokers, nil, nil, nil, nil, nil, "jollysus") + if Cryptid.enabled("e_cry_m") == true then + card:set_edition({ cry_m = true }) + end + card:add_to_deck() + G.jokers:emplace(card) + return { + card_eval_status_text(card, "extra", nil, nil, nil, { + message = localize("cry_m_ex"), + colour = G.C.FILTER, + card = card, + }), + } + end end, cry_credits = { idea = { @@ -97,10 +118,16 @@ local bubblem = { pools = { ["M"] = true }, order = 251, pos = { x = 0, y = 0 }, - config = { extra = { spawn = false, type = "Three of a Kind" } }, + config = { + extra = { + spawn = false, + type = "Three of a Kind", + }, + }, rarity = 1, cost = 2, eternal_compat = false, + demicoloncompat = true, immutable = true, loc_vars = function(self, info_queue, center) info_queue[#info_queue + 1] = G.P_CENTERS.j_jolly @@ -152,6 +179,20 @@ local bubblem = { }), } end + if context.forcetrigger then + local card = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_jolly") + card:set_edition({ + foil = true, + }) + card:add_to_deck() + G.jokers:emplace(card) + return { + card_eval_status_text(card, "extra", nil, nil, nil, { + message = localize("cry_m_ex"), + colour = G.C.FILTER, + }), + } + end end, cry_credits = { idea = { @@ -170,7 +211,13 @@ local foodm = { name = "cry-foodm", key = "foodm", pools = { ["M"] = true, ["Food"] = true }, - config = { extra = { mult = 40, rounds_remaining = 2, round_inc = 1 } }, + config = { + extra = { + mult = 40, + rounds_remaining = 2, + round_inc = 1, + }, + }, pos = { x = 4, y = 2 }, rarity = 1, dependencies = { @@ -181,21 +228,26 @@ local foodm = { atlas = "atlasone", blueprint_compat = true, eternal_compat = false, + demicoloncompat = true, loc_vars = function(self, info_queue, center) info_queue[#info_queue + 1] = G.P_CENTERS.j_jolly return { vars = { - center.ability.extra.mult, - center.ability.extra.rounds_remaining, - center.ability.extra.round_inc, + number_format(center.ability.extra.mult), + number_format(center.ability.extra.rounds_remaining), + number_format(center.ability.extra.round_inc), }, } end, calculate = function(self, card, context) - if context.joker_main and (card.ability.extra.mult > 0) then + if context.joker_main and (to_big(card.ability.extra.mult) > to_big(0)) then return { - message = localize({ type = "variable", key = "a_mult", vars = { card.ability.extra.mult } }), - mult_mod = card.ability.extra.mult, + message = localize({ + type = "variable", + key = "a_mult", + vars = { number_format(card.ability.extra.mult) }, + }), + mult_mod = lenient_bignum(card.ability.extra.mult), colour = G.C.MULT, } end @@ -206,8 +258,8 @@ local foodm = { and not context.repetition and not context.retrigger_joker then - card.ability.extra.rounds_remaining = card.ability.extra.rounds_remaining - 1 - if card.ability.extra.rounds_remaining > 0 then + card.ability.extra.rounds_remaining = lenient_bignum(to_big(card.ability.extra.rounds_remaining) - 1) + if to_big(card.ability.extra.rounds_remaining) > to_big(0) then return { message = { localize("cry_minus_round") }, colour = G.C.FILTER, @@ -245,14 +297,30 @@ local foodm = { and not context.retrigger_joker and context.card:is_jolly() then - card.ability.extra.rounds_remaining = card.ability.extra.rounds_remaining + card.ability.extra.round_inc + card.ability.extra.rounds_remaining = + lenient_bignum(to_big(card.ability.extra.rounds_remaining) + card.ability.extra.round_inc) return { card_eval_status_text(card, "extra", nil, nil, nil, { - message = localize({ type = "variable", key = "a_round", vars = { card.ability.extra.round_inc } }), + message = localize({ + type = "variable", + key = "a_round", + vars = { number_format(card.ability.extra.round_inc) }, + }), colour = G.C.FILTER, }), } end + if context.forcetrigger then + return { + message = localize({ + type = "variable", + key = "a_mult", + vars = { number_format(card.ability.extra.mult) }, + }), + mult_mod = lenient_bignum(card.ability.extra.mult), + colour = G.C.MULT, + } + end end, cry_credits = { idea = { @@ -272,7 +340,17 @@ local mstack = { key = "mstack", pools = { ["M"] = true }, order = 253, - config = { extra = { sell = 0, sell_req = 3, retriggers = 1, check = false } }, + config = { + extra = { + sell = 0, + sell_req = 3, + retriggers = 1, + check = false, + }, + immutable = { + max_retriggers = 40, + }, + }, dependencies = { items = { "set_cry_m" }, }, @@ -284,14 +362,22 @@ local mstack = { perishable_compat = false, loc_vars = function(self, info_queue, center) info_queue[#info_queue + 1] = G.P_CENTERS.j_jolly - return { vars = { center.ability.extra.retriggers, center.ability.extra.sell_req, center.ability.extra.sell } } + return { + vars = { + number_format(math.min(center.ability.extra.retriggers, center.ability.immutable.max_retriggers)), + number_format(center.ability.extra.sell_req), + number_format(center.ability.extra.sell), + }, + } end, calculate = function(self, card, context) if context.repetition then if context.cardarea == G.play then return { message = localize("k_again_ex"), - repetitions = math.min(card.ability.extra.retriggers, 40), + repetitions = to_number( + math.min(card.ability.extra.retriggers, card.ability.immutable.max_retriggers) + ), card = card, } end @@ -304,9 +390,9 @@ local mstack = { and not context.retrigger_joker then card.ability.extra.check = true - if card.ability.extra.sell + 1 >= card.ability.extra.sell_req then + if to_big(card.ability.extra.sell) + 1 >= to_big(card.ability.extra.sell_req) then if not context.blueprint or context.retrigger_joker then - card.ability.extra.retriggers = card.ability.extra.retriggers + 1 + card.ability.extra.retriggers = lenient_bignum(to_big(card.ability.extra.retriggers) + 1) end card.ability.extra.sell = 0 return { @@ -319,7 +405,9 @@ local mstack = { card.ability.extra.sell = card.ability.extra.sell + 1 return { card_eval_status_text(card, "extra", nil, nil, nil, { - message = card.ability.extra.sell .. "/" .. card.ability.extra.sell_req, + message = number_format(card.ability.extra.sell) .. "/" .. number_format( + card.ability.extra.sell_req + ), colour = G.C.FILTER, }), } @@ -327,8 +415,8 @@ local mstack = { end end, add_to_deck = function(self, card, from_debuff) --Force retriggers to be 1 when bought/obtained on misprint deck (no 0.43 retriggers that do nothing) - card.ability.extra.retriggers = math.floor(card.ability.extra.retriggers) - if card.ability.extra.retriggers < 1 and not card.ability.extra.check then + card.ability.extra.retriggers = lenient_bignum(math.floor(card.ability.extra.retriggers)) + if to_big(card.ability.extra.retriggers) < to_big(1) and not card.ability.extra.check then card.ability.extra.retriggers = 1 end end, @@ -354,32 +442,60 @@ local mneon = { pools = { ["M"] = true }, pos = { x = 4, y = 2 }, order = 254, - config = { extra = { bonus = 1, money = 0 } }, + config = { + extra = { + bonus = 1, + money = 0, + }, + }, rarity = 2, cost = 7, perishable_compat = false, blueprint_compat = false, + demicoloncompat = true, loc_vars = function(self, info_queue, center) info_queue[#info_queue + 1] = G.P_CENTERS.j_jolly - return { vars = { center.ability.extra.bonus, center.ability.extra.money } } + return { + vars = { + number_format(center.ability.extra.bonus), + number_format(center.ability.extra.money), + }, + } end, atlas = "atlastwo", calculate = function(self, card, context) if context.end_of_round and not context.blueprint and not context.individual and not context.repetition then local jollycount = 0 for i = 1, #G.jokers.cards do - if G.jokers.cards[i]:is_jolly() or Cryptid.safe_get(G.jokers.cards[i].config.center, "pools", "M") then + if + G.jokers.cards[i]:is_jolly() + or Cryptid.safe_get(G.jokers.cards[i].config.center, "pools", "M") + or G.jokers.cards[i].ability.name == "cry-mprime" + then jollycount = jollycount + 1 end end - card.ability.extra.money = card.ability.extra.money - + math.max(1, card.ability.extra.bonus) * (jollycount or 1) + card.ability.extra.money = lenient_bignum( + to_big(card.ability.extra.money) + math.max(1, to_big(card.ability.extra.bonus)) * (jollycount or 1) + ) + -- currently can't use SMODS.scale_card unless a for loop is used to trigger scaling once for every jolly joker + return { message = localize("cry_m_ex") } end + if context.forcetrigger then + card.ability.extra.money = lenient_bignum( + to_big(card.ability.extra.money) + math.max(1, to_big(card.ability.extra.bonus)) * (jollycount or 1) + ) + return { + dollars = lenient_bignum( + to_big(card.ability.extra.money) + math.max(1, to_big(card.ability.extra.bonus)) * (jollycount or 1) + ), + } + end end, calc_dollar_bonus = function(self, card) - if card.ability.extra.money > 0 then - return card.ability.extra.money + if to_big(card.ability.extra.money) > to_big(0) then + return lenient_bignum(card.ability.extra.money) end end, cry_credits = { @@ -405,21 +521,34 @@ local notebook = { pos = { x = 1, y = 0 }, order = 255, config = { - extra = { odds = 7, slot = 0, jollies = 4, check = true, active = "Active", inactive = "", add = 1 }, + extra = { + add = 1, + odds = 7, + jollies = 4, + check = true, + active = "Active", + inactive = "", + }, + immutable = { + slots = 0, + max_slots = 100, + }, }, rarity = 3, cost = 9, perishable_compat = false, + demicoloncompat = true, loc_vars = function(self, info_queue, card) info_queue[#info_queue + 1] = G.P_CENTERS.j_jolly + local aaa, bbb = SMODS.get_probability_vars(card, 1, card.ability.extra.odds, "Notebook") return { vars = { - cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged), - card.ability.extra.odds, - card.ability.extra.slot, - card.ability.extra.active, - card.ability.extra.jollies, - card.ability.extra.add, + aaa, + bbb, + number_format(card.ability.immutable.slots), + number_format(card.ability.extra.active), + number_format(card.ability.extra.jollies), + number_format(card.ability.extra.add), }, } end, @@ -437,13 +566,20 @@ local notebook = { jollycount = jollycount + 1 end end - if - jollycount >= card.ability.extra.jollies --if there are 5 or more jolly jokers - or pseudorandom("cry_notebook") - < cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged) / card.ability.extra.odds - then - card.ability.extra.slot = card.ability.extra.slot + card.ability.extra.add - G.jokers.config.card_limit = G.jokers.config.card_limit + card.ability.extra.add + local aaa = to_number(jollycount) >= to_number(card.ability.extra.jollies) + if aaa or SMODS.pseudorandom_probability(card, "cry_notebook", 1, card.ability.extra.odds, "Notebook") then + card.ability.immutable.slots = to_number( + math.min( + card.ability.immutable.max_slots, + lenient_bignum(card.ability.immutable.slots + to_big(card.ability.extra.add)) + ) + ) + + if to_big(card.ability.immutable.slots) >= to_big(card.ability.immutable.max_slots) then + card.ability.extra.add = 0 + end + + G.jokers.config.card_limit = lenient_bignum(G.jokers.config.card_limit + to_big(card.ability.extra.add)) card.ability.extra.check = false card.ability.extra.active = localize("cry_inactive") return { @@ -464,12 +600,26 @@ local notebook = { } end end + if context.forcetrigger then + card.ability.immutable.slots = to_number( + math.min( + card.ability.immutable.max_slots, + lenient_bignum(card.ability.immutable.slots + to_big(card.ability.extra.add)) + ) + ) + + if card.ability.immutable.slots >= card.ability.immutable.max_slots then + card.ability.extra.add = 0 + end + + G.jokers.config.card_limit = lenient_bignum(G.jokers.config.card_limit + to_big(card.ability.extra.add)) + end end, add_to_deck = function(self, card, from_debuff) - G.jokers.config.card_limit = G.jokers.config.card_limit + card.ability.extra.slot + G.jokers.config.card_limit = lenient_bignum(G.jokers.config.card_limit + to_big(card.ability.immutable.slots)) end, remove_from_deck = function(self, card, from_debuff) - G.jokers.config.card_limit = G.jokers.config.card_limit - card.ability.extra.slot + G.jokers.config.card_limit = lenient_bignum(G.jokers.config.card_limit - to_big(card.ability.immutable.slots)) end, cry_credits = { idea = { @@ -485,7 +635,10 @@ local notebook = { } local bonk = { dependencies = { - items = { "set_cry_m" }, + items = { + "set_cry_m", + "set_cry_meme", + }, }, object_type = "Joker", name = "cry-bonk", @@ -493,15 +646,22 @@ local bonk = { pools = { ["M"] = true, ["Meme"] = true }, order = 256, pos = { x = 2, y = 2 }, - config = { extra = { chips = 6, bonus = 1, xchips = 3, type = "Pair" } }, + config = { + extra = { + chips = 6, + bonus = 1, + xchips = 3, + type = "Pair", + }, + }, loc_vars = function(self, info_queue, center) info_queue[#info_queue + 1] = G.P_CENTERS.j_jolly return { vars = { - center.ability.extra.chips, - center.ability.extra.bonus, + number_format(center.ability.extra.chips), + number_format(center.ability.extra.bonus), localize(center.ability.extra.type, "poker_hands"), - (center.ability.extra.chips * center.ability.extra.xchips), + number_format(lenient_bignum(to_big(center.ability.extra.chips) * center.ability.extra.xchips)), }, } end, @@ -510,13 +670,15 @@ local bonk = { blueprint_compat = true, atlas = "atlasone", perishable_compat = false, + demicoloncompat = true, calculate = function(self, card, context) if context.cardarea == G.jokers and context.before and not context.blueprint then if context.scoring_name == card.ability.extra.type then - card.ability.extra.chips = card.ability.extra.chips + card.ability.extra.bonus - card_eval_status_text(card, "extra", nil, nil, nil, { - message = localize("k_upgrade_ex"), - colour = G.C.CHIPS, + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "chips", + scalar_value = "bonus", + message_colour = G.C.CHIPS, }) return nil, true end @@ -535,9 +697,11 @@ local bonk = { message = localize({ type = "variable", key = "a_chips", - vars = { card.ability.extra.chips * card.ability.extra.xchips }, + vars = { + number_format(lenient_bignum(to_big(card.ability.extra.chips) * card.ability.extra.xchips)), + }, }), - chip_mod = card.ability.extra.chips * card.ability.extra.xchips, + chip_mod = lenient_bignum(to_big(card.ability.extra.chips) * card.ability.extra.xchips), } else if not Talisman.config_file.disable_anims then @@ -549,14 +713,30 @@ local bonk = { })) end return { - message = localize({ type = "variable", key = "a_chips", vars = { card.ability.extra.chips } }), - chip_mod = card.ability.extra.chips, + message = localize({ + type = "variable", + key = "a_chips", + vars = { number_format(card.ability.extra.chips) }, + }), + chip_mod = lenient_bignum(card.ability.extra.chips), } end end + if context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "chips", + scalar_value = "bonus", + message_key = "a_chips", + message_colour = G.C.CHIPS, + }) + return { + chip_mod = lenient_bignum(to_big(card.ability.extra.chips) * card.ability.extra.xchips), + } + end end, add_to_deck = function(self, card, from_debuff) - card.ability.extra.xchips = math.floor(card.ability.extra.xchips + 0.5) --lua moment + card.ability.extra.xchips = lenient_bignum(math.floor(to_big(card.ability.extra.xchips) + 0.5)) --lua moment end, cry_credits = { idea = { @@ -578,18 +758,17 @@ local loopy = { name = "cry-loopy", key = "loopy", pools = { ["M"] = true }, - config = { extra = { retrigger = 0 } }, + config = { extra = { retrigger = 0 }, immutable = { limit = 40 } }, pos = { x = 7, y = 0 }, order = 257, atlas = "atlastwo", immutable = true, rarity = 1, cost = 4, - joker_gate = "Jolly Joker", blueprint_compat = true, loc_vars = function(self, info_queue, center) info_queue[#info_queue + 1] = G.P_CENTERS.j_jolly - return { vars = { center.ability.extra.retrigger } } + return { vars = { math.min(center.ability.extra.retrigger, center.ability.immutable.limit) } } end, calculate = function(self, card, context) if @@ -598,7 +777,7 @@ local loopy = { and not context.blueprint and not context.retrigger_joker then - card.ability.extra.retrigger = card.ability.extra.retrigger + 1 + card.ability.extra.retrigger = math.min((card.ability.extra.retrigger + 1), card.ability.immutable.limit) return { card_eval_status_text(card, "extra", nil, nil, nil, { message = localize("cry_m_ex"), @@ -615,7 +794,7 @@ local loopy = { return { message = localize("k_again_ex"), colour = G.C.GREEN, - repetitions = card.ability.extra.retrigger, + repetitions = math.min(card.ability.extra.retrigger, card.ability.immutable.limit), card = card, } end @@ -646,26 +825,20 @@ local scrabble = { rarity = 2, cost = 8, blueprint_compat = true, + demicoloncompat = true, atlas = "atlasone", loc_vars = function(self, info_queue, card) if Cryptid.enabled("e_cry_m") == true then info_queue[#info_queue + 1] = G.P_CENTERS.e_cry_m end return { - vars = { - cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged), - card.ability.extra.odds, - }, + vars = { SMODS.get_probability_vars(card, 1, card.ability.extra.odds, "Scrabble Tile") }, } end, calculate = function(self, card, context) if context.cardarea == G.jokers and context.before and not context.retrigger_joker then local check = false - if - pseudorandom("scrabbleother") - < cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged) - / card.ability.extra.odds - then + if SMODS.pseudorandom_probability(card, "scrabbleother", 1, card.ability.extra.odds, "Scrabble Tile") then check = true local card = create_card("Joker", G.jokers, nil, 0.9, nil, nil, nil, "scrabbletile") if Cryptid.enabled("e_cry_m") == true then @@ -686,6 +859,14 @@ local scrabble = { return nil, true end end + if context.forcetrigger then + local card = create_card("Joker", G.jokers, nil, 0.9, nil, nil, nil, "scrabbletile") + if Cryptid.enabled("e_cry_m") == true then + card:set_edition({ cry_m = true }) + end + card:add_to_deck() + G.jokers:emplace(card) + end end, cry_credits = { idea = { @@ -707,20 +888,31 @@ local sacrifice = { }, key = "sacrifice", pools = { ["M"] = true }, - config = { extra = { jollies = 3, unc = 1, text = localize("k_active_ex"), spawn = true } }, + config = { + extra = { + jollies = 3, + unc = 1, + text = localize("k_active_ex"), + spawn = true, + }, + immutable = { + max_spawns = 30, + }, + }, pos = { x = 5, y = 2 }, order = 259, rarity = 1, cost = 4, blueprint_compat = true, + demicoloncompat = true, atlas = "atlasone", loc_vars = function(self, info_queue, center) info_queue[#info_queue + 1] = G.P_CENTERS.j_jolly return { vars = { center.ability.extra.text, - math.min(30, center.ability.extra.jollies), - math.min(30, center.ability.extra.unc), + math.min(center.ability.immutable.max_spawns, center.ability.extra.jollies), + math.min(center.ability.immutable.max_spawns, center.ability.extra.unc), }, } end, @@ -735,18 +927,18 @@ local sacrifice = { end, })) end - if card.ability.extra.jollies < 1 then + if to_big(card.ability.extra.jollies) < to_big(1) then card.ability.extra.jollies = 1 end - if card.ability.extra.unc < 1 then + if to_big(card.ability.extra.unc) < to_big(1) then card.ability.extra.unc = 1 end - for i = 1, math.min(30, card.ability.extra.jollies) do + for i = 1, math.min(card.ability.immutable.max_spawns, card.ability.extra.jollies) do local jolly = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_jolly") jolly:add_to_deck() G.jokers:emplace(jolly) end - for i = 1, math.min(30, card.ability.extra.unc) do + for i = 1, math.min(card.ability.immutable.max_spawns, card.ability.extra.unc) do local unc = create_card("Joker", G.jokers, nil, 0.9, nil, nil, nil, "sacrifice") unc:add_to_deck() G.jokers:emplace(unc) @@ -773,6 +965,33 @@ local sacrifice = { } end end + if context.forcetrigger then + if to_big(card.ability.extra.jollies) < to_big(1) then + card.ability.extra.jollies = 1 + end + if to_big(card.ability.extra.unc) < to_big(1) then + card.ability.extra.unc = 1 + end + for i = 1, math.min(card.ability.immutable.max_spawns, card.ability.extra.jollies) do + local jolly = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_jolly") + jolly:add_to_deck() + G.jokers:emplace(jolly) + end + for i = 1, math.min(card.ability.immutable.max_spawns, card.ability.extra.unc) do + local unc = create_card("Joker", G.jokers, nil, 0.9, nil, nil, nil, "sacrifice") + unc:add_to_deck() + G.jokers:emplace(unc) + unc:start_materialize() + end + card_eval_status_text( + context.blueprint_card or card, + "extra", + nil, + nil, + nil, + { message = localize("cry_m_ex"), colour = G.C.SPECTRAL } + ) + end end, cry_credits = { idea = { @@ -794,9 +1013,15 @@ local reverse = { key = "reverse", effect = "M Joker", dependencies = { - items = { "set_cry_m" }, + items = { + "set_cry_m", + "set_cry_meme", + }, + }, + config = { + extra = { type = "Pair" }, + immutable = { max_spawns = 100 }, }, - config = { extra = { type = "Pair" } }, pools = { ["Meme"] = true, ["M"] = true }, pos = { x = 0, y = 0 }, display_size = { w = 0.7 * 71, h = 0.7 * 95 }, @@ -804,6 +1029,7 @@ local reverse = { order = 260, cost = 4, eternal_compat = false, + demicoloncompat = true, immutable = true, atlas = "atlastwo", loc_vars = function(self, info_queue, center) @@ -840,8 +1066,10 @@ local reverse = { return true end, })) - local spawnamount = math.min(100, G.jokers.config.card_limit - (#G.jokers.cards + G.GAME.joker_buffer)) - + 1 -- +1 to account for reverse card self destruct + local spawnamount = math.min( + card.ability.immutable.max_spawns, + G.jokers.config.card_limit - (#G.jokers.cards + G.GAME.joker_buffer) + ) + 1 -- +1 to account for reverse card self destruct G.GAME.joker_buffer = G.GAME.joker_buffer + spawnamount G.E_MANAGER:add_event(Event({ func = function() @@ -867,6 +1095,35 @@ local reverse = { ) end end + if context.forcetrigger then + local spawnamount = math.min( + card.ability.immutable.max_spawns, + G.jokers.config.card_limit - (#G.jokers.cards + G.GAME.joker_buffer) + ) + 1 -- +1 to account for reverse card self destruct + G.GAME.joker_buffer = G.GAME.joker_buffer + spawnamount + G.E_MANAGER:add_event(Event({ + func = function() + for i = 1, spawnamount do + local card = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_jolly") + card:set_edition({ + holo = true, --certified Thunk moment, this literally took ten minutes to figure out why is it set up like this + }) + card:add_to_deck() + G.jokers:emplace(card) + G.GAME.joker_buffer = 0 + end + return true + end, + })) + card_eval_status_text( + card, + "extra", + nil, + nil, + nil, + { message = localize("cry_m_ex"), colour = G.C.DARK_EDITION } + ) + end end, cry_credits = { idea = { @@ -892,27 +1149,39 @@ local doodlem = { "set_cry_epic", }, }, - config = { extra = { add = 1, init = 2 } }, + config = { + extra = { + add = 1, + init = 2, + }, + immutable = { max_jollies = 25 }, + }, pos = { x = 2, y = 0 }, rarity = "cry_epic", cost = 13, order = 266, blueprint_compat = true, + demicoloncompat = true, loc_vars = function(self, info_queue, center) info_queue[#info_queue + 1] = G.P_CENTERS.j_jolly info_queue[#info_queue + 1] = { key = "e_negative_consumable", set = "Edition", config = { extra = 1 } } - return { vars = { center.ability.extra.add, center.ability.extra.init } } + return { + vars = { + number_format(center.ability.extra.add), + number_format(center.ability.extra.init), + }, + } end, calculate = function(self, card, context) - if context.setting_blind and not (context.blueprint_card or self).getting_sliced then - local jollycount = card.ability.extra.init + if (context.setting_blind and not (context.blueprint_card or self).getting_sliced) or context.forcetrigger then + local jollycount = lenient_bignum(card.ability.extra.init) for i = 1, #G.jokers.cards do if G.jokers.cards[i]:is_jolly() then - jollycount = jollycount + math.floor(card.ability.extra.add) + jollycount = lenient_bignum(to_big(jollycount) + math.floor(card.ability.extra.add)) end end - if jollycount > 25 then - jollycount = 25 + if to_big(jollycount) > to_big(card.ability.immutable.max_jollies) then + jollycount = card.ability.immutable.max_jollies end --reduce excessive consumeable spam (Lag) for i = 1, jollycount do local card = create_card("Consumeables", G.consumeables, nil, nil, nil, nil, nil, "cry_doodlem") @@ -943,6 +1212,44 @@ local doodlem = { }, }, } +-- To organize virgo's code a little better +local function virgoJollies(card) + G.E_MANAGER:add_event(Event({ + func = function() + G.E_MANAGER:add_event(Event({ + func = function() + local summon = lenient_bignum( + math.floor( + (to_big(card.ability.extra_value) + to_big(card.cost / 2)) + / to_big(card.ability.extra.bonus) + ) + ) + if summon == nil or to_big(summon) < to_big(1) then + summon = 1 + end --precautionary measure, just in case + for i = 1, math.min(card.ability.immutable.max_summons, summon) do --another precautionary measure + local card = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_jolly") + card:set_edition({ + polychrome = true, + }) + card:add_to_deck() + G.jokers:emplace(card) + end + return true + end, + })) + card_eval_status_text( + card, + "extra", + nil, + nil, + nil, + { message = localize("cry_m_ex"), colour = G.C.DARK_EDITION } + ) + return true + end, + })) +end local virgo = { object_type = "Joker", name = "cry-virgo", @@ -956,17 +1263,29 @@ local virgo = { }, pos = { x = 1, y = 2 }, soul_pos = { x = 10, y = 0, extra = { x = 2, y = 2 } }, - config = { extra = { bonus = 4, type = "Pair" } }, + config = { + extra = { + bonus = 4, + type = "Pair", + }, + immutable = { max_summons = 80 }, + }, rarity = "cry_epic", cost = 8, order = 265, eternal_compat = false, + demicoloncompat = true, loc_vars = function(self, info_queue, center) info_queue[#info_queue + 1] = G.P_CENTERS.j_jolly if not center.edition or (center.edition and not center.edition.polychrome) then info_queue[#info_queue + 1] = G.P_CENTERS.e_polychrome end - return { vars = { center.ability.extra.bonus, localize(center.ability.extra.type, "poker_hands") } } + return { + vars = { + number_format(center.ability.extra.bonus), + localize(center.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasepic", calculate = function(self, card, context) @@ -976,45 +1295,32 @@ local virgo = { and next(context.poker_hands["Pair"]) and not context.blueprint then - card.ability.extra_value = card.ability.extra_value + card.ability.extra.bonus --this doesn't seem to work with retrigger jokers. Intentional? - card:set_cost() - card_eval_status_text(card, "extra", nil, nil, nil, { - message = localize("k_val_up"), - colour = G.C.MONEY, + --this doesn't seem to work with retrigger jokers. Intentional? + SMODS.scale_card(card, { + ref_table = card.ability, + ref_value = "extra_value", + scalar_table = card.ability.extra, + scalar_value = "bonus", }) - end - if context.selling_self and not context.blueprint and not context.retrigger_joker then - G.E_MANAGER:add_event(Event({ - func = function() - G.E_MANAGER:add_event(Event({ - func = function() - local summon = math.floor((card.ability.extra_value + 4) / 4) - if summon < 1 or summon == nil then - summon = 1 - end --precautionary measure, just in case - for i = 1, math.min(80, summon) do --another precautionary measure - local card = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_jolly") - card:set_edition({ - polychrome = true, - }) - card:add_to_deck() - G.jokers:emplace(card) - end - return true - end, - })) - card_eval_status_text( - card, - "extra", - nil, - nil, - nil, - { message = localize("cry_m_ex"), colour = G.C.DARK_EDITION } - ) - return true - end, - })) + card:set_cost() + if not msg or type(msg) == "string" then + card_eval_status_text(card, "extra", nil, nil, nil, { + message = msg or localize("k_val_up"), + colour = G.C.MONEY, + }) + end + elseif context.selling_self and not context.blueprint and not context.retrigger_joker then + virgoJollies(card) return nil, true + elseif context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability, + ref_value = "extra_value", + scalar_table = card.ability.extra, + scalar_value = "bonus", + }) + + virgoJollies(card) end end, cry_credits = { @@ -1071,6 +1377,17 @@ local smallestm = { }) end end + if context.forcetrigger then + local tag = Tag("tag_cry_double_m") + tag.ability.shiny = Cryptid.is_shiny() + add_tag(tag) + play_sound("generic1", 0.9 + math.random() * 0.1, 0.8) + play_sound("holo1", 1.2 + math.random() * 0.1, 0.4) + card_eval_status_text(context.blueprint_card or card, "extra", nil, nil, nil, { + message = localize("cry_m_ex"), + colour = G.C.FILTER, + }) + end end, cry_credits = { idea = { @@ -1088,7 +1405,14 @@ local biggestm = { object_type = "Joker", name = "cry-biggestm", key = "biggestm", - config = { extra = { x_mult = 7, type = "Pair", check = false, text = "Inactive" } }, + config = { + extra = { + x_mult = 7, + type = "Pair", + check = false, + text = "Inactive", + }, + }, pos = { x = 3, y = 3 }, display_size = { w = 1.7 * 71, h = 1.7 * 95 }, dependencies = { @@ -1102,21 +1426,26 @@ local biggestm = { cost = 12, order = 268, blueprint_compat = true, + demicoloncompat = true, atlas = "atlasepic", loc_vars = function(self, info_queue, center) return { vars = { - center.ability.extra.x_mult, + number_format(center.ability.extra.x_mult), localize(center.ability.extra.type, "poker_hands"), center.ability.extra.text, }, } end, calculate = function(self, card, context) - if context.joker_main and card.ability.extra.check then + if (context.joker_main and card.ability.extra.check) or context.forcetrigger then return { - message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.x_mult } }), - Xmult_mod = card.ability.extra.x_mult, + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.x_mult) }, + }), + Xmult_mod = lenient_bignum(card.ability.extra.x_mult), colour = G.C.MULT, } end @@ -1151,7 +1480,7 @@ local biggestm = { "Kailen", }, art = { - "Kailen", + "Ein13", }, code = { "Kailen", @@ -1170,10 +1499,20 @@ local mprime = { key = "mprime", pos = { x = 0, y = 5 }, soul_pos = { x = 2, y = 5, extra = { x = 1, y = 5 } }, - config = { extra = { mult = 1.05, bonus = 0.04 } }, + config = { + extra = { + mult = 1.05, + bonus = 0.04, + }, + }, loc_vars = function(self, info_queue, center) info_queue[#info_queue + 1] = G.P_CENTERS.j_jolly - return { vars = { center.ability.extra.mult, center.ability.extra.bonus } } + return { + vars = { + number_format(center.ability.extra.mult), + number_format(center.ability.extra.bonus), + }, + } end, rarity = "cry_exotic", cost = 50, @@ -1181,20 +1520,19 @@ local mprime = { blueprint_compat = true, atlas = "atlasexotic", perishable_compat = false, + demicoloncompat = true, calculate = function(self, card, context) if context.selling_card and (context.card:is_jolly()) then if not context.blueprint then - card.ability.extra.mult = card.ability.extra.mult + card.ability.extra.bonus - end - if not context.retrigger_joker then - card_eval_status_text( - card, - "extra", - nil, - nil, - nil, - { message = localize("cry_m_ex"), colour = G.C.DARK_EDITION } - ) + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "mult", + scalar_value = "bonus", + scaling_message = { + message = localize("cry_m_ex"), + colour = G.C.DARK_EDITION, + }, + }) end elseif context.end_of_round @@ -1233,13 +1571,47 @@ local mprime = { })) end return { - message = localize({ type = "variable", key = "a_powmult", vars = { card.ability.extra.mult } }), - Emult_mod = card.ability.extra.mult, + message = localize({ + type = "variable", + key = "a_powmult", + vars = { number_format(card.ability.extra.mult) }, + }), + Emult_mod = lenient_bignum(card.ability.extra.mult), colour = G.C.DARK_EDITION, card = card, } end end + if context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "mult", + scalar_value = "bonus", + }) + local mjoker = math.min(1, G.jokers.config.card_limit - (#G.jokers.cards + G.GAME.joker_buffer)) + G.GAME.joker_buffer = G.GAME.joker_buffer + mjoker + G.E_MANAGER:add_event(Event({ + func = function() + if mjoker > 0 then + local card = create_card("M", G.jokers, nil, nil, nil, nil, nil, "mprime") + card:add_to_deck() + G.jokers:emplace(card) + card:start_materialize() + G.GAME.joker_buffer = 0 + end + return true + end, + })) + return { + message = localize({ + type = "variable", + key = "a_powmult", + vars = { number_format(card.ability.extra.mult) }, + }), + Emult_mod = lenient_bignum(card.ability.extra.mult), + colour = G.C.DARK_EDITION, + } + end end, cry_credits = { idea = { @@ -1266,17 +1638,28 @@ local macabre = { order = 263, pos = { x = 1, y = 2 }, display_size = { w = 1.2 * 71, h = 1.2 * 95 }, - config = { extra = { add = 1 } }, + config = { + extra = { add = 1 }, + immutable = { max_spawn = 15 }, + }, loc_vars = function(self, info_queue, center) info_queue[#info_queue + 1] = G.P_CENTERS.j_jolly - return { vars = { math.min(15, center.ability.extra.add) } } + return { + vars = { + math.min(center.ability.immutable.max_spawn, center.ability.extra.add), + }, + } end, rarity = 1, cost = 5, atlas = "atlasthree", + demicoloncompat = true, calculate = function(self, card, context) - if context.setting_blind and not (context.blueprint or context.retrigger_joker) and not card.getting_sliced then - if card.ability.extra.add < 1 then + if + (context.setting_blind and not (context.blueprint or context.retrigger_joker) and not card.getting_sliced) + or context.forcetrigger + then + if to_big(card.ability.extra.add) < to_big(1) then card.ability.extra.add = 1 end G.E_MANAGER:add_event(Event({ @@ -1289,7 +1672,7 @@ local macabre = { and not v:is_jolly() and v.config.center.key ~= "j_cry_mprime" and not ( - v.ability.eternal + SMODS.is_eternal(v) or v.getting_sliced or Cryptid.safe_get(v.config.center, "pools", "M") ) @@ -1304,7 +1687,7 @@ local macabre = { triggered = true v.getting_sliced = true v:start_dissolve({ HEX("57ecab") }, nil, 1.6) - for i = 1, math.min(15, card.ability.extra.add) do + for i = 1, math.min(card.ability.immutable.max_spawn, card.ability.extra.add) do local jolly_card = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_jolly") jolly_card:add_to_deck() G.jokers:emplace(jolly_card) @@ -1337,19 +1720,26 @@ local megg = { }, object_type = "Joker", name = "cry-megg", - key = "Megg", + key = "megg", pools = { ["M"] = true }, blueprint_compat = false, eternal_compat = false, + demicoloncompat = true, pos = { x = 0, y = 4 }, order = 262, - config = { extra = { amount = 0, amount_mod = 1 }, jolly = { t_mult = 8, type = "Pair" } }, + config = { + extra = { + amount = 0, + amount_mod = 1, + }, + immutable = { max_amount = 200 }, + }, loc_vars = function(self, info_queue, center) info_queue[#info_queue + 1] = G.P_CENTERS.j_jolly return { vars = { math.max(1, center.ability.extra.amount_mod), - math.min(200, math.floor(center.ability.extra.amount)), + math.min(center.ability.immutable.max_amount, math.floor(center.ability.extra.amount)), (center.ability.extra.amount > 1 and "Jokers") or "Joker", }, } @@ -1360,29 +1750,47 @@ local megg = { calculate = function(self, card, context) if context.end_of_round - and card.ability.extra.amount < 200 + and to_big(card.ability.extra.amount) < to_big(card.ability.immutable.max_amount) and not (context.individual or context.repetition or context.blueprint) then - card.ability.extra.amount = card.ability.extra.amount + math.max(1, card.ability.extra.amount_mod) - if card.ability.extra.amount > 200 then - card.ability.extra.amount = 200 + -- could be a bit unintuitive? + card.ability.extra.amount_mod = math.max(1, card.ability.extra.amount_mod) + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "amount", + scalar_value = "amount_mod", + scaling_message = { + message = localize("cry_jolly_ex"), + }, + }) + if to_big(card.ability.extra.amount) > to_big(card.ability.immutable.max_amount) then + card.ability.extra.amount = lenient_bignum(card.ability.immutable.max_amount) end - card_eval_status_text( - card, - "extra", - nil, - nil, - nil, - { message = { localize("cry_jolly_ex") }, colour = G.C.FILTER } - ) return nil, true end if context.selling_self and not (context.blueprint or context.retrigger_joker_check or context.retrigger_joker) - and card.ability.extra.amount > 0 + and to_big(card.ability.extra.amount) > to_big(0) then - for i = 1, math.min(200, math.floor(card.ability.extra.amount)) do + for i = 1, math.min(card.ability.immutable.max_amount, math.floor(card.ability.extra.amount)) do + local jolly_card = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_jolly") + jolly_card:add_to_deck() + G.jokers:emplace(jolly_card) + end + end + if context.forcetrigger then + -- could be a bit unintuitive? + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "amount", + scalar_value = "amount_mod", + no_message = true, + }) + if to_big(card.ability.extra.amount) > to_big(card.ability.immutable.max_amount) then + card.ability.extra.amount = lenient_bignum(card.ability.immutable.max_amount) + end + for i = 1, math.min(card.ability.immutable.max_amount, math.floor(card.ability.extra.amount)) do local jolly_card = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_jolly") jolly_card:add_to_deck() G.jokers:emplace(jolly_card) @@ -1409,45 +1817,68 @@ local longboi = { name = "cry-longboi", key = "longboi", pos = { x = 5, y = 4 }, - config = { extra = { monster = 1, bonus = 0.75 } }, + config = { + extra = { + monster = 1, + bonus = 0.75, + secret_variable_so_smods_scale_works_correctly = 1, + }, + immutable = { max_bonus = 0.75 }, -- this is technically a minimum but i didn't name the variable + }, rarity = 1, cost = 5, order = 261, pools = { ["M"] = true }, blueprint_compat = true, eternal_compat = false, + demicoloncompat = true, loc_vars = function(self, info_queue, center) return { vars = { - math.max(0.75, center.ability.extra.bonus), - center.ability.extra.monster, + math.max(center.ability.immutable.max_bonus, center.ability.extra.bonus), + number_format(center.ability.extra.monster), }, } end, atlas = "atlasthree", calculate = function(self, card, context) if context.end_of_round and not context.individual and not context.repetition then - G.GAME.monstermult = G.GAME.monstermult + math.max(0.75, card.ability.extra.bonus) - if not context.retrigger_joker then + card.ability.extra.bonus = math.max(card.ability.extra.bonus, card.ability.immutable.max_bonus) -- maybe remove this entirely + if not context.retrigger_joker and (not msg or type(msg) == "string") then return { card_eval_status_text(context.blueprint_card or card, "extra", nil, nil, nil, { - message = localize("cry_m_ex"), + message = msg or localize("cry_m_ex"), colour = G.C.FILTER, }), } end - elseif context.joker_main and card.ability.extra.monster > 1 then + elseif context.joker_main and to_big(card.ability.extra.monster) > to_big(1) then return { - message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.monster } }), - Xmult_mod = card.ability.extra.monster, + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.monster) }, + }), + Xmult_mod = lenient_bignum(card.ability.extra.monster), + } + end + if context.forcetrigger then + card.ability.extra.bonus = math.max(card.ability.extra.bonus, card.ability.immutable.max_bonus) -- maybe remove this entirely + return { + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.monster) }, + }), + Xmult_mod = lenient_bignum(card.ability.extra.monster), } end end, set_ability = function(self, card, initial, delay_sprites) - card.ability.extra.monster = G.GAME and G.GAME.monstermult or 1 - if card.ability.extra.monster >= 1234567654321 then + card.ability.extra.monster = lenient_bignum(G.GAME and G.GAME.monstermult or 1) + if to_big(card.ability.extra.monster) >= to_big(1234567654321) then card.children.center:set_sprite_pos({ x = 7, y = 5 }) - elseif card.ability.extra.monster >= 12321 then + elseif to_big(card.ability.extra.monster) >= to_big(12321) then card.children.center:set_sprite_pos({ x = 7, y = 6 }) end end, diff --git a/Cryptid/items/misc.lua b/Cryptid/items/misc.lua index 63e863e..53957f8 100644 --- a/Cryptid/items/misc.lua +++ b/Cryptid/items/misc.lua @@ -1,3 +1,450 @@ +-- Echo (Enhancement) +-- 1 in 2 to retrigger twice when played +local echo = { + cry_credits = { + idea = { + "Mystic Misclick", + }, + art = { + "Coronacht", + }, + code = { + "AlexZGreat", + }, + }, + object_type = "Enhancement", + dependencies = { + items = { + "set_cry_misc", + }, + }, + key = "echo", + atlas = "cry_misc", + order = 201, + pos = { x = 2, y = 0 }, + config = { retriggers = 2, extra = 2 }, + loc_vars = function(self, info_queue, card) + return { + vars = { + card and card.ability.retriggers or self.config.retriggers, + SMODS.get_probability_vars(card, 1, card.ability.extra, "Echo Card"), + }, + } -- note that the check for (card.ability.cry_prob or 1) is probably unnecessary due to cards being initialised with ability.cry_prob + end, + calculate = function(self, card, context) + if context.repetition and SMODS.pseudorandom_probability(card, "echo", 1, card.ability.extra, "Echo Card") then + return { + message = localize("k_again_ex"), + repetitions = card.ability.retriggers, + card = card, + } + end + end, +} +-- Eclipse (Tarot) +-- Makes a selected playing card Echo +local eclipse = { + cry_credits = { + idea = { + "Mystick Misclick", + }, + art = { + "AlexZGreat", + }, + code = { + "AlexZGreat", + }, + }, + object_type = "Consumable", + dependencies = { + items = { + "set_cry_misc", + "m_cry_echo", + }, + }, + set = "Tarot", + name = "cry-Eclipse", + key = "eclipse", + order = 202, + pos = { x = 4, y = 0 }, + config = { mod_conv = "m_cry_echo", max_highlighted = 1 }, + atlas = "atlasnotjokers", + loc_vars = function(self, info_queue, card) + info_queue[#info_queue + 1] = G.P_CENTERS.m_cry_echo + + return { vars = { card and card.ability.max_highlighted or self.config.max_highlighted } } + end, + demicoloncompat = true, +} +-- Light (Enhancement) +-- When triggered with 5 other cards, gain 0.2 Xmult +-- Increases requirement by 5 when reached +-- Gives Xmult when scored +local light = { + cry_credits = { + idea = { + "HexaCryonic", + }, + art = { + "AlexZGreat", + }, + code = { + "AlexZGreat", + }, + }, + object_type = "Enhancement", + dependencies = { + items = { + "set_cry_misc", + }, + }, + key = "light", + atlas = "cry_misc", + cry_noshadow = true, + order = 203, + pos = { x = 0, y = 3 }, + config = { extra = { a_x_mult = 0.2, current_x_mult = 1, req = 5, current = 5 } }, + loc_vars = function(self, info_queue, card) + return { + vars = { + card and card.ability.extra.a_x_mult or self.config.extra.a_x_mult, + card and card.ability.extra.current_x_mult or self.config.extra.current_x_mult, + card and card.ability.extra.current or self.config.extra.current, + card and card.ability.extra.req or self.config.extra.req, + }, + } + end, + calculate = function(self, card, context) + if context.cardarea == G.play and context.main_scoring then + if #context.scoring_hand > 1 then + card.ability.extra.current = card.ability.extra.current - (#context.scoring_hand - 1) + while card.ability.extra.current <= 0 do + card.ability.extra.req = card.ability.extra.req + 5 + card.ability.extra.current = card.ability.extra.current + card.ability.extra.req + card.ability.extra.current_x_mult = card.ability.extra.current_x_mult + card.ability.extra.a_x_mult + end + end + if card.ability.extra.current_x_mult > 1 then + return { + x_mult = card.ability.extra.current_x_mult, + } + end + end + end, +} +-- Seraph (Tarot) +-- Makes 2 selected playing cards Light +local seraph = { + cry_credits = { + idea = { + "HexaCryonic", + }, + art = { + "sachertote", + }, + code = { + "AlexZGreat", + }, + }, + object_type = "Consumable", + dependencies = { + items = { + "set_cry_misc", + "m_cry_light", + }, + }, + set = "Tarot", + name = "cry-Seraph", + key = "seraph", + order = 204, + pos = { x = 5, y = 3 }, + config = { mod_conv = "m_cry_light", max_highlighted = 2 }, + atlas = "atlasnotjokers", + loc_vars = function(self, info_queue, card) + info_queue[#info_queue + 1] = G.P_CENTERS.m_cry_light + + return { vars = { card and card.ability.max_highlighted or self.config.max_highlighted } } + end, + demicoloncompat = true, +} +-- Abstract (Enhancement) +-- Has its own rank/suit +-- 1 in 4 to destroy card if held in hand at round end or hand played +-- ^1.15 mult when scored +local abstract = { + cry_credits = { + idea = { + "lolxddj", + }, + art = { + "lolxddj", + }, + code = { + "70UNIK", + }, + }, + object_type = "Enhancement", + dependencies = { + items = { + "set_cry_misc", + }, + }, + name = "cry_abstract", + key = "abstract", + not_stoned = true, + overrides_base_rank = true, --enhancement do not generate in grim, incantation, etc... + replace_base_card = true, --So no base chips and no image + atlas = "cry_misc", + order = 205, + pos = { x = 3, y = 0 }, + shatters = true, --SMODS has a new "shatters" function + force_no_face = true, --true = always face, false = always face + --NEW! specific_suit suit. Like abstracted! + specific_suit = "cry_abstract", + specific_rank = "cry_abstract", + config = { extra = { Emult = 1.15, odds_after_play = 2, odds_after_round = 4, marked = false, survive = false } }, + --#1# emult, #2# in #3# chance card is destroyed after play, #4# in #5$ chance card is destroyed at end of round (even discarded or in deck) + loc_vars = function(self, info_queue, card) + local aaa, bbb = SMODS.get_probability_vars(card, 1, card.ability.extra.odds_after_play, "Abstract Card") + local ccc, ddd = SMODS.get_probability_vars(card, 1, card.ability.extra.odds_after_round, "Abstract Card") + return { + vars = { + card.ability.extra.Emult, + aaa, + bbb, + ccc, + ddd, + }, + } + end, + calculate = function(self, card, context) + --During scoring + if + context.cardarea == G.hand + and context.before + and not card.ability.extra.marked + and not SMODS.is_eternal(card) + and not card.ability.extra.survive --this presvents repitition of shatter chance by shutting it out once it confirms to "survive" + and SMODS.pseudorandom_probability( + card, + "cry_abstract_destroy", + 1, + card.ability.extra.odds_after_play, + "Abstract Card" + ) + then -- the 'card.area' part makes sure the card has a chance to survive if in the play area + card.ability.extra.marked = true + elseif context.cardarea == G.play and not card.ability.extra.marked then + card.ability.extra.survive = true + end + if context.cardarea == G.play and context.main_scoring then + return { + message = localize({ + type = "variable", + key = "a_powmult", + vars = { + number_format(card.ability.extra.Emult), + }, + }), + Emult_mod = card.ability.extra.Emult, + colour = G.C.DARK_EDITION, + } + end + + if + context.final_scoring_step + and context.cardarea == G.hand + and card.ability.extra.marked + and not context.repetition + and not SMODS.is_eternal(card) + and not (card.will_shatter or card.destroyed or card.shattered) + then + G.E_MANAGER:add_event(Event({ + trigger = "immediate", + func = function() + card:juice_up(0.9, 0.9) + card:shatter() + return true + end, + })) + end + card.ability.extra.survive = false + end, +} +-- Instability (Tarot) +-- Makes a selected playing card Abstract +local instability = { + cry_credits = { + idea = { + "lolxddj", + }, + art = { + "lolxddj", + }, + code = { + "70UNIK", + }, + }, + object_type = "Consumable", + dependencies = { + items = { + "set_cry_misc", + "m_cry_abstract", + }, + }, + set = "Tarot", + name = "cry-Instability", + key = "instability", + order = 206, + pos = { x = 5, y = 5 }, + config = { mod_conv = "m_cry_abstract", max_highlighted = 1 }, + atlas = "atlasnotjokers", + loc_vars = function(self, info_queue, card) + info_queue[#info_queue + 1] = G.P_CENTERS.m_cry_abstract + + return { vars = { card and card.ability.max_highlighted or self.config.max_highlighted } } + end, + demicoloncompat = true, +} + +-- Blessing +-- Creates a random Consumeable +local blessing = { + cry_credits = { + idea = { + "5381", + }, + art = { + "RattlingSnow353", + }, + code = { + "Jevonn", + }, + }, + object_type = "Consumable", + dependencies = { + items = { + "set_cry_misc", + }, + }, + set = "Tarot", + name = "cry-theblessing", + key = "theblessing", + order = 500, + pos = { x = 2, y = 3 }, + cost = 3, + atlas = "atlasnotjokers", + can_use = function(self, card) + return #G.consumeables.cards < G.consumeables.config.card_limit or card.area == G.consumeables + end, + can_bulk_use = true, + use = function(self, card, area, copier) + local used_consumable = copier or card + local forceuse = G.cry_force_use + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.4, + func = function() + if G.consumeables.config.card_limit > #G.consumeables.cards or forceuse then + play_sound("timpani") + local forced_key = Cryptid.random_consumable("blessing", nil, "c_cry_blessing") + local _card = create_card( + "Consumeables", + G.consumeables, + nil, + nil, + nil, + nil, + forced_key.config.center_key, + "blessing" + ) + _card:add_to_deck() + G.consumeables:emplace(_card) + used_consumable:juice_up(0.3, 0.5) + end + return true + end, + })) + delay(0.6) + end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, +} + +-- insert typhoon here (why is it in spectral.lua) +local azure_seal = { + cry_credits = { + idea = { + "stupid", + }, + art = { + "stupid", + }, + code = { + "stupid", + }, + }, + object_type = "Seal", + dependencies = { + items = { + "set_cry_misc", + }, + }, + name = "cry-Azure-Seal", + key = "azure", + badge_colour = HEX("1d4fd7"), + config = { planets_amount = 3 }, + loc_vars = function(self, info_queue) + return { vars = { self.config.planets_amount } } + end, + atlas = "cry_misc", + order = 502, + pos = { x = 0, y = 2 }, + -- This is still quite jank + calculate = function(self, card, context) + if context.destroying_card and context.cardarea == G.play and context.destroy_card == card then + card.will_shatter = true + G.E_MANAGER:add_event(Event({ + trigger = "before", + delay = 0.0, + func = function() + local card_type = "Planet" + local _planet = nil + if G.GAME.last_hand_played then + for k, v in pairs(G.P_CENTER_POOLS.Planet) do + if v.config.hand_type == G.GAME.last_hand_played then + _planet = v.key + break + end + end + if + ( + G.GAME.last_hand_played == "cry_Declare0" + or G.GAME.last_hand_played == "cry_Declare1" + or G.GAME.last_hand_played == "cry_Declare2" + ) and Cryptid.enabled("c_cry_voxel") == true + then + _planet = "c_cry_voxel" + end + end + + for i = 1, self.config.planets_amount do + local card = create_card(card_type, G.consumeables, nil, nil, nil, nil, _planet, "cry_azure") + + card:set_edition({ negative = true }, true) + card:add_to_deck() + G.consumeables:emplace(card) + end + return true + end, + })) + return { remove = true } + end + end, +} + -- Packs local meme_digital_hallucinations_compat = { colour = G.C.CRY_ASCENDANT, @@ -9,6 +456,18 @@ local meme_digital_hallucinations_compat = { G.jokers:emplace(ccard) --Note: Will break if any non-Joker gets added to the meme pool end, } +-- Anti synergy with digital hallucinations, it will create ANOTHER cursed Joker when opening the pack +local cursed_digital_hallucinations_compat = { + colour = HEX("474931"), + loc_key = "k_plus_joker", + create = function() + local ccard = create_card("Joker", G.jokers, nil, "cry_cursed", nil, nil, nil, "diha") + ccard:set_edition({ negative = true }, true) + ccard:add_to_deck() + G.jokers:emplace(ccard) --Note: Will break if any non-Joker gets added to the meme pool + end, +} +-- Meme Pack 1 (2/5 Meme Jokers) local meme1 = { cry_credits = { idea = { @@ -24,14 +483,14 @@ local meme1 = { object_type = "Booster", dependencies = { items = { - "set_cry_misc", + "set_cry_meme", }, }, key = "meme_1", kind = "meme", atlas = "pack", pos = { x = 0, y = 1 }, - order = 5, + order = 801, config = { extra = 5, choose = 2 }, cost = 14, weight = 0.18 / 3, --0.18 base ÷ 3 since there are 3 identical packs @@ -66,6 +525,7 @@ local meme1 = { group_key = "k_cry_meme_pack", cry_digital_hallucinations = meme_digital_hallucinations_compat, } +-- Meme Pack 2 (2/5 Meme Jokers) local meme2 = { cry_credits = { idea = { @@ -81,14 +541,14 @@ local meme2 = { object_type = "Booster", dependencies = { items = { - "set_cry_misc", + "set_cry_meme", }, }, key = "meme_two", kind = "meme", atlas = "pack", pos = { x = 1, y = 1 }, - order = 6, + order = 802, config = { extra = 5, choose = 2 }, cost = 14, weight = 0.18 / 3, --0.18 base ÷ 3 since there are 3 identical packs @@ -123,6 +583,7 @@ local meme2 = { group_key = "k_cry_meme_pack", cry_digital_hallucinations = meme_digital_hallucinations_compat, } +-- Meme Pack 3 (2/5 Meme Jokers) local meme3 = { cry_credits = { idea = { @@ -138,14 +599,14 @@ local meme3 = { object_type = "Booster", dependencies = { items = { - "set_cry_misc", + "set_cry_meme", }, }, key = "meme_three", kind = "meme", atlas = "pack", pos = { x = 2, y = 1 }, - order = 7, + order = 803, config = { extra = 5, choose = 2 }, cost = 14, weight = 0.18 / 3, --0.18 base ÷ 3 since there are 3 identical packs @@ -180,6 +641,81 @@ local meme3 = { group_key = "k_cry_meme_pack", cry_digital_hallucinations = meme_digital_hallucinations_compat, } +-- 804 in case of meme pack 4 +-- 805-808 for program packs +-- Baneful Buffoon Pack 1 (1/4 Cursed jokers) +local baneful1 = { + cry_credits = { + idea = { + "HexaCryonic", + }, + art = { + "Nova", + }, + code = { + "70UNIK", + }, + }, + object_type = "Booster", + dependencies = { + items = { + "set_cry_cursed", + }, + }, + key = "baneful_1", + kind = "baneful", + atlas = "pack", + order = 809, + pos = { x = 0, y = 2 }, + cry_baneful_punishment = true, + no_music = true, --prevent override of music, such as in boss blinds + no_doe = true, + unskippable = function(self) + --Only be unskippable if no VALID jokers are owned (if rightmost is eternal/cursed, the next) + if G.jokers and (#G.jokers.cards == 0 or not G.jokers.cards) then + return true + end + --For loop that iterates from right to left, breaking and returning false if finding the rightmost valid noneternal or cursed Joker + if G.jokers and G.jokers.cards then + for i = #G.jokers.cards, 1, -1 do + if + not (SMODS.is_eternal(G.jokers.cards[i]) or G.jokers.cards[i].config.center.rarity == "cry_cursed") + then + return false + end + end + end + return true + end, + config = { extra = 4, choose = 1 }, + cost = 1, + immutable = true, + weight = 0, --never spawn naturally + create_card = function(self, card) + return create_card("Joker", G.jokers, nil, "cry_cursed", nil, nil, nil, "baneful_pack") + end, + ease_background_colour = function(self) + ease_colour(G.C.DYN_UI.MAIN, HEX("474931")) + ease_background_colour({ new_colour = HEX("474931"), special_colour = G.C.BLACK, contrast = 2 }) + end, + loc_vars = function(self, info_queue, card) + return { + vars = { + card and card.ability.choose or self.config.choose, + card and card.ability.extra or self.config.extra, + }, + } + end, + --never spawn as well in pool + in_pool = function() + return false + end, + group_key = "k_cry_baneful_pack", + cry_digital_hallucinations = cursed_digital_hallucinations_compat, +} +-- 810-812 reserved for more Baneful packs if they come + +-- Editions start at 900, haven't decided on order yet if not AurinkoAddons then AurinkoAddons = {} @@ -225,8 +761,8 @@ local mosaic = { get_weight = function(self) return G.GAME.edition_rate * self.weight end, - loc_vars = function(self, info_queue) - return { vars = { self.config.x_chips } } + loc_vars = function(self, info_queue, card) + return { vars = { card and card.edition and card.edition.x_chips or self.config.x_chips } } end, calculate = function(self, card, context) if @@ -239,7 +775,7 @@ local mosaic = { and context.cardarea == G.play ) then - return { x_chips = self.config.x_chips } -- updated value + return { x_chips = card and card.edition and card.edition.x_chips or self.config.x_chips } -- updated value end if context.joker_main then card.config.trigger = true -- context.edition triggers twice, this makes it only trigger once (only for jonklers) @@ -291,12 +827,9 @@ local oversat = { -- Note: Duping playing cards resets the base chips for some reason on_apply = function(card) if not card.ability.cry_oversat then - Cryptid.with_deck_effects(card, function(card) - Cryptid.misprintize(card, { - min = 2, - max = 2, - }, nil, true) - end) + Cryptid.manipulate(card, { + value = 2, + }, nil, true) if card.config.center.apply_oversat then card.config.center:apply_oversat(card, function(val) return Cryptid.misprintize_val(val, { @@ -309,10 +842,8 @@ local oversat = { card.ability.cry_oversat = true end, on_remove = function(card) - Cryptid.with_deck_effects(card, function(card) - Cryptid.misprintize(card, { min = 1, max = 1 }, true) - Cryptid.misprintize(card) -- Correct me if i'm wrong but this is for misprint deck. or atleast it is after this patch - end) + Cryptid.manipulate(card, { value = 1 / 2 }) + Cryptid.manipulate(card) -- Correct me if i'm wrong but this is for misprint deck. or atleast it is after this patch card.ability.cry_oversat = nil end, init = function(self) @@ -377,10 +908,20 @@ local glitched_shader = { key = "glitched", path = "glitched.fs", } +local glitched_shader2 = { + object_type = "Shader", + key = "ultrafoil", + path = "ultrafoil.fs", +} +local glitched_shaderb = { + object_type = "Shader", + key = "glitched_b", + path = "glitched_b.fs", +} local glitched = { cry_credits = { art = { - "Samario", + "Cassknows", }, code = { "Math", @@ -395,7 +936,8 @@ local glitched = { key = "glitched", order = 1, weight = 15, - shader = "glitched", + --shader = G.SETTINGS.reduced_motion and "ultrafoil" or "glitched", + shader = "glitched_b", in_shop = true, extra_cost = 0, sound = { @@ -409,17 +951,17 @@ local glitched = { -- Note: Duping playing cards resets the base chips for some reason on_apply = function(card) if not card.ability.cry_glitched then - Cryptid.with_deck_effects(card, function(card) - Cryptid.misprintize(card, { - min = 0.1, - max = 10, - }, nil, true) - end) + Cryptid.manipulate(card, { + min = 0.1, + max = 10, + }) + if card.config.center.apply_glitched then card.config.center:apply_glitched(card, function(val) - return Cryptid.misprintize_val(val, { + return Cryptid.manipulate_value(val, { min = 0.1 * (G.GAME.modifiers.cry_misprint_min or 1), max = 10 * (G.GAME.modifiers.cry_misprint_max or 1), + type = "X", }, Cryptid.is_card_big(card)) end) end @@ -427,10 +969,8 @@ local glitched = { card.ability.cry_glitched = true end, on_remove = function(card) - Cryptid.with_deck_effects(card, function(card) - Cryptid.misprintize(card, { min = 1, max = 1 }, true) - Cryptid.misprintize(card) -- Correct me if i'm wrong but this is for misprint deck. or atleast it is after this patch - end) + Cryptid.manipulate(card, { min = 1, max = 1, dont_stack = true }) + Cryptid.manipulate(card) -- Correct me if i'm wrong but this is for misprint deck. or atleast it is after this patch card.ability.cry_glitched = nil end, init = function(self) @@ -622,6 +1162,10 @@ local astral = { code = { "Math", }, + art = { + "lord.ruby", + "Oiiman", + }, }, object_type = "Edition", dependencies = { @@ -644,8 +1188,8 @@ local astral = { return G.GAME.edition_rate * self.weight end, config = { e_mult = 1.1, trigger = nil }, - loc_vars = function(self, info_queue) - return { vars = { self.config.e_mult } } + loc_vars = function(self, info_queue, card) + return { vars = { card and card.edition and card.edition.e_mult or self.config.e_mult } } end, calculate = function(self, card, context) if @@ -658,7 +1202,7 @@ local astral = { and context.cardarea == G.play ) then - return { e_mult = self.config.e_mult } -- updated value + return { e_mult = card and card.edition and card.edition.e_mult or self.config.e_mult } -- updated value end if context.joker_main then card.config.trigger = true -- context.edition triggers twice, this makes it only trigger once (only for jonklers) @@ -709,10 +1253,10 @@ local blurred = { end, config = { retrigger_chance = 2, retriggers = 1, extra_retriggers = 1 }, loc_vars = function(self, info_queue, center) - local chance = center and center.edition and center.edition.retrigger_chance or self.config.retrigger_chance + local aaa, bbb = SMODS.get_probability_vars(self, 1, self.config.retrigger_chance, "Blurred Edition") local retriggers = center and center.edition and center.edition.retriggers or self.config.retriggers - return { vars = { G.GAME.probabilities.normal, chance, retriggers } } + return { vars = { aaa, bbb, retriggers } } end, --Note: This doesn't always play the animations properly for Jokers calculate = function(self, card, context) @@ -723,11 +1267,15 @@ local blurred = { or (context.retrigger_joker_check and not context.retrigger_joker) ) then - local extra_retrigger = pseudorandom("cry_blurred") - <= G.GAME.probabilities.normal / self.config.retrigger_chance return { message = localize("cry_again_q"), - repetitions = self.config.retriggers + (extra_retrigger and self.config.extra_retriggers or 0), + repetitions = self.config.retriggers + (SMODS.pseudorandom_probability( + self, + "cry_blurred", + 1, + self.config.retrigger_chance, + "Blurred Edition" + ) and self.config.extra_retriggers or 0), card = card, } end @@ -796,9 +1344,13 @@ local noisy = { and context.cardarea == G.play ) then + local min_mult = card and card.edition and card.edition.min_mult or self.config.min_mult + local max_mult = card and card.edition and card.edition.max_mult or self.config.max_mult + local min_chips = card and card.edition and card.edition.min_chips or self.config.min_chips + local max_chips = card and card.edition and card.edition.max_chips or self.config.max_chips return { - mult = pseudorandom("cry_noisy_mult", self.config.min_mult, self.config.max_mult), - chips = pseudorandom("cry_noisy_chips", self.config.min_chips, self.config.max_chips), + mult = pseudorandom("cry_noisy_mult", min_mult, max_mult), + chips = pseudorandom("cry_noisy_chips", min_chips, max_chips), } -- updated value end if context.joker_main then @@ -822,7 +1374,7 @@ local noisy = { for i = self.config.min_chips, self.config.max_chips do r_chips[#r_chips + 1] = tostring(i) end - local loc_chips = " Chips " + local loc_chips = " " .. (localize("k_chips")) .. " " mult_ui = { { n = G.UIT.T, config = { text = " +", colour = G.C.MULT, scale = 0.32 } }, { @@ -1029,8 +1581,8 @@ local noisy = { end AurinkoAddons.cry_noisy = function(card, hand, instant, amount) - local modc = pseudorandom("cry_noisy_chips_aurinko", noisy_stats.min.chips, noisy_stats.max.chips) - local modm = pseudorandom("cry_noisy_mult_aurinko", noisy_stats.min.mult, noisy_stats.max.mult) + local modc = pseudorandom("cry_noisy_chips_aurinko", noisy_stats.min.chips, noisy_stats.max.chips) * amount + local modm = pseudorandom("cry_noisy_mult_aurinko", noisy_stats.min.mult, noisy_stats.max.mult) * amount G.GAME.hands[hand].chips = math.max(G.GAME.hands[hand].chips + modc, 1) G.GAME.hands[hand].mult = math.max(G.GAME.hands[hand].mult + modm, 1) if not instant then @@ -1148,8 +1700,8 @@ local jollyedition = { shader = "m", disable_base_shader = true, disable_shadow = true, - loc_vars = function(self, info_queue) - return { vars = { self.config.mult } } + loc_vars = function(self, info_queue, card) + return { vars = { card and card.edition and card.edition.mult or self.config.mult } } end, calculate = function(self, card, context) if @@ -1162,7 +1714,7 @@ local jollyedition = { and context.cardarea == G.play ) then - return { mult = self.config.mult } -- updated value + return { mult = card and card.edition and card.edition.mult or self.config.mult } -- updated value end if context.joker_main then card.config.trigger = true -- context.edition triggers twice, this makes it only trigger once (only for jonklers) @@ -1285,18 +1837,18 @@ local glass_edition = { weight = 7, extra_cost = 2, config = { x_mult = 3, shatter_chance = 8, trigger = nil }, - loc_vars = function(self, info_queue) + loc_vars = function(self, info_queue, card) return { vars = { - (G.GAME.probabilities.normal or 1) * (self.config.shatter_chance - 1), - self.config.shatter_chance, - self.config.x_mult, + ((card and card.edition and card.edition.shatter_chance or self.config.shatter_chance) - 1), + (card and card.edition and card.edition.shatter_chance or self.config.shatter_chance), + card and card.edition and card.edition.x_mult or self.config.x_mult, }, } end, calculate = function(self, card, context) if context.edition and context.cardarea == G.jokers and card.config.trigger then - return { x_mult = self.config.x_mult } + return { x_mult = card and card.edition and card.edition.x_mult or self.config.x_mult } end if @@ -1305,7 +1857,7 @@ local glass_edition = { and context.other_card == card --animation-wise this looks weird sometimes then if - not card.ability.eternal + not SMODS.is_eternal(card) and not ( pseudorandom(pseudoseed("cry_fragile")) > ((self.config.shatter_chance - 1) / self.config.shatter_chance) @@ -1335,7 +1887,7 @@ local glass_edition = { end if context.main_scoring and context.cardarea == G.play then if - not card.ability.eternal + not SMODS.is_eternal(card) and ( pseudorandom(pseudoseed("cry_fragile")) > ((self.config.shatter_chance - 1) / self.config.shatter_chance) @@ -1414,8 +1966,8 @@ local gold_edition = { extra_cost = 4, in_shop = true, config = { dollars = 2, active = true }, - loc_vars = function(self, info_queue) - return { vars = { self.config.dollars } } + loc_vars = function(self, info_queue, card) + return { vars = { card and card.edition and card.edition.dollars or self.config.dollars } } end, sound = { sound = "cry_e_golden", @@ -1441,7 +1993,7 @@ local gold_edition = { and context.consumeable == card ) then - return { p_dollars = self.config.dollars } -- updated value + return { p_dollars = card and card.edition and card.edition.dollars or self.config.dollars } -- updated value end end, } @@ -1453,15 +2005,15 @@ local double_sided = { "set_cry_misc", }, }, - gameset_config = { - modest = { disabled = true }, - mainline = { disabled = true }, - madness = { disabled = true }, - exp = {}, - }, + -- gameset_config = { + -- modest = { disabled = true }, + -- mainline = { disabled = true }, + -- madness = { disabled = true }, + -- exp = {}, + -- }, extra_gamesets = { "exp" }, key = "double_sided", - shader = false, + shader = G.SETTINGS.reduced_motion and "ultrafoil" or "glitched", order = 32, weight = 10, extra_cost = 0, @@ -1473,168 +2025,325 @@ local double_sided = { vol = 0.3, }, cry_credits = { + art = { + "Samario", + -- Reduced Motion Shader + "Selicre", + }, code = { "Math", + "lord-ruby", }, jolly = { "Jolly Open Winner", "Axolotolus", }, }, + on_apply = function(card) + if not card.ability.immutable then + card.ability.immutable = {} + end + if not card.ability.immutable.other_side then + card.ability.immutable.other_side = "c_base" + end + end, get_weight = function(self) return G.GAME.edition_rate * self.weight * (G.GAME.used_vouchers.v_cry_double_vision and 4 or 1) end, init = function(self) - -- Double-Sided - create FLIP button - -- kinda based on Fusion Jokers - local card_focus_ui = G.UIDEF.card_focus_ui - function G.FUNCS.can_flip_card(e) - e.config.colour = G.C.DARK_EDITION - e.config.button = "flip" - end - function G.FUNCS.can_flip_merge_card(e) - local area = e.config.ref_table.area - local mergable = 0 - for i = 1, #area.highlighted do - if area.highlighted[i].edition and area.highlighted[i].edition.cry_double_sided then - mergable = mergable + 1 - mergedcard = area.highlighted[i] + local highlight_ref = Card.highlight + function Card:highlight(is_highlighted) + if self.edition and self.edition.key == "e_cry_double_sided" then + if is_highlighted and self.area.config.type ~= "shop" and self.area ~= G.pack_cards then + self.children.flip = UIBox({ + definition = { + n = G.UIT.ROOT, + config = { + minh = 0.3, + maxh = 0.5, + minw = 0.4, + maxw = 4, + r = 0.08, + padding = 0.1, + align = "cm", + colour = G.C.PURPLE, + shadow = true, + button = "flip_ds", + func = "can_flip_ds", + ref_table = self, + }, + nodes = { + { + n = G.UIT.T, + config = { + text = localize("b_flip"), --localize + scale = 0.3, + colour = G.C.UI.TEXT_LIGHT, + }, + }, + }, + }, + config = { + align = "bmi", + offset = { + x = 0, + y = 0.5, + }, + bond = "Strong", + parent = self, + }, + }) + self.children.merge_ds = UIBox({ + definition = { + n = G.UIT.ROOT, + config = { + minh = 0.3, + maxh = 0.5, + minw = 0.4, + maxw = 4, + r = 0.08, + padding = 0.1, + align = "cm", + colour = G.C.PURPLE, + shadow = true, + button = "merge_ds", + func = "can_merge_ds", + ref_table = self, + }, + nodes = { + { + n = G.UIT.T, + config = { + text = localize("b_merge"), + scale = 0.3, + colour = G.C.UI.TEXT_LIGHT, + }, + }, + }, + }, + config = { + align = "bmi", + offset = { + x = 0, + y = 1, + }, + bond = "Strong", + parent = self, + }, + }) end - end - if mergable == 1 then - e.config.colour = G.C.DARK_EDITION - e.config.button = "flip_merge" - else - e.config.colour = G.C.UI.BACKGROUND_INACTIVE - e.config.button = nil - end - end - function G.FUNCS.flip(e) - e.config.ref_table:flip() - e.config.ref_table.area:remove_from_highlighted(e.config.ref_table) - end - function G.FUNCS.flip_merge(e) - e.config.ref_table:flip() - e.config.ref_table.area:remove_from_highlighted(e.config.ref_table) - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 1, - func = function() - local area = e.config.ref_table.area - area:remove_card(e.config.ref_table) - mergedcard:init_dbl_side() - Cryptid.copy_dbl_card(e.config.ref_table, mergedcard.dbl_side) - e.config.ref_table:remove() - e.config.ref_table = nil - return true - end, - })) - end - function Cryptid.copy_dbl_card(C, c, deck_effects) - if not deck_effects then - Cdeck = C.added_to_deck - cdeck = c.added_to_deck - C.added_to_deck = true - c.added_to_deck = false - end - copy_card(C, c) - c.config.center_key = C.config.center_key - end - function Card:init_dbl_side() - if Card.no(self, "dbl") then - self:set_edition(nil, true) - end - if not self.dbl_side then - self.dbl_side = Cryptid.deep_copy(self) - self.dbl_side:set_ability(G.P_CENTERS.j_joker) - -- self.dbl_side:set_base(G.P_CARDS.empty) -- RIGHT HERE THIS RIGHT HERE THATS YOUR DAM CULPRIT - if self.area == G.hand then - self.dbl_side = Cryptid.deep_copy(self) - self.dbl_side:set_ability(G.P_CENTERS.c_base) - end - self.dbl_side.added_to_deck = false - return true - end - end - function Card:dbl_side_flip() - local init_dbl_side = self:init_dbl_side() - local tmp_side = Cryptid.deep_copy(self.dbl_side) - self.children.center.scale = { x = self.children.center.atlas.px, y = self.children.center.atlas.py } - self.T.w, self.T.h = G.CARD_W, G.CARD_H - local active_side = self - if next(find_joker("cry-Flip Side")) and self.dbl_side then - active_side = self.dbl_side - end - if not init_dbl_side then - active_side:remove_from_deck(true) - end - Cryptid.copy_dbl_card(self, self.dbl_side, false) - Cryptid.copy_dbl_card(tmp_side, self, false) - active_side:add_to_deck(true) - self.children.center:set_sprite_pos(G.P_CENTERS[self.config.center.key].pos) - if self.base then - --Note: this causes a one-frame stutter - for k, v in pairs(G.P_CARDS) do - if self.base.suit == v.suit and self.base.value == v.value then - self.config.card_key = k + if not is_highlighted or self.area.config.type == "shop" or self.area == G.pack_cards then + if self.children.flip then + self.children.flip:remove() + self.children.flip = nil + end + + if self.children.merge_ds then + self.children.merge_ds:remove() + self.children.merge_ds = nil end end - self:set_sprites(nil, self.config.card) - if self.children and self.children.front and self.config.card_key then - self.children.front:set_sprite_pos(G.P_CARDS[self.config.card_key].pos) - end end - if (not self.base or not self.base.name) and self.children.front then - self.children.front:remove() - self.children.front = nil - end - self:set_edition({ cry_double_sided = true }, true, true) + return highlight_ref(self, is_highlighted) end - local cgcb = Card.get_chip_bonus - function Card:get_chip_bonus() - if self.ability.set == "Joker" then - return 0 + function Card:flip_side() + local card = self + if not card.ability.immutable then + card.ability.immutable = {} end - return cgcb(self) - end - local csave = Card.save - function Card:save() - local cardTable = csave(self) - if self.dbl_side then - cardTable.dbl_side = csave(self.dbl_side) - end - return cardTable - end - local cload = Card.load - function Card:load(cardTable, other_card) - cload(self, cardTable, other_card) - if self.ability.set == "Default" then - self:set_ability(G.P_CENTERS.c_base, true) - end - if not self.base.name then - self:set_base(G.P_CARDS.empty, true) - if self.children.front then - self.children.front:remove() - self.children.front = nil - end - end - if cardTable.dbl_side then - self.dbl_side = Cryptid.deep_copy(self) - cload(self.dbl_side, cardTable.dbl_side) - if self.dbl_side.ability.set == "Default" and self.ability.set ~= "Default" then - self.dbl_side:set_ability(G.P_CENTERS.c_base, true) - end - if not self.dbl_side.base.name then - self.dbl_side:set_base(G.P_CARDS.empty, true) + if card.ability.immutable.other_side then + if type(card.ability.immutable.other_side) == "string" then + if next(find_joker("cry-Flip Side")) then + if card:get_other_side_dummy() then + local dummy = card:get_other_side_dummy() + dummy.added_to_deck = true + Card.remove_from_deck(dummy, true) + end + else + card:remove_from_deck(true) + end + local curr_abil = copy_table(card.ability) + local key = card.config.center.key + local base = copy_table(card.base) + local seal = card.seal + if card.ability.immutable.other_side.base then + card.base = card.ability.immutable.other_side.base + else + card.base = { + nominal = 0, + suit_nominal = 0, + face_nominal = 0, + times_played = 0, + suit_nominal_original = 0, + } + end + if card.base.nominal ~= 0 then + SMODS.change_base(card, card.base.suit, card.base.value) + else + if card.children.front then + card.children.front:remove() + card.children.front = nil + end + end + card.seal = G.P_SEALS[card.ability.immutable.other_side.seal] + and card.ability.immutable.other_side.seal + or nil + card:set_ability(G.P_CENTERS[card.ability.immutable.other_side], true, true) + if not card.ability.immutable then + card.ability.immutable = {} + end + card.ability.immutable.other_side = curr_abil + card.ability.immutable.other_side.key = key + card.ability.immutable.other_side.seal = G.P_SEALS[seal] and seal or nil + if next(find_joker("cry-Flip Side")) then + if card:get_other_side_dummy() then + Card.add_to_deck(card:get_other_side_dummy(), true) + end + else + card:add_to_deck(true) + end + card.ability.immutable.other_side.base = base + else + if next(find_joker("cry-Flip Side")) then + local dummy = card:get_other_side_dummy() + dummy.added_to_deck = true + Card.remove_from_deck(dummy, true) + else + card:remove_from_deck(true) + end + local curr_abil = copy_table(card.ability) + local key = card.config.center.key + local seal = card.seal + local base = copy_table(card.base) + if card.ability.immutable.other_side.base then + card.base = card.ability.immutable.other_side.base + else + card.base = { + nominal = 0, + suit_nominal = 0, + face_nominal = 0, + times_played = 0, + suit_nominal_original = 0, + } + end + if card.base.nominal ~= 0 then + SMODS.change_base(card, card.base.suit, card.base.value) + else + if card.children.front then + card.children.front:remove() + card.children.front = nil + end + end + card.seal = G.P_SEALS[card.ability.immutable.other_side.seal] + and card.ability.immutable.other_side.seal + or nil + card:set_ability(card.ability.immutable.other_side.key, true, true) + if card.ability.immutable.other_side then + card.ability = copy_table(card.ability.immutable.other_side) + end + if not card.ability.immutable then + card.ability.immutable = {} + end + card.ability.immutable.other_side = curr_abil + card.ability.immutable.other_side.key = key + card.ability.immutable.other_side.seal = G.P_SEALS[seal] and seal or nil + if next(find_joker("cry-Flip Side")) then + Card.add_to_deck(card:get_other_side_dummy(), true) + else + card:add_to_deck(true) + end + card.ability.immutable.other_side.base = base end end end - local rma = remove_all - function remove_all(t) - if t then - rma(t) + function Card:get_other_side_dummy(added_to_deck) + if self.ability.immutable and type(self.ability.immutable.other_side) == "table" then + local tbl = { + ability = self.ability.immutable.other_side, + config = { + center = G.P_CENTERS[self.ability.immutable.other_side.key], + }, + juice_up = function(_, ...) + return self:juice_up(...) + end, + start_dissolve = function(_, ...) + return self:start_dissolve(...) + end, + remove = function(_, ...) + return self:remove(...) + end, + flip = function(_, ...) + return self:flip(...) + end, + original_card = self, + area = self.area, + added_to_deck = added_to_deck, + } + for i, v in pairs(self) do + if type(v) == "function" and i ~= "flip_side" then + tbl[i] = function(_, ...) + return v(self, ...) + end + end + end + return tbl end end + local set_editionref = Card.set_edition + function Card:set_edition(...) + set_editionref(self, ...) + if self.edition and self.edition.key ~= "e_cry_double_sided" then + if self.children.flip then + self.children.flip:remove() + self.children.flip = nil + end + if self.children.merge then + self.children.merge:remove() + self.children.merge = nil + end + self.merged = nil + if self.ability.immutable then + self.ability.immutable.other_side = nil + end + end + end + + local no_rankref = SMODS.has_no_rank + function SMODS.has_no_rank(card) + if not card.base.value then + return true + end + return no_rankref(card) + end + + local no_suitref = SMODS.has_no_suit + function SMODS.has_no_suit(card) + if not card.base.suit then + return true + end + return no_suitref(card) + end + + -- local calculate_joker = Card.calculate_joker + -- function Card:calculate_joker(context) + -- if next(SMODS.find_card("cry-Flip Side")) and type(self.ability.immutable.other_side) ~= "string" and self.ability.immutable.other_side then + -- context.dbl_side = true + -- local ret = self:get_other_side_dummy() + -- return calculate_joker(ret, context) + -- end + -- return calculate_joker(self, context) + -- end + + local card_st_ref = card_eval_status_text + function card_eval_status_text(card, ...) + return card_st_ref(card.original_card or card, ...) + end + + local remove_cardref = CardArea.remove_card + function CardArea:remove_card(card, ...) + return remove_cardref(self, card and card.original_card or card, ...) + end + --prevent chaos the clown's ability from being applied on debuff local catd = Card.add_to_deck local crfd = Card.remove_from_deck @@ -1650,24 +2359,17 @@ local double_sided = { end return crfd(self, debuff) end - local cae = CardArea.emplace - function CardArea:emplace(card, m1, m2) - if not (card.will_shatter or card.destroyed or card.shattered) then - cae(self, card, m1, m2) - else - if card.area then - card.area:remove_card(card) - end - card:remove() - card = nil - end - end local sjw = set_joker_win function set_joker_win() sjw() for k, v in pairs(G.jokers.cards) do - if v.dbl_side and v.dbl_side.config.center_key and v.dbl_side.ability.set == "Joker" then - G.PROFILES[G.SETTINGS.profile].joker_usage[v.dbl_side.config.center_key] = G.PROFILES[G.SETTINGS.profile].joker_usage[v.dbl_side.config.center_key] + if + v.ability.immutable + and v.ability.immutable.other_side + and type(v.ability.immutable.other_side) == "table" + and G.P_CENTERS[v.ability.immutable.other_side.key] == "Joker" + then + G.PROFILES[G.SETTINGS.profile].joker_usage[v.ability.immutable.other_side.key] = G.PROFILES[G.SETTINGS.profile].joker_usage[v.ability.immutable.other_side.key] or { count = 1, order = v.dbl_side.config.center.order, @@ -1676,11 +2378,11 @@ local double_sided = { wins_by_key = {}, losses_by_key = {}, } - if G.PROFILES[G.SETTINGS.profile].joker_usage[v.dbl_side.config.center_key] then - G.PROFILES[G.SETTINGS.profile].joker_usage[v.dbl_side.config.center_key].wins = G.PROFILES[G.SETTINGS.profile].joker_usage[v.dbl_side.config.center_key].wins + if G.PROFILES[G.SETTINGS.profile].joker_usage[v.ability.immutable.other_side.key] then + G.PROFILES[G.SETTINGS.profile].joker_usage[v.ability.immutable.other_side.key].wins = G.PROFILES[G.SETTINGS.profile].joker_usage[v.ability.immutable.other_side.key].wins or {} - G.PROFILES[G.SETTINGS.profile].joker_usage[v.dbl_side.config.center_key].wins[G.GAME.stake] = ( - G.PROFILES[G.SETTINGS.profile].joker_usage[v.dbl_side.config.center_key].wins[G.GAME.stake] + G.PROFILES[G.SETTINGS.profile].joker_usage[v.ability.immutable.other_side.key].wins[G.GAME.stake] = ( + G.PROFILES[G.SETTINGS.profile].joker_usage[v.ability.immutable.other_side.key].wins[G.GAME.stake] or 0 ) + 1 end @@ -1690,433 +2392,83 @@ local double_sided = { end end, } -local meld = { - object_type = "Consumable", - dependencies = { - items = { - "set_cry_misc", - "e_cry_double_sided", - }, - }, - set = "Tarot", - name = "cry-Meld", - key = "meld", - order = 3, - pos = { x = 4, y = 4 }, - config = { extra = 4 }, - cost = 4, - atlas = "atlasnotjokers", - can_use = function(self, card) - if - #G.jokers.highlighted - + #G.hand.highlighted - - (G.hand.highlighted[1] and G.hand.highlighted[1] == self and 1 or 0) - == 1 - then - if - #G.jokers.highlighted == 1 - and (Card.no(G.jokers.highlighted[1], "dbl") or G.jokers.highlighted[1].edition) - then - return false - end - if #G.hand.highlighted == 1 and G.hand.highlighted[1].edition then - return false - end - return true + +G.FUNCS.can_flip_ds = function(e) + local card = e.config.ref_table + if + not (G.CONTROLLER.locked or (G.GAME.STOP_USE and G.GAME.STOP_USE > 0)) + and not G.SETTINGS.paused + and card.area.config.type ~= "shop" + then + e.config.colour = G.C.PURPLE + e.config.button = "flip_ds" + e.states.visible = true + else + e.config.colour = G.C.UI.BACKGROUND_INACTIVE + e.config.button = nil + if card.area.config.type == "shop" then + e.states.visible = false end - end, - cry_credits = { - art = { - "Linus Goof Balls", - }, - code = { - "Math", - }, - jolly = { - "Jolly Open Winner", - "Axolotolus", - }, - }, - loc_vars = function(self, info_queue) - info_queue[#info_queue + 1] = G.P_CENTERS.e_cry_double_sided - end, - use = function(self, card, area, copier) - if #G.jokers.highlighted == 1 then - G.jokers.highlighted[1]:remove_from_deck(true) - G.jokers.highlighted[1]:set_edition({ cry_double_sided = true }) - G.jokers.highlighted[1]:add_to_deck(true) - G.jokers:remove_from_highlighted(G.jokers.highlighted[1]) - else - G.hand.highlighted[1]:set_edition({ cry_double_sided = true }) - G.hand:remove_from_highlighted(G.hand.highlighted[1]) + end +end + +G.FUNCS.flip_ds = function(e) + e.config.ref_table:flip() +end + +G.FUNCS.can_merge_ds = function(e) + local card = e.config.ref_table + local other + for i, v in ipairs(card.area.highlighted) do + if v ~= card then + other = v end - end, - in_pool = function() - return G.GAME.used_vouchers.v_cry_double_slit - end, -} + end + local highlighted = #card.area.highlighted + if + not (G.CONTROLLER.locked or (G.GAME.STOP_USE and G.GAME.STOP_USE > 0)) + and highlighted == 2 + and not G.SETTINGS.paused + and not card.merged + and other + and not other.merged + and card.area + and card.area.config.type ~= "shop" + then + e.config.colour = G.C.PURPLE + e.config.button = "merge_ds" + e.states.visible = true + else + e.config.colour = G.C.UI.BACKGROUND_INACTIVE + e.config.button = nil + e.states.visible = false + end +end --- Enhancements/Tarots -local echo = { - cry_credits = { - idea = { - "Mystic Misclick", - }, - art = { - "Coronacht", - }, - code = { - "AlexZGreat", - }, - }, - object_type = "Enhancement", - dependencies = { - items = { - "set_cry_misc", - }, - }, - key = "echo", - atlas = "cry_misc", - pos = { x = 2, y = 0 }, - config = { retriggers = 2, extra = 2 }, - loc_vars = function(self, info_queue, card) - return { - vars = { - card and card.ability.retriggers or self.config.retriggers, - card and cry_prob(card.ability.cry_prob or 1, card.ability.extra, card.ability.cry_rigged) or 1, - card and card.ability.extra or self.config.extra, - }, - } -- note that the check for (card.ability.cry_prob or 1) is probably unnecessary due to cards being initialised with ability.cry_prob - end, - calculate = function(self, card, context) - if - context.repetition - and pseudorandom("echo") - < cry_prob(card.ability.cry_prob or 1, card.ability.extra or 2, card.ability.cry_rigged) / (card.ability.extra or 2) - then - return { - message = localize("k_again_ex"), - repetitions = card.ability.retriggers, - card = card, - } +G.FUNCS.merge_ds = function(e) + local card = e.config.ref_table + card.merged = true + local other + for i, v in ipairs(card.area.highlighted) do + if v ~= card then + other = v end - end, -} -local eclipse = { - cry_credits = { - idea = { - "Mystick Misclick", - }, - art = { - "AlexZGreat", - }, - code = { - "AlexZGreat", - }, - }, - object_type = "Consumable", - dependencies = { - items = { - "set_cry_misc", - "m_cry_echo", - }, - }, - set = "Tarot", - name = "cry-Eclipse", - key = "eclipse", - order = 1, - pos = { x = 4, y = 0 }, - config = { mod_conv = "m_cry_echo", max_highlighted = 1 }, - atlas = "atlasnotjokers", - loc_vars = function(self, info_queue, card) - info_queue[#info_queue + 1] = G.P_CENTERS.m_cry_echo - - return { vars = { card and card.ability.max_highlighted or self.config.max_highlighted } } - end, -} -local light = { - cry_credits = { - idea = { - "HexaCryonic", - }, - art = { - "AlexZGreat", - }, - code = { - "AlexZGreat", - }, - }, - object_type = "Enhancement", - dependencies = { - items = { - "set_cry_misc", - }, - }, - key = "light", - atlas = "cry_misc", - cry_noshadow = true, - pos = { x = 0, y = 3 }, - config = { extra = { a_x_mult = 0.2, current_x_mult = 1, req = 5, current = 5 } }, - loc_vars = function(self, info_queue, card) - return { - vars = { - card and card.ability.extra.a_x_mult or self.config.extra.a_x_mult, - card and card.ability.extra.current_x_mult or self.config.extra.current_x_mult, - card and card.ability.extra.current or self.config.extra.current, - card and card.ability.extra.req or self.config.extra.req, - }, - } - end, - calculate = function(self, card, context) - if context.cardarea == G.play and context.main_scoring then - if #context.scoring_hand > 1 then - card.ability.extra.current = card.ability.extra.current - (#context.scoring_hand - 1) - while card.ability.extra.current <= 0 do - card.ability.extra.req = card.ability.extra.req + 5 - card.ability.extra.current = card.ability.extra.current + card.ability.extra.req - card.ability.extra.current_x_mult = card.ability.extra.current_x_mult + card.ability.extra.a_x_mult - end - end - if card.ability.extra.current_x_mult > 1 then - return { - x_mult = card.ability.extra.current_x_mult, - } - end - end - end, -} -local seraph = { - cry_credits = { - idea = { - "HexaCryonic", - }, - art = { - "sachertote", - }, - code = { - "AlexZGreat", - }, - }, - object_type = "Consumable", - dependencies = { - items = { - "set_cry_misc", - "m_cry_light", - }, - }, - set = "Tarot", - name = "cry-Seraph", - key = "seraph", - order = 2, - pos = { x = 5, y = 3 }, - config = { mod_conv = "m_cry_light", max_highlighted = 2 }, - atlas = "atlasnotjokers", - loc_vars = function(self, info_queue, card) - info_queue[#info_queue + 1] = G.P_CENTERS.m_cry_light - - return { vars = { card and card.ability.max_highlighted or self.config.max_highlighted } } - end, -} -local blessing = { - cry_credits = { - idea = { - "5381", - }, - art = { - "RattlingSnow353", - }, - code = { - "Jevonn", - }, - }, - object_type = "Consumable", - dependencies = { - items = { - "set_cry_misc", - }, - }, - set = "Tarot", - name = "cry-theblessing", - key = "theblessing", - order = 6, - pos = { x = 2, y = 3 }, - cost = 3, - atlas = "atlasnotjokers", - can_use = function(self, card) - return #G.consumeables.cards < G.consumeables.config.card_limit or card.area == G.consumeables - end, - can_bulk_use = true, - use = function(self, card, area, copier) - local used_consumable = copier or card - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.4, - func = function() - if G.consumeables.config.card_limit > #G.consumeables.cards then - play_sound("timpani") - local forced_key = Cryptid.random_consumable("blessing", nil, "c_cry_blessing") - local _card = create_card( - "Consumeables", - G.consumeables, - nil, - nil, - nil, - nil, - forced_key.config.center_key, - "blessing" - ) - _card:add_to_deck() - G.consumeables:emplace(_card) - used_consumable:juice_up(0.3, 0.5) - end - return true - end, - })) - delay(0.6) - end, -} - --- Seals -local azure_seal = { - cry_credits = { - idea = { - "stupid", - }, - art = { - "stupid", - }, - code = { - "stupid", - }, - }, - object_type = "Seal", - dependencies = { - items = { - "set_cry_misc", - }, - }, - name = "cry-Azure-Seal", - key = "azure", - badge_colour = HEX("1d4fd7"), - config = { planets_amount = 3 }, - loc_vars = function(self, info_queue) - return { vars = { self.config.planets_amount } } - end, - atlas = "cry_misc", - pos = { x = 0, y = 2 }, - -- This is still quite jank - calculate = function(self, card, context) - if context.destroying_card and not card.will_shatter and context.cardarea == G.play then - for i, cards in ipairs(context.full_hand) do - if cards ~= card then - return - end - end - card.will_shatter = true - G.E_MANAGER:add_event(Event({ - trigger = "before", - delay = 0.0, - func = function() - local card_type = "Planet" - local _planet = nil - if G.GAME.last_hand_played then - for k, v in pairs(G.P_CENTER_POOLS.Planet) do - if v.config.hand_type == G.GAME.last_hand_played then - _planet = v.key - break - end - end - end - - for i = 1, self.config.planets_amount do - local card = create_card(card_type, G.consumeables, nil, nil, nil, nil, _planet, "cry_azure") - - card:set_edition({ negative = true }, true) - card:add_to_deck() - G.consumeables:emplace(card) - end - return true - end, - })) - - return { remove = true } - end - end, -} -local typhoon = { - cry_credits = { - idea = { - "stupid", - }, - art = { - "stupid", - }, - code = { - "stupid", - }, - }, - object_type = "Consumable", - dependencies = { - items = { - "set_cry_misc", - "cry_azure", - }, - }, - set = "Spectral", - name = "cry-Typhoon", - key = "typhoon", - order = 8, - config = { - -- This will add a tooltip. - mod_conv = "cry_azure_seal", - -- Tooltip args - seal = { planets_amount = 3 }, - max_highlighted = 1, - }, - loc_vars = function(self, info_queue, center) - -- Handle creating a tooltip with set args. - info_queue[#info_queue + 1] = - { set = "Other", key = "cry_azure_seal", specific_vars = { self.config.seal.planets_amount } } - return { vars = { center.ability.max_highlighted } } - end, - cost = 4, - atlas = "atlasnotjokers", - pos = { x = 0, y = 4 }, - use = function(self, card, area, copier) --Good enough - local used_consumable = copier or card - check_for_unlock({ cry_used_consumable = "c_cry_typhoon" }) - for i = 1, #G.hand.highlighted do - local highlighted = G.hand.highlighted[i] - G.E_MANAGER:add_event(Event({ - func = function() - play_sound("tarot1") - highlighted:juice_up(0.3, 0.5) - return true - end, - })) - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.1, - func = function() - if highlighted then - highlighted:set_seal("cry_azure") - end - return true - end, - })) - delay(0.5) - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.2, - func = function() - G.hand:unhighlight_all() - return true - end, - })) - end - end, -} + end + card.ability.immutable.other_side = copy_table(other.ability) + card.ability.immutable.other_side.key = copy_table(other.config.center.key) + card.ability.immutable.other_side.seal = copy_table(other.seal) + if other.base.nominal ~= 0 then + card.ability.immutable.other_side.base = copy_table(other.base) + end + other:start_dissolve() + if next(find_joker("cry-Flip Side")) then + card:remove_from_deck(true) + Card.add_to_deck(card:get_other_side_dummy(), true) + end +end +-- Absolute +-- Can't be sold, destroyed, Absolute can't be removed local absolute = { object_type = "Sticker", dependencies = { @@ -2128,6 +2480,7 @@ local absolute = { prefix_config = { key = false }, key = "cry_absolute", atlas = "sticker", + order = 3004, pos = { x = 1, y = 5 }, should_apply = false, no_sticker_sheet = true, @@ -2154,13 +2507,17 @@ local absolute = { ) end, } + local miscitems = { meme1, meme2, meme3, + baneful1, mosaic_shader, oversat_shader, glitched_shader, + glitched_shader2, + glitched_shaderb, astral_shader, blurred_shader, glass_shader, @@ -2177,10 +2534,10 @@ local miscitems = { echo, eclipse, blessing, - typhoon, azure_seal, - --double_sided, - --meld, + double_sided, + abstract, + instability, absolute, light, seraph, @@ -2201,6 +2558,37 @@ return { self.ignore_shadow["cry_noshadow"] = nil end end + function Card:calculate_abstract_break() + if self.config.center_key == "m_cry_abstract" and not self.ability.extra.marked then + if + SMODS.pseudorandom_probability( + self, + "cry_abstract_destroy2", + 1, + self.ability and self.ability.extra and self.ability.extra.odds_after_round + or self.config.extra.odds_after_round + or 4, + "Abstract Card" + ) + then + self.ability.extra.marked = true + --KUFMO HAS abstract!!!!111!!! + G.E_MANAGER:add_event(Event({ + trigger = "immediate", + delay = "0.1", + func = function() + self:juice_up(2, 2) + self:shatter(0.2) + return true + end, + })) + return true + else + return false + end + end + return false + end end, items = miscitems, } diff --git a/Cryptid/items/misc_joker.lua b/Cryptid/items/misc_joker.lua index 6797dfb..831c37a 100644 --- a/Cryptid/items/misc_joker.lua +++ b/Cryptid/items/misc_joker.lua @@ -1,3 +1,13 @@ +--[[ +gameset_config = { + modest = {extra = {chips = 1}, center = {rarity = 1, blueprint_compat = false, immutable = true, no_dbl = false}}, + mainline = {center = {rarity = 2, blueprint_compat = true, immutable = true, no_dbl = true}}, + madness = {extra = {chips = 100}, center = {rarity = 3}}, + cryptid_in_2025 = {extra = {chips = 1e308}, center = {rarity = "cry_exotic"}}, + }, +]] +-- +-- Card.get_gameset(card) ~= "modest" local dropshot = { object_type = "Joker", dependencies = { @@ -8,22 +18,36 @@ local dropshot = { name = "cry-Dropshot", key = "dropshot", order = 3, - config = { extra = { Xmult_mod = 0.2, x_mult = 1 } }, + config = { + extra = { + Xmult_mod = 0.2, + x_mult = 1, + }, + }, + gameset_config = { + modest = { + extra = { + Xmult_mod = 0.1, + x_mult = 1, + }, + }, + }, pos = { x = 5, y = 0 }, rarity = 3, cost = 8, blueprint_compat = true, perishable_compat = false, + demicoloncompat = true, atlas = "atlasone", loc_vars = function(self, info_queue, center) return { vars = { - center.ability.extra.Xmult_mod, + number_format(center.ability.extra.Xmult_mod), localize( G.GAME.current_round.cry_dropshot_card and G.GAME.current_round.cry_dropshot_card.suit or "Spades", "suits_singular" ), - center.ability.extra.x_mult, + number_format(center.ability.extra.x_mult), colours = { G.C.SUITS[G.GAME.current_round.cry_dropshot_card and G.GAME.current_round.cry_dropshot_card.suit or "Spades"], }, @@ -51,15 +75,13 @@ local dropshot = { v.cry_dropshot_incompat = nil end if cards > 0 then - card.ability.extra.x_mult = card.ability.extra.x_mult + cards * card.ability.extra.Xmult_mod - card_eval_status_text( - card, - "extra", - nil, - nil, - nil, - { message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.x_mult } }) } - ) + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "x_mult", + scalar_value = "Xmult_mod", + message_key = "a_xmult", + message_colour = G.C.RED, + }) return nil, true end end @@ -69,6 +91,18 @@ local dropshot = { Xmult_mod = card.ability.extra.x_mult, } end + if context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "x_mult", + scalar_value = "Xmult_mod", + no_message = true, + }) + return { + message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.x_mult } }), + Xmult_mod = card.ability.extra.x_mult, + } + end end, cry_credits = { idea = { @@ -87,22 +121,35 @@ local happyhouse = { object_type = "Joker", dependencies = { items = { - "set_cry_misc_joker", + "set_cry_meme", }, }, name = "cry-happyhouse", key = "happyhouse", pos = { x = 2, y = 4 }, order = 2, - config = { extra = { mult = 4, check = 0 } }, - immutable = true, + config = { + immutable = { + mult = 4, + trigger = 114, + check = 0, + ante_cutoff = 8, + }, + }, pools = { ["Meme"] = true }, rarity = 2, cost = 2, blueprint_compat = true, + demicoloncompat = true, atlas = "atlastwo", loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.mult, center.ability.extra.check } } + return { + vars = { + number_format(center.ability.immutable.mult), + number_format(center.ability.immutable.check), + number_format(center.ability.immutable.trigger), + }, + } end, calculate = function(self, card, context) if @@ -111,36 +158,58 @@ local happyhouse = { and not context.blueprint and not context.retrigger_joker then - card.ability.extra.check = card.ability.extra.check + 1 + card.ability.immutable.check = lenient_bignum(card.ability.immutable.check + 1) if - card.ability.extra.check == 114 - and G.GAME.round_resets.ante < 8 + card.ability.immutable.check == card.ability.immutable.trigger + and G.GAME.round_resets.ante < card.ability.immutable.ante_cutoff and not (G.GAME.selected_back.effect.center.key == "antimatter" or G.GAME.selected_back.effect.center.key == "equilibrium") and ( not CardSleeves or ( CardSleeves and G.GAME.selected_sleeve - -- and G.GAME.selected_sleeve ~= "sleeve_cry_antimatter_sleeve" TODO: Add check if Antimatter sleeve gets added + and G.GAME.selected_sleeve ~= "sleeve_cry_antimatter_sleeve" and G.GAME.selected_sleeve ~= "sleeve_cry_equilibrium_sleeve" ) ) then --Yes, the cut off point is boss blind Ante 7. I'm evil >:3. check_for_unlock({ type = "home_realtor" }) end - if card.ability.extra.check < 114 then --Hardcoded, dont want misprint to mess with this hehe + if card.ability.immutable.check < card.ability.immutable.trigger then --Hardcoded, dont want misprint to mess with this hehe return { card_eval_status_text(card, "extra", nil, nil, nil, { - message = card.ability.extra.check .. "/114", + message = number_format(card.ability.immutable.check) .. "/" .. number_format( + card.ability.immutable.trigger + ), colour = G.C.DARK_EDITION, }), } end end - if context.joker_main and (to_big(card.ability.extra.mult) > to_big(1)) and card.ability.extra.check > 113 then + if + context.joker_main + and (to_big(card.ability.immutable.mult) > to_big(1)) + and to_big(card.ability.immutable.check) > to_big(card.ability.immutable.trigger) + then return { - message = localize({ type = "variable", key = "a_powmult", vars = { card.ability.extra.mult } }), - Emult_mod = card.ability.extra.mult, + message = localize({ + type = "variable", + key = "a_powmult", + vars = { number_format(card.ability.immutable.mult) }, + }), + Emult_mod = lenient_bignum(card.ability.immutable.mult), + colour = G.C.DARK_EDITION, + card = card, + } + end + if context.forcetrigger then + return { + message = localize({ + type = "variable", + key = "a_powmult", + vars = { number_format(card.ability.immutable.mult) }, + }), + Emult_mod = lenient_bignum(card.ability.immutable.mult), colour = G.C.DARK_EDITION, card = card, } @@ -178,7 +247,7 @@ local maximized = { "Gold", }, art = { - "Gold", + "George The Rat", }, code = { "Math", @@ -221,25 +290,38 @@ local potofjokes = { }, name = "cry-Pot of Jokes", key = "pot_of_jokes", - config = { extra = { h_size = -2, h_mod = 1 }, immutable = { h_added = 0, h_mod_max = 1000 } }, + config = { + extra = { + h_size = -2, + h_mod = 1, + }, + immutable = { + h_added = 0, + h_mod_max = 1000, + }, + }, pos = { x = 5, y = 0 }, rarity = 3, order = 104, cost = 10, perishable_compat = false, + demicoloncompat = true, atlas = "atlastwo", loc_vars = function(self, info_queue, center) return { vars = { center.ability.extra.h_size < 0 and center.ability.extra.h_size or "+" .. math.min(1000, center.ability.extra.h_size), - center.ability.extra.h_mod, + number_format(center.ability.extra.h_mod), "+" .. center.ability.immutable.h_mod_max, }, } end, calculate = function(self, card, context) - if context.end_of_round and not context.individual and not context.repetition and not context.blueprint then + if + (context.end_of_round and not context.individual and not context.repetition and not context.blueprint) + or context.forcetrigger + then if to_big(card.ability.extra.h_size) + to_big(card.ability.extra.h_mod) >= to_big(card.ability.immutable.h_mod_max) @@ -257,21 +339,23 @@ local potofjokes = { end end - local delta = math.min( - math.max(0, card.ability.immutable.h_mod_max - card.ability.extra.h_size), - card.ability.extra.h_mod + local delta = to_number( + math.min( + math.max(0, card.ability.immutable.h_mod_max - card.ability.extra.h_size), + card.ability.extra.h_mod + ) ) G.hand:change_size(delta) - card.ability.extra.h_size = card.ability.extra.h_size + card.ability.extra.h_mod card.ability.immutable.h_added = card.ability.immutable.h_added + delta - return { - message = localize({ type = "variable", key = "a_handsize", vars = { card.ability.extra.h_mod } }), - colour = G.C.FILTER, - card = card, - } + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "h_size", + scalar_value = "h_mod", + message_key = "a_handsize", + }) end end, add_to_deck = function(self, card, from_debuff) @@ -319,6 +403,7 @@ local queensgambit = { order = 7, cost = 7, immutable = true, + demicoloncompat = true, loc_vars = function(self, info_queue, center) if not center.edition or (center.edition and not center.edition.negative) then info_queue[#info_queue + 1] = G.P_CENTERS.e_negative @@ -329,7 +414,7 @@ local queensgambit = { calculate = function(self, card, context) if context.destroying_card and not context.blueprint then if - G.GAME.current_round.current_hand.handname == "Royal Flush" + G.GAME.current_round.current_hand.handname == localize("Royal Flush", "poker_hands") and context.destroying_card:get_id() == 12 then card_eval_status_text( @@ -351,16 +436,37 @@ local queensgambit = { return true end, })) - return { remove = not context.destroying_card.ability.eternal } + return { remove = not SMODS.is_eternal(context.destroying_card) } end end + if context.forcetrigger then + card_eval_status_text( + card, + "extra", + nil, + nil, + nil, + { message = localize("k_plus_joker"), colour = G.C.FILTER } + ) + G.E_MANAGER:add_event(Event({ + trigger = "after", + func = function() + local card = create_card("Joker", G.jokers, nil, 0.99, nil, nil, nil, "cry_gambit") + card:set_edition({ negative = true }) + card:add_to_deck() + G.jokers:emplace(card) + card:start_materialize() + return true + end, + })) + end end, cry_credits = { idea = { "Project666", }, art = { - "Ein13", + "Missingnumber", }, code = { --wonder what happened to this guy @@ -377,7 +483,20 @@ local wee_fib = { }, name = "cry-Wee Fibonacci", key = "wee_fib", - config = { extra = { mult = 0, mult_mod = 3 } }, + config = { + extra = { + mult = 0, + mult_mod = 3, + }, + }, + gameset_config = { + modest = { + extra = { + mult = 0, + mult_mod = 1, + }, + }, + }, pos = { x = 1, y = 5 }, display_size = { w = 0.7 * 71, h = 0.7 * 95 }, rarity = 3, @@ -385,29 +504,50 @@ local wee_fib = { order = 98, blueprint_compat = true, perishable_compat = false, + demicoloncompat = true, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.mult, center.ability.extra.mult_mod } } + return { + vars = { + number_format(center.ability.extra.mult), + number_format(center.ability.extra.mult_mod), + }, + } end, calculate = function(self, card, context) if context.cardarea == G.play and context.individual and not context.blueprint then local rank = context.other_card:get_id() if rank == 14 or rank == 2 or rank == 3 or rank == 5 or rank == 8 then - card.ability.extra.mult = card.ability.extra.mult + card.ability.extra.mult_mod - - return { - extra = { focus = card, message = localize("k_upgrade_ex") }, - card = card, - colour = G.C.MULT, - } + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "mult", + scalar_value = "mult_mod", + message_colour = G.C.MULT, + }) end end if context.joker_main and (to_big(card.ability.extra.mult) > to_big(0)) then return { - message = localize({ type = "variable", key = "a_mult", vars = { card.ability.extra.mult } }), - mult_mod = card.ability.extra.mult, + message = localize({ + type = "variable", + key = "a_mult", + vars = { number_format(card.ability.extra.mult) }, + }), + mult_mod = lenient_bignum(card.ability.extra.mult), colour = G.C.MULT, } end + if context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "mult", + scalar_value = "mult_mod", + message_colour = G.C.MULT, + no_message = true, + }) + return { + mult = lenient_bignum(card.ability.extra.mult), + } + end end, cry_credits = { idea = { @@ -431,15 +571,34 @@ local whip = { name = "cry-The WHIP", key = "whip", pos = { x = 5, y = 3 }, - config = { extra = { Xmult_mod = 0.5, x_mult = 1 } }, + config = { + extra = { + Xmult_mod = 0.5, + x_mult = 1, + }, + }, + gameset_config = { + modest = { + extra = { + Xmult_mod = 0.1, + x_mult = 1, + }, + }, + }, rarity = 2, cost = 8, order = 15, blueprint_compat = true, perishable_compat = false, + demicoloncompat = true, atlas = "atlasone", loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.Xmult_mod, center.ability.extra.x_mult } } + return { + vars = { + number_format(center.ability.extra.Xmult_mod), + number_format(center.ability.extra.x_mult), + }, + } end, calculate = function(self, card, context) if context.cardarea == G.jokers and context.before and not context.blueprint then @@ -490,13 +649,12 @@ local whip = { (#twosuits > 1 or #sevensuits > 1) or (#twosuits == 1 and #sevensuits == 1 and twosuits[1] ~= sevensuits[1]) then - card.ability.extra.x_mult = card.ability.extra.x_mult + card.ability.extra.Xmult_mod - card_eval_status_text(card, "extra", nil, nil, nil, { - message = localize({ - type = "variable", - key = "a_xmult", - vars = { card.ability.extra.x_mult }, - }), + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "x_mult", + scalar_value = "Xmult_mod", + message_key = "a_xmult", + message_colour = G.C.MULT, }) return nil, true end @@ -505,10 +663,25 @@ local whip = { end if context.joker_main and (to_big(card.ability.extra.x_mult) > to_big(1)) then return { - message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.x_mult } }), + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.x_mult) }, + }), Xmult_mod = card.ability.extra.x_mult, } end + if context.force_trigger then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "x_mult", + scalar_value = "Xmult_mod", + no_message = true, + }) + return { + xmult = card.ability.extra.x_mult, + } + end end, cry_credits = { idea = { @@ -532,11 +705,19 @@ local lucky_joker = { name = "cry-Lucky Joker", key = "lucky_joker", config = { extra = { dollars = 5 } }, + gameset_config = { + modest = { + extra = { + dollars = 4, + }, + }, + }, pos = { x = 4, y = 3 }, rarity = 1, cost = 4, order = 36, blueprint_compat = true, + demicoloncompat = true, atlas = "atlasone", enhancement_gate = "m_lucky", loc_vars = function(self, info_queue, center) @@ -545,7 +726,7 @@ local lucky_joker = { end, calculate = function(self, card, context) if context.individual and context.other_card.lucky_trigger then - G.GAME.dollar_buffer = (G.GAME.dollar_buffer or 0) + card.ability.extra.dollars + G.GAME.dollar_buffer = lenient_bignum((G.GAME.dollar_buffer or 0) + card.ability.extra.dollars) G.E_MANAGER:add_event(Event({ func = function() G.GAME.dollar_buffer = 0 @@ -553,7 +734,13 @@ local lucky_joker = { end, })) return { - dollars = card.ability.extra.dollars, + dollars = lenient_bignum(card.ability.extra.dollars), + card = card, + } + end + if context.forcetrigger then + return { + dollars = lenient_bignum(card.ability.extra.dollars), card = card, } end @@ -580,29 +767,61 @@ local cursor = { name = "cry-Cursor", key = "cursor", config = { extra = { chips = 0, chip_mod = 8 } }, + gameset_config = { + modest = { + extra = { + chips = 0, + chip_mod = 4, + }, + }, + }, pos = { x = 4, y = 1 }, rarity = 1, cost = 5, order = 5, blueprint_compat = true, perishable_compat = false, + demicoloncompat = true, atlas = "atlasone", loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.chips, center.ability.extra.chip_mod } } + return { + vars = { + number_format(center.ability.extra.chips), + number_format(center.ability.extra.chip_mod), + }, + } end, calculate = function(self, card, context) if context.buying_card and not context.blueprint and not (context.card == card) then - card.ability.extra.chips = card.ability.extra.chips + card.ability.extra.chip_mod - card_eval_status_text(card, "extra", nil, nil, nil, { - message = localize({ type = "variable", key = "a_chips", vars = { card.ability.extra.chips } }), - colour = G.C.CHIPS, + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "chips", + scalar_value = "chip_mod", + message_key = "a_chips", + message_colour = G.C.CHIPS, }) return nil, true end if context.joker_main and (to_big(card.ability.extra.chips) > to_big(0)) then return { - message = localize({ type = "variable", key = "a_chips", vars = { card.ability.extra.chips } }), - chip_mod = card.ability.extra.chips, + message = localize({ + type = "variable", + key = "a_chips", + vars = { number_format(card.ability.extra.chips) }, + }), + chip_mod = lenient_bignum(card.ability.extra.chips), + } + end + if context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "chips", + scalar_value = "chip_mod", + message_key = "a_chips", + message_colour = G.C.CHIPS, + }) + return { + chip_mod = lenient_bignum(card.ability.extra.chips), } end end, @@ -627,21 +846,35 @@ local pickle = { }, name = "cry-Pickle", key = "pickle", - config = { extra = { tags = 3, tags_mod = 1 } }, + config = { + extra = { + tags = 3, + tags_mod = 1, + }, + immutable = { + max_tags = 20, + }, + }, pos = { x = 3, y = 3 }, rarity = 2, order = 45, cost = 6, blueprint_compat = true, eternal_compat = false, + demicoloncompat = true, atlas = "atlasone", pools = { ["Food"] = true }, loc_vars = function(self, info_queue, center) - return { vars = { math.min(20, center.ability.extra.tags), center.ability.extra.tags_mod } } + return { + vars = { + math.min(center.ability.immutable.max_tags, center.ability.extra.tags), + number_format(center.ability.extra.tags_mod), + }, + } end, calculate = function(self, card, context) - if context.skip_blind then - for i = 1, math.min(20, card.ability.extra.tags) do + if context.skip_blind or context.forcetrigger then + for i = 1, to_number(math.min(card.ability.immutable.max_tags, card.ability.extra.tags)) do local tag_key = get_next_tag_key("cry_pickle") if tag_key == "tag_boss" then i = i - 1 --skip these, as they can cause bugs with pack opening from other tags @@ -664,23 +897,31 @@ local pickle = { message = localize({ type = "variable", key = card.ability.extra.tags == 1 and "a_tag" or "a_tags", - vars = { card.ability.extra.tags }, + vars = { number_format(card.ability.extra.tags) }, })[1], colour = G.C.FILTER, }) return nil, true end - if context.setting_blind and not context.blueprint then - card.ability.extra.tags = card.ability.extra.tags - card.ability.extra.tags_mod + if (context.setting_blind and not context.blueprint) or context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "tags", + scalar_value = "tags_mod", + operation = "-", + no_message = true, + }) if to_big(card.ability.extra.tags) > to_big(0) then - card_eval_status_text(card, "extra", nil, nil, nil, { - message = localize({ - type = "variable", - key = card.ability.extra.tags_mod == 1 and "a_tag_minus" or "a_tags_minus", - vars = { card.ability.extra.tags_mod }, - })[1], - colour = G.C.FILTER, - }) + if not msg or type(msg) == "string" then + card_eval_status_text(card, "extra", nil, nil, nil, { + message = msg or localize({ + type = "variable", + key = card.ability.extra.tags_mod == 1 and "a_tag_minus" or "a_tags_minus", + vars = { number_format(card.ability.extra.tags_mod) }, + })[1], + colour = G.C.FILTER, + }) + end return nil, true else G.E_MANAGER:add_event(Event({ @@ -728,7 +969,7 @@ local cube = { object_type = "Joker", dependencies = { items = { - "set_cry_misc_joker", + "set_cry_meme", }, }, name = "cry-Cube", @@ -740,17 +981,22 @@ local cube = { order = 11, cost = -27, blueprint_compat = true, + demicoloncompat = true, atlas = "atlasone", pools = { ["Meme"] = true }, source_gate = "sho", loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.chips } } + return { vars = { number_format(center.ability.extra.chips) } } end, calculate = function(self, card, context) - if context.joker_main then + if context.joker_main or context.forcetrigger then return { - message = localize({ type = "variable", key = "a_chips", vars = { card.ability.extra.chips } }), - chip_mod = card.ability.extra.chips, + message = localize({ + type = "variable", + key = "a_chips", + vars = { number_format(card.ability.extra.chips) }, + }), + chip_mod = lenient_bignum(card.ability.extra.chips), } end end, @@ -782,9 +1028,10 @@ local triplet_rhythm = { order = 10, cost = 6, blueprint_compat = true, + demicoloncompat = true, atlas = "atlastwo", loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.Xmult } } + return { vars = { number_format(center.ability.extra.Xmult) } } end, calculate = function(self, card, context) if context.joker_main and context.scoring_hand then @@ -796,11 +1043,25 @@ local triplet_rhythm = { end if threes == 3 then return { - message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.Xmult } }), - Xmult_mod = card.ability.extra.Xmult, + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), } end end + if context.forcetrigger then + return { + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), + } + end end, cry_credits = { idea = { @@ -823,7 +1084,10 @@ local booster = { }, name = "cry-Booster Joker", key = "booster", - config = { extra = { booster_slots = 1 } }, + config = { + extra = { booster_slots = 1 }, + immutable = { max_slots = 25 }, + }, pos = { x = 2, y = 0 }, display_size = { w = 1.17 * 71, h = 1.17 * 95 }, order = 34, @@ -832,14 +1096,14 @@ local booster = { blueprint_compat = false, atlas = "atlastwo", loc_vars = function(self, info_queue, center) - return { vars = { math.min(25, center.ability.extra.booster_slots) } } + return { vars = { math.min(center.ability.immutable.max_slots, center.ability.extra.booster_slots) } } end, add_to_deck = function(self, card, from_debuff) - local mod = math.min(25, card.ability.extra.booster_slots) + local mod = to_number(math.min(card.ability.immutable.max_slots, card.ability.extra.booster_slots)) SMODS.change_booster_limit(mod) end, remove_from_deck = function(self, card, from_debuff) - local mod = math.min(25, card.ability.extra.booster_slots) + local mod = to_number(math.min(card.ability.immutable.max_slots, card.ability.extra.booster_slots)) SMODS.change_booster_limit(-mod) end, cry_credits = { @@ -863,7 +1127,22 @@ local chili_pepper = { }, name = "cry-Chili Pepper", key = "chili_pepper", - config = { extra = { Xmult = 1, Xmult_mod = 0.5, rounds_remaining = 8 } }, + config = { + extra = { + Xmult = 1, + Xmult_mod = 0.5, + rounds_remaining = 8, + }, + }, + gameset_config = { + modest = { + extra = { + Xmult = 1, + Xmult_mod = 0.5, + rounds_remaining = 5, + }, + }, + }, pos = { x = 0, y = 1 }, rarity = 2, cost = 6, @@ -871,18 +1150,27 @@ local chili_pepper = { blueprint_compat = true, eternal_compat = false, perishable_compat = false, + demicoloncompat = true, atlas = "atlastwo", pools = { ["Food"] = true }, loc_vars = function(self, info_queue, center) return { - vars = { center.ability.extra.Xmult, center.ability.extra.Xmult_mod, center.ability.extra.rounds_remaining }, + vars = { + number_format(center.ability.extra.Xmult), + number_format(center.ability.extra.Xmult_mod), + number_format(center.ability.extra.rounds_remaining), + }, } end, calculate = function(self, card, context) if context.joker_main and to_big(card.ability.extra.Xmult) > to_big(1) then return { - message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.Xmult } }), - Xmult_mod = card.ability.extra.Xmult, + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), } end if @@ -892,13 +1180,25 @@ local chili_pepper = { and not context.repetition and not context.retrigger_joker then - card.ability.extra.Xmult = card.ability.extra.Xmult + card.ability.extra.Xmult_mod - card.ability.extra.rounds_remaining = card.ability.extra.rounds_remaining - 1 - if card.ability.extra.rounds_remaining > 0 then - return { - message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.Xmult } }), - colour = G.C.FILTER, - } + card.ability.extra.rounds_remaining = lenient_bignum(to_big(card.ability.extra.rounds_remaining) - 1) + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "Xmult", + scalar_value = "Xmult_mod", + no_message = true, + }) + if to_big(card.ability.extra.rounds_remaining) > to_big(0) then + if not msg or type(msg) == "string" then + return { + message = msg or localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), + colour = G.C.FILTER, + } + end + return nil, true else G.E_MANAGER:add_event(Event({ func = function() @@ -927,6 +1227,19 @@ local chili_pepper = { } end end + if context.forcetrigger then + card.ability.extra.rounds_remaining = lenient_bignum(to_big(card.ability.extra.rounds_remaining) - 1) + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "Xmult", + scalar_value = "Xmult_mod", + message_key = "a_xmult", + message_colour = G.C.MULT, + }) + return { + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), + } + end end, cry_credits = { idea = { @@ -950,7 +1263,12 @@ local compound_interest = { }, name = "cry-Compound Interest", key = "compound_interest", - config = { extra = { percent_mod = 3, percent = 12 } }, + config = { + extra = { + percent_mod = 3, + percent = 12, + }, + }, pos = { x = 3, y = 2 }, rarity = 3, order = 9, @@ -958,15 +1276,28 @@ local compound_interest = { perishable_compat = false, atlas = "atlastwo", loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.percent, center.ability.extra.percent_mod } } + return { + vars = { + number_format(center.ability.extra.percent), + number_format(center.ability.extra.percent_mod), + }, + } end, calc_dollar_bonus = function(self, card) - if G.GAME.dollars > to_big(0) then - local bonus = math.max(0, math.floor(0.01 * card.ability.extra.percent * (G.GAME.dollars or 1))) - local old = card.ability.extra.percent - card.ability.extra.percent = card.ability.extra.percent + card.ability.extra.percent_mod - Cryptid.compound_interest_scale_mod(card, card.ability.extra.percent_mod, old, card.ability.extra.percent) - if bonus > to_big(0) then + if to_big(G.GAME.dollars) > to_big(0) then + local bonus = lenient_bignum( + math.max(0, math.floor(0.01 * to_big(card.ability.extra.percent) * (G.GAME.dollars or 1))) + ) + + local old = lenient_bignum(card.ability.extra.percent) + + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "percent", + scalar_value = "percent_mod", + no_message = true, + }) + if to_big(bonus) > to_big(0) then return bonus end else @@ -997,24 +1328,39 @@ local big_cube = { key = "big_cube", joker_gate = "cry-Cube", config = { extra = { x_chips = 6 }, override_x_chips_check = true }, + gameset_config = { + modest = { + extra = { + x_chips = 3, + }, + }, + }, pos = { x = 4, y = 4 }, rarity = 1, order = 105, cost = 27, blueprint_compat = true, + demicoloncompat = true, atlas = "atlasone", loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.x_chips } } + return { vars = { number_format(center.ability.extra.x_chips) } } end, calculate = function(self, card, context) - if context.joker_main then + if context.joker_main or context.forcetrigger then return { - message = localize({ type = "variable", key = "a_xchips", vars = { card.ability.extra.x_chips } }), - Xchip_mod = card.ability.extra.x_chips, + message = localize({ + type = "variable", + key = "a_xchips", + vars = { number_format(card.ability.extra.x_chips) }, + }), + Xchip_mod = lenient_bignum(card.ability.extra.x_chips), colour = G.C.CHIPS, } end end, + in_pool = function(self) + return #find_joker("cry-Cube", true) ~= 0 + end, cry_credits = { idea = { "Mystic Misclick", @@ -1037,15 +1383,24 @@ local eternalflame = { name = "cry-eternalflame", key = "eternalflame", pos = { x = 0, y = 4 }, - config = { extra = { extra = 0.2, x_mult = 1 } }, + config = { + extra = { + extra = 0.1, + x_mult = 1, + }, + }, rarity = 3, order = 100, cost = 9, perishable_compat = false, blueprint_compat = true, + demicoloncompat = true, loc_vars = function(self, info_queue, center) return { - vars = { center.ability.extra.extra, center.ability.extra.x_mult }, + vars = { + number_format(center.ability.extra.extra), + number_format(center.ability.extra.x_mult), + }, key = Card.get_gameset(card) ~= "modest" and "j_cry_eternalflame2" or "j_cry_eternalflame", } end, @@ -1053,32 +1408,47 @@ local eternalflame = { calculate = function(self, card, context) if context.joker_main and (to_big(card.ability.extra.x_mult) > to_big(1)) then return { - message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.x_mult } }), - Xmult_mod = card.ability.extra.x_mult, + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.x_mult) }, + }), + Xmult_mod = lenient_bignum(card.ability.extra.x_mult), } elseif context.selling_card - and (context.card.sell_cost >= 3 or Card.get_gameset(card) ~= "modest") + and (context.card.sell_cost >= 2 or Card.get_gameset(card) ~= "modest") and not context.blueprint then - card.ability.extra.x_mult = card.ability.extra.x_mult + card.ability.extra.extra - card_eval_status_text( - card, - "extra", - nil, - nil, - nil, - { message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.x_mult } }) } - ) + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "x_mult", + scalar_value = "extra", + message_key = "a_xmult", + message_colour = G.C.MULT, + }) return nil, true end + if context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "x_mult", + scalar_value = "extra", + message_key = "a_xmult", + message_colour = G.C.MULT, + }) + return { + Xmult_mod = lenient_bignum(card.ability.extra.x_mult), + } + end end, cry_credits = { idea = { "Dovahkiin1307", }, art = { - "Jevonn", + "Missingnumber", + "George The Rat", }, code = { "Jevonn", @@ -1089,41 +1459,66 @@ local nice = { object_type = "Joker", dependencies = { items = { - "set_cry_misc_joker", + "set_cry_meme", }, }, name = "cry-Nice", key = "nice", - config = { extra = { chips = 420, sixcount = 0, ninecount = 0 } }, + config = { + extra = { + chips = 420, + }, + }, + gameset_config = { + modest = { + extra = { + chips = 200, + }, + }, + }, pos = { x = 2, y = 3 }, pools = { ["Meme"] = true }, rarity = 3, - cost = 6.9, + cost = 6, order = 84, atlas = "atlasone", blueprint_compat = true, + demicoloncompat = true, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.chips } } + return { vars = { number_format(center.ability.extra.chips) } } end, calculate = function(self, card, context) - if context.cardarea == G.jokers and context.before then - card.ability.extra.sixcount = 0 - card.ability.extra.ninecount = 0 - for i, v in pairs(context.full_hand) do - if v:get_id() == 6 then - card.ability.extra.sixcount = card.ability.extra.sixcount + 1 - elseif v:get_id() == 9 then - card.ability.extra.ninecount = card.ability.extra.ninecount + 1 + if context.cardarea == G.jokers and context.joker_main then + local aaa, bbb = nil, nil + for i = 1, #context.full_hand do + if context.full_hand[i]:get_id() == 6 then + aaa = true + end + if context.full_hand[i]:get_id() == 9 then + bbb = true end end - elseif context.cardarea == G.jokers and context.joker_main then - if card.ability.extra.sixcount > 0 and card.ability.extra.ninecount > 0 then + if aaa and bbb then return { - message = localize({ type = "variable", key = "a_chips", vars = { card.ability.extra.chips or 0 } }), - chip_mod = card.ability.extra.chips or 0, + message = localize({ + type = "variable", + key = "a_chips", + vars = { number_format(card.ability.extra.chips) }, + }), + chip_mod = lenient_bignum(card.ability.extra.chips), } end end + if context.forcetrigger then + return { + message = localize({ + type = "variable", + key = "a_chips", + vars = { number_format(card.ability.extra.chips) }, + }), + chip_mod = lenient_bignum(card.ability.extra.chips), + } + end end, cry_credits = { idea = { @@ -1156,7 +1551,8 @@ local seal_the_deal = { calculate = function(self, card, context) if context.after - and G.GAME.current_round.hands_left == 0 + and (G.GAME.current_round.hands_left == 0 or next(find_joker("cry-panopticon"))) + and context.scoring_hand and not context.blueprint and not context.retrigger_joker then @@ -1183,17 +1579,11 @@ local seal_the_deal = { end end, set_ability = function(self, card, initial, delay_sprites) - local sealtable = { "blue", "red", "purple" } - if Cryptid.enabled("cry_azure") then - sealtable[#sealtable + 1] = "azure" - end - if Cryptid.enabled("cry_green") then - sealtable[#sealtable + 1] = "green" - end + local sealtable = { "blue", "red", "purple", "azure", "green" } card.ability.extra = pseudorandom_element(sealtable, pseudoseed("abc")) - if self.discovered then + if self.discovered and not (card.area and card.area.config.collection) then --Gold (ULTRA RARE!!!!!!!!) - if pseudorandom("xyz") <= 0.000001 and not (card.area and card.area.config.collection) then + if pseudorandom("xyz") <= 0.000001 then card.children.center:set_sprite_pos({ x = 6, y = 4 }) --Others elseif card.ability.extra == "red" then @@ -1223,20 +1613,23 @@ local chad = { object_type = "Joker", dependencies = { items = { - "set_cry_misc_joker", + "set_cry_meme", }, }, name = "cry-Chad", key = "chad", pos = { x = 0, y = 3 }, order = 71, - config = { extra = { retriggers = 2 } }, + config = { + extra = { retriggers = 2 }, + immutable = { max_retriggers = 25 }, + }, pools = { ["Meme"] = true }, rarity = 3, cost = 10, blueprint_compat = true, loc_vars = function(self, info_queue, center) - return { vars = { math.min(25, center.ability.extra.retriggers) } } + return { vars = { math.min(center.ability.immutable.max_retriggers, center.ability.extra.retriggers) } } end, atlas = "atlasone", calculate = function(self, card, context) @@ -1244,7 +1637,9 @@ local chad = { if context.other_card == G.jokers.cards[1] then return { message = localize("k_again_ex"), - repetitions = math.min(25, card.ability.extra.retriggers), + repetitions = to_number( + math.min(card.ability.immutable.max_retriggers, card.ability.extra.retriggers) + ), card = card, } else @@ -1268,7 +1663,7 @@ local jimball = { object_type = "Joker", dependencies = { items = { - "set_cry_misc_joker", + "set_cry_meme", }, }, name = "cry-Jimball", @@ -1276,15 +1671,26 @@ local jimball = { pos = { x = 0, y = 0 }, pixel_size = { w = 57 / 69 * 71, h = 57 / 69 * 71 }, order = 8, - config = { x_mult = 1, extra = 0.15, override_x_mult_check = true }, + config = { + extra = { + x_mult = 1, + x_mult_mod = 0.15, + }, + }, pools = { ["Meme"] = true }, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra, center.ability.x_mult } } + return { + vars = { + number_format(center.ability.extra.x_mult_mod), + number_format(center.ability.extra.x_mult), + }, + } end, rarity = 3, cost = 9, blueprint_compat = true, perishable_compat = false, + demicoloncompat = true, calculate = function(self, card, context) if context.before and not context.blueprint then local reset = false @@ -1295,18 +1701,47 @@ local jimball = { end end if reset then - if to_big(card.ability.x_mult) > to_big(1) then - card.ability.x_mult = 1 + if to_big(card.ability.extra.x_mult) > to_big(1) then + card.ability.extra.x_mult = 1 return { card = self, message = localize("k_reset"), } end else - card.ability.x_mult = card.ability.x_mult + card.ability.extra + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "x_mult", + scalar_value = "x_mult_mod", + message_key = "a_xmult", + message_colour = G.C.MULT, + }) return nil, true end end + --Adding actual scoring because that is missing + if context.joker_main and to_big(card.ability.extra.x_mult) > to_big(1) then + return { + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.x_mult) }, + }), + Xmult_mod = lenient_bignum(card.ability.extra.x_mult), + } + end + if context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "x_mult", + scalar_value = "x_mult_mod", + message_key = "a_xmult", + message_colour = G.C.MULT, + }) + return { + Xmult_mod = lenient_bignum(card.ability.extra.x_mult), + } + end end, add_to_deck = function(self, card, from_debuff) if not from_debuff then @@ -1368,7 +1803,7 @@ local sus = { object_type = "Joker", dependencies = { items = { - "set_cry_misc_joker", + "set_cry_meme", }, }, name = "cry-SUS", @@ -1382,88 +1817,81 @@ local sus = { atlas = "atlasone", calculate = function(self, card, context) local function is_impostor(card) - return card.base.value and SMODS.Ranks[card.base.value].key == "King" and card:is_suit("Hearts") + return card.base.value and card:get_id() == 13 and card:is_suit("Hearts") end - if - context.end_of_round - and context.cardarea == G.jokers - and not context.blueprint - and not context.retrigger_joker - then - if not card.ability.used_round or card.ability.used_round ~= G.GAME.round then - card.ability.chosen_card = nil - end - local choosable_cards = {} - local has_impostor = false - for i = 1, #G.hand.cards do - if not G.hand.cards[i].murdered_by_impostor then - choosable_cards[#choosable_cards + 1] = G.hand.cards[i] - if is_impostor(G.hand.cards[i]) then - has_impostor = true - end + if context.end_of_round and context.cardarea == G.jokers and #G.hand.cards >= 1 then + local king_of_hearts_cards, destroyed_cards = {}, {} + local chosen_card = nil + -- use the chosen card from previous SUS activations if there are any + -- Use a random card elsewhere + for _, v in ipairs(G.hand.cards) do + if v.sus then + chosen_card = v + break end end - if has_impostor then - choosable_cards = {} - for i = 1, #G.hand.cards do - if not G.hand.cards[i].murdered_by_impostor and is_impostor(G.hand.cards[i]) then - choosable_cards[#choosable_cards + 1] = G.hand.cards[i] - end + chosen_card = chosen_card or pseudorandom_element(G.hand.cards, pseudoseed("cry_sus")) + -- For future sus activations + chosen_card.sus = true + + -- Add Ignored cards to a table, this table will be used to destroy the cards + -- Ignore King of Kearts and ignore the chosen card only if there are no King of Hearts + for _, v in ipairs(G.hand.cards) do + if is_impostor(v) then + table.insert(king_of_hearts_cards, v) + end + if not SMODS.is_eternal(v) and not (v.sus and #king_of_hearts_cards == 0) and not is_impostor(v) then + table.insert(destroyed_cards, v) end end - card.ability.chosen_card = card.ability.chosen_card - or pseudorandom_element(choosable_cards, pseudoseed("cry_sus")) - if not card.ability.used_round or card.ability.used_round ~= G.GAME.round then - card.ability.used_round = G.GAME.round - local deletable_cards = {} - for k, v in pairs(G.hand.cards) do - if not v.ability.eternal and not is_impostor(v) then - deletable_cards[#deletable_cards + 1] = v - end - end - if #deletable_cards ~= 0 then - local _first_dissolve = nil - for j = 1, #G.jokers.cards do - eval_card( - G.jokers.cards[j], - { cardarea = G.jokers, remove_playing_cards = true, removed = deletable_cards } - ) - end - G.E_MANAGER:add_event(Event({ - trigger = "before", - delay = 0.75, - func = function() - for k, v in pairs(deletable_cards) do - if v ~= card.ability.chosen_card then - v.murdered_by_impostor = true - v:start_dissolve(nil, _first_dissolve) - _first_dissolve = true - end - end - return true - end, - })) - end - end - if card.ability.chosen_card ~= nil then + -- Destroy Cards + -- Don't destroy them if they were already destroyed though + if not G.GAME.sus_cards then G.E_MANAGER:add_event(Event({ - trigger = "before", - delay = 0.4, + trigger = "after", + delay = 0.1, func = function() - card:juice_up(0.3, 0.4) - G.playing_card = (G.playing_card and G.playing_card + 1) or 1 - local _c = copy_card(card.ability.chosen_card, nil, nil, G.playing_card) - _c:start_materialize() - _c:add_to_deck() - G.deck.config.card_limit = G.deck.config.card_limit + 1 - table.insert(G.playing_cards, _c) - G.hand:emplace(_c) - playing_card_joker_effects({ _c }) + for i = #destroyed_cards, 1, -1 do + local aaa = destroyed_cards[i] + if SMODS.shatters(aaa) then + aaa:shatter() + else + aaa:start_dissolve(nil, i == #destroyed_cards) + end + end return true end, })) - return { message = localize("cry_sus_ex") } end + --Create the copied card + G.E_MANAGER:add_event(Event({ + trigger = "before", + delay = 0.4, + func = function() + card:juice_up(0.3, 0.4) + G.playing_card = (G.playing_card or 0) + 1 + --Prioritize copying King of hearts if there are any, otherwise copy the chosen card + local to_copy = ( + #king_of_hearts_cards > 0 and pseudorandom_element(king_of_hearts_cards, pseudoseed("cry_sus2")) + ) or chosen_card + local _c = copy_card(to_copy, nil, nil, G.playing_card) + _c:start_materialize() + _c:add_to_deck() + G.deck.config.card_limit = G.deck.config.card_limit + 1 + table.insert(G.playing_cards, _c) + G.hand:emplace(_c) + playing_card_joker_effects({ _c }) + return true + end, + })) + + -- use destroyed cards to Calc card removal effects + -- not here though; doing it here would make said effects trigger multiple times + if not G.GAME.sus_cards then + G.GAME.sus_cards = destroyed_cards + end + -- SMODS.calculate_context({ remove_playing_cards = true, removed = G.GAME.sus_cards }) + return { message = localize("cry_sus_ex") } end end, cry_credits = { @@ -1489,32 +1917,59 @@ local fspinner = { name = "cry-fspinner", key = "fspinner", pos = { x = 4, y = 0 }, - config = { extra = { chips = 0, chip_mod = 6 } }, + config = { + extra = { + chips = 0, + chip_mod = 6, + }, + }, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.chips, center.ability.extra.chip_mod } } + return { + vars = { + number_format(center.ability.extra.chips), + number_format(center.ability.extra.chip_mod), + }, + } end, rarity = 1, cost = 5, order = 77, blueprint_compat = true, perishable_compat = false, + demicoloncompat = true, calculate = function(self, card, context) if context.before and not context.blueprint then local play_more_than = (G.GAME.hands[context.scoring_name].played or 0) for k, v in pairs(G.GAME.hands) do if k ~= context.scoring_name and v.played >= play_more_than and v.visible then - card.ability.extra.chips = card.ability.extra.chips + card.ability.extra.chip_mod - return { - message = localize("k_upgrade_ex"), - card = card, - } + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "chips", + scalar_value = "chip_mod", + }) end end end if context.joker_main and (to_big(card.ability.extra.chips) > to_big(0)) then return { - message = localize({ type = "variable", key = "a_chips", vars = { card.ability.extra.chips } }), - chip_mod = card.ability.extra.chips, + message = localize({ + type = "variable", + key = "a_chips", + vars = { number_format(card.ability.extra.chips) }, + }), + chip_mod = lenient_bignum(card.ability.extra.chips), + } + end + if context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "chips", + scalar_value = "chip_mod", + message_key = "a_chips", + message_colour = G.C.BLUE, + }) + return { + chip_mod = lenient_bignum(card.ability.extra.chips), } end end, @@ -1524,8 +1979,7 @@ local fspinner = { "Jevonn", }, art = { - "Jevonn", - "George the Rat", + "Lil. Mr. Slipstream", }, code = { "Jevonn", @@ -1545,12 +1999,13 @@ local waluigi = { soul_pos = { x = 1, y = 3 }, config = { extra = { Xmult = 2.5 } }, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.Xmult } } + return { vars = { number_format(center.ability.extra.Xmult) } } end, rarity = 4, cost = 20, order = 87, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) if context.other_joker and context.other_joker.ability.set == "Joker" then if not Talisman.config_file.disable_anims then @@ -1562,8 +2017,22 @@ local waluigi = { })) end return { - message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.Xmult } }), - Xmult_mod = card.ability.extra.Xmult, + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), + } + end + if context.forcetrigger then + return { + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), } end end, @@ -1573,6 +2042,7 @@ local waluigi = { "HexaCryonic", }, art = { + "MarioFan597", "HexaCryonic", }, code = { @@ -1593,14 +2063,21 @@ local wario = { pos = { x = 2, y = 3 }, soul_pos = { x = 3, y = 3 }, config = { extra = { money = 3 } }, + demicoloncompat = true, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.money } } + return { vars = { number_format(center.ability.extra.money) } } end, calculate = function(self, card, context) - if context.post_trigger then + if + ( + context.post_trigger + and not context.other_context.fixed_probability + and not context.other_context.mod_probability + ) or context.forcetrigger + then return { - dollars = card.ability.extra.money, - card = context.other_context.blueprint_card or context.other_card, + dollars = lenient_bignum(card.ability.extra.money), + card = context.other_context and context.other_context.blueprint_card or context.other_card or nil, -- This function isn't working properly :sob: --[[func = function() G.E_MANAGER:add_event(Event({ @@ -1636,36 +2113,62 @@ local krustytheclown = { object_type = "Joker", dependencies = { items = { - "set_cry_misc_joker", + "set_cry_meme", }, }, name = "cry-krustytheclown", key = "krustytheclown", pos = { x = 3, y = 4 }, - config = { extra = { extra = 0.02, x_mult = 1 } }, + config = { + extra = { + extra = 0.02, + x_mult = 1, + }, + }, pools = { ["Meme"] = true }, rarity = 2, order = 31, cost = 7, perishable_compat = false, blueprint_compat = true, + demicoloncompat = true, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.extra, center.ability.extra.x_mult } } + return { + vars = { + number_format(center.ability.extra.extra), + number_format(center.ability.extra.x_mult), + }, + } end, atlas = "atlasone", calculate = function(self, card, context) if context.joker_main and (to_big(card.ability.extra.x_mult) > to_big(1)) then return { - message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.x_mult } }), - Xmult_mod = card.ability.extra.x_mult, + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.x_mult) }, + }), + Xmult_mod = lenient_bignum(card.ability.extra.x_mult), } end if context.cardarea == G.play and context.individual and not context.blueprint then - card.ability.extra.x_mult = card.ability.extra.x_mult + card.ability.extra.extra + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "x_mult", + scalar_value = "extra", + }) + end + if context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "x_mult", + scalar_value = "extra", + message_key = "a_xmult", + message_colour = G.C.RED, + }) return { - extra = { focus = card, message = localize("k_upgrade_ex") }, - card = card, - colour = G.C.MULT, + Xmult_mod = lenient_bignum(card.ability.extra.x_mult), } end end, @@ -1685,35 +2188,53 @@ local blurred = { object_type = "Joker", dependencies = { items = { - "set_cry_misc_joker", + "set_cry_meme", }, }, name = "cry-blurred Joker", key = "blurred", pos = { x = 4, y = 4 }, pools = { ["Meme"] = true }, - config = { extra = 1 }, + config = { + extra = { extra_hands = 1 }, + immutable = { max_hand_size_mod = 1000 }, + }, rarity = 1, cost = 4, order = 51, blueprint_compat = true, + demicoloncompat = true, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra } } + local aaa + if next(SMODS.find_mod("sdm0sstuff")) then + if G.localization.descriptions.Other.blurred_sdm0 then + aaa = {} + localize({ type = "other", key = "blurred_sdm0", nodes = aaa, vars = {} }) + aaa = aaa[1] + end + end + return { + vars = { math.min(center.ability.immutable.max_hand_size_mod, center.ability.extra.extra_hands) }, + main_end = aaa, + } end, atlas = "atlastwo", calculate = function(self, card, context) - if context.setting_blind and not (context.blueprint_card or card).getting_sliced then + if (context.setting_blind and not (context.blueprint_card or card).getting_sliced) or context.forcetrigger then G.E_MANAGER:add_event(Event({ func = function() - ease_hands_played(card.ability.extra) - card_eval_status_text( - context.blueprint_card or card, - "extra", - nil, - nil, - nil, - { message = localize({ type = "variable", key = "a_hands", vars = { card.ability.extra } }) } + ease_hands_played( + math.min(card.ability.immutable.max_hand_size_mod, card.ability.extra.extra_hands) ) + card_eval_status_text(context.blueprint_card or card, "extra", nil, nil, nil, { + message = localize({ + type = "variable", + key = "a_hands", + vars = { + math.min(card.ability.immutable.max_hand_size_mod, card.ability.extra.extra_hands), + }, + }), + }) return true end, })) @@ -1746,9 +2267,10 @@ local gardenfork = { cost = 7, order = 66, blueprint_compat = true, + demicoloncompat = true, atlas = "atlasone", loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.money } } + return { vars = { number_format(center.ability.extra.money) } } end, calculate = function(self, card, context) if context.cardarea == G.jokers and context.before and context.full_hand then @@ -1762,10 +2284,14 @@ local gardenfork = { end end if has_ace and has_7 then - ease_dollars(card.ability.extra.money) - return { message = "$" .. card.ability.extra.money, colour = G.C.MONEY } + ease_dollars(lenient_bignum(card.ability.extra.money)) + return { message = "$" .. number_format(card.ability.extra.money), colour = G.C.MONEY } end end + if context.forcetrigger then + ease_dollars(lenient_bignum(card.ability.extra.money)) + return { message = "$" .. number_format(card.ability.extra.money), colour = G.C.MONEY } + end end, cry_credits = { idea = { @@ -1789,26 +2315,39 @@ local lightupthenight = { name = "cry-lightupthenight", key = "lightupthenight", config = { extra = { xmult = 1.5 } }, + gameset_config = { + modest = { + cost = 9, + }, + }, pos = { x = 1, y = 1 }, atlas = "atlasone", rarity = 3, cost = 7, order = 67, blueprint_compat = true, + demicoloncompat = true, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.xmult } } + return { vars = { number_format(center.ability.extra.xmult) } } end, calculate = function(self, card, context) if context.cardarea == G.play and context.individual then local rank = context.other_card:get_id() if rank == 2 or rank == 7 then return { - x_mult = card.ability.extra.xmult, + x_mult = lenient_bignum(card.ability.extra.xmult), colour = G.C.RED, card = card, } end end + if context.forcetrigger then + return { + x_mult = lenient_bignum(card.ability.extra.xmult), + colour = G.C.RED, + card = card, + } + end end, cry_credits = { idea = { @@ -1831,7 +2370,10 @@ local nosound = { }, name = "cry-nosound", key = "nosound", - config = { extra = { retriggers = 3 } }, + config = { + extra = { retriggers = 3 }, + immutable = { max_retriggers = 40 }, + }, pos = { x = 2, y = 1 }, atlas = "atlasone", rarity = 3, @@ -1839,7 +2381,7 @@ local nosound = { cost = 7, blueprint_compat = true, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.retriggers } } + return { vars = { math.min(center.ability.immutable.max_retriggers, center.ability.extra.retriggers) } } end, calculate = function(self, card, context) if context.repetition then @@ -1847,7 +2389,9 @@ local nosound = { if context.other_card:get_id() == 7 then return { message = localize("k_again_ex"), - repetitions = card.ability.extra.retriggers, + repetitions = to_number( + math.min(card.ability.immutable.max_retriggers, card.ability.extra.retriggers) + ), card = card, } end @@ -1876,14 +2420,25 @@ local antennastoheaven = { name = "cry-antennastoheaven", key = "antennastoheaven", pos = { x = 3, y = 1 }, - config = { extra = { bonus = 0.1, x_chips = 1 } }, + config = { + extra = { + bonus = 0.1, + x_chips = 1, + }, + }, rarity = 3, cost = 7, order = 69, perishable_compat = false, blueprint_compat = true, + demicoloncompat = true, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.bonus, center.ability.extra.x_chips } } + return { + vars = { + number_format(center.ability.extra.bonus), + number_format(center.ability.extra.x_chips), + }, + } end, atlas = "atlasone", calculate = function(self, card, context) @@ -1894,21 +2449,32 @@ local antennastoheaven = { key = "a_xchips", vars = { number_format(card.ability.extra.x_chips) }, }), - Xchip_mod = card.ability.extra.x_chips, + Xchip_mod = lenient_bignum(card.ability.extra.x_chips), colour = G.C.CHIPS, } end if context.cardarea == G.play and context.individual and not context.blueprint then local rank = context.other_card:get_id() if rank == 4 or rank == 7 then - card.ability.extra.x_chips = card.ability.extra.x_chips + card.ability.extra.bonus - return { - extra = { focus = card, message = localize("k_upgrade_ex") }, - card = card, - colour = G.C.CHIPS, - } + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "x_chips", + scalar_value = "bonus", + }) end end + if context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "x_chips", + scalar_value = "bonus", + message_key = "a_xchips", + message_colour = G.C.CHIPS, + }) + return { + Xchip_mod = lenient_bignum(card.ability.extra.x_chips), + } + end end, cry_credits = { idea = { @@ -1941,12 +2507,14 @@ local hunger = { cost = 6, order = 80, blueprint_compat = true, + demicoloncompat = true, atlas = "atlastwo", loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.money } } + return { vars = { number_format(center.ability.extra.money) } } end, calculate = function(self, card, context) -- haha one liner - return context.using_consumeable and { p_dollars = card.ability.extra.money } + return (context.using_consumeable or context.forcetrigger) + and { p_dollars = lenient_bignum(card.ability.extra.money) } end, cry_credits = { idea = { @@ -1970,14 +2538,17 @@ local weegaming = { name = "cry-weegaming", key = "weegaming", order = 62, - config = { extra = { retriggers = 2 } }, + config = { + extra = { retriggers = 2 }, + immutable = { max_retriggers = 25 }, + }, pos = { x = 3, y = 4 }, atlas = "atlastwo", rarity = 1, cost = 5, blueprint_compat = true, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.retriggers } } + return { vars = { math.min(center.ability.immutable.max_retriggers, center.ability.extra.retriggers) } } end, calculate = function(self, card, context) if context.repetition then @@ -1985,7 +2556,9 @@ local weegaming = { if context.other_card:get_id() == 2 then return { message = localize("k_again_ex"), - repetitions = card.ability.extra.retriggers, + repetitions = to_number( + math.min(card.ability.immutable.max_retriggers, card.ability.extra.retriggers) + ), card = card, } end @@ -2013,7 +2586,20 @@ local redbloon = { }, name = "cry-redbloon", key = "redbloon", - config = { extra = { money = 20, rounds_remaining = 2 } }, + config = { + extra = { + money = 20, + rounds_remaining = 2, + }, + }, + gameset_config = { + modest = { + extra = { + money = 20, + rounds_remaining = 3, + }, + }, + }, pos = { x = 5, y = 1 }, rarity = 1, cost = 4, @@ -2021,9 +2607,15 @@ local redbloon = { blueprint_compat = false, eternal_compat = false, perishable_compat = false, + demicoloncompat = true, atlas = "atlasone", loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.money, center.ability.extra.rounds_remaining } } + return { + vars = { + number_format(center.ability.extra.money), + number_format(center.ability.extra.rounds_remaining), + }, + } end, calculate = function(self, card, context) if @@ -2033,14 +2625,14 @@ local redbloon = { and not context.repetition and not context.retrigger_joker then - card.ability.extra.rounds_remaining = card.ability.extra.rounds_remaining - 1 - if card.ability.extra.rounds_remaining > 0 then + card.ability.extra.rounds_remaining = lenient_bignum(to_big(card.ability.extra.rounds_remaining) - 1) + if to_big(card.ability.extra.rounds_remaining) > to_big(0) then return { message = { localize("cry_minus_round") }, colour = G.C.FILTER, } else - ease_dollars(card.ability.extra.money) + ease_dollars(lenient_bignum(card.ability.extra.money)) G.E_MANAGER:add_event(Event({ func = function() play_sound("tarot1") @@ -2063,11 +2655,39 @@ local redbloon = { end, })) return { - message = "$" .. card.ability.extra.money, + message = "$" .. number_format(card.ability.extra.money), colour = G.C.MONEY, } end end + if context.forcetrigger then + ease_dollars(lenient_bignum(card.ability.extra.money)) + G.E_MANAGER:add_event(Event({ + func = function() + play_sound("tarot1") + card.T.r = -0.2 + card:juice_up(0.3, 0.4) + card.states.drag.is = true + card.children.center.pinch.x = true + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.3, + blockable = false, + func = function() + G.jokers:remove_card(card) + card:remove() + card = nil + return true + end, + })) + return true + end, + })) + return { + message = "$" .. number_format(card.ability.extra.money), + colour = G.C.MONEY, + } + end end, cry_credits = { idea = { @@ -2097,15 +2717,20 @@ local apjoker = { order = 37, blueprint_compat = true, perishable_compat = false, + demicoloncompat = true, atlas = "atlasone", loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.x_mult } } + return { vars = { number_format(center.ability.extra.x_mult) } } end, calculate = function(self, card, context) - if context.joker_main and G.GAME.blind.boss then + if (context.joker_main and G.GAME.blind.boss) or context.forcetrigger then return { - message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.x_mult } }), - Xmult_mod = card.ability.extra.x_mult, + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.x_mult) }, + }), + Xmult_mod = lenient_bignum(card.ability.extra.x_mult), } end end, @@ -2114,7 +2739,7 @@ local apjoker = { "HexaCryonic", }, art = { - "HexaCryonic", + "unexian", }, code = { "Jevonn", @@ -2136,24 +2761,6 @@ local maze = { order = 61, immutable = true, atlas = "atlastwo", - update = function(self, card, dt) - if G.STAGE == G.STAGES.RUN then - if G.GAME.current_round.hands_played > 0 then - G.GAME.current_round.hands_played = 0 - end - if G.GAME.current_round.discards_used > 0 then - G.GAME.current_round.discards_used = 0 - end - end - end, - add_to_deck = function(self, card, from_debuff) - if G.GAME.current_round.hands_played > 0 then - G.GAME.current_round.hands_played = 0 - end - if G.GAME.current_round.discards_used > 0 then - G.GAME.current_round.discards_used = 0 - end - end, cry_credits = { idea = { "zy-b-org", @@ -2224,20 +2831,47 @@ local magnet = { key = "magnet", pos = { x = 4, y = 0 }, pixel_size = { w = 35, h = 35 }, - config = { extra = { money = 2, Xmoney = 5, slots = 4 } }, + config = { + extra = { + money = 2, + Xmoney = 5, + slots = 4, + }, + }, + gameset_config = { + modest = { + extra = { + money = 2, + Xmoney = 3, + slots = 3, + }, + }, + }, rarity = 1, cost = 6, order = 96, blueprint_compat = false, + demicoloncompat = true, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.money, center.ability.extra.Xmoney, center.ability.extra.slots } } + return { + vars = { + number_format(center.ability.extra.money), + number_format(center.ability.extra.Xmoney), + number_format(center.ability.extra.slots), + }, + } end, atlas = "atlastwo", + calculate = function(self, card, context) + if context.forcetrigger then + ease_dollars(lenient_bignum(to_big(card.ability.extra.money) * card.ability.extra.Xmoney)) + end + end, calc_dollar_bonus = function(self, card) - if #G.jokers.cards <= card.ability.extra.slots then - return card.ability.extra.money * card.ability.extra.Xmoney + if to_big(#G.jokers.cards) <= to_big(card.ability.extra.slots) then + return lenient_bignum(to_big(card.ability.extra.money) * card.ability.extra.Xmoney) else - return card.ability.extra.money + return lenient_bignum(card.ability.extra.money) end end, cry_credits = { @@ -2267,16 +2901,21 @@ local unjust_dagger = { cost = 8, order = 102, perishable_compat = false, + demicoloncompat = true, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.x_mult } } + return { vars = { number_format(center.ability.extra.x_mult) } } end, atlas = "atlasone", blueprint_compat = true, calculate = function(self, card, context) - if context.joker_main and (card.ability.extra.x_mult > 1) then + if context.joker_main and (to_big(card.ability.extra.x_mult) > to_big(1)) then return { - message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.x_mult } }), - Xmult_mod = card.ability.extra.x_mult, + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.x_mult) }, + }), + Xmult_mod = lenient_bignum(card.ability.extra.x_mult), } end local my_pos = nil @@ -2291,7 +2930,7 @@ local unjust_dagger = { and not (context.blueprint_card or self).getting_sliced and my_pos and G.jokers.cards[my_pos - 1] - and not G.jokers.cards[my_pos - 1].ability.eternal + and not SMODS.is_eternal(G.jokers.cards[my_pos - 1]) and not G.jokers.cards[my_pos - 1].getting_sliced then local sliced_card = G.jokers.cards[my_pos - 1] @@ -2303,24 +2942,58 @@ local unjust_dagger = { G.E_MANAGER:add_event(Event({ func = function() G.GAME.joker_buffer = 0 - card.ability.extra.x_mult = card.ability.extra.x_mult + sliced_card.sell_cost * 0.2 + card.ability.extra.x_mult = + lenient_bignum(to_big(card.ability.extra.x_mult) + sliced_card.sell_cost * 0.2) card:juice_up(0.8, 0.8) sliced_card:start_dissolve({ HEX("57ecab") }, nil, 1.6) play_sound("slice1", 0.96 + math.random() * 0.08) return true end, })) - card_eval_status_text(card, "extra", nil, nil, nil, { - message = localize({ - type = "variable", - key = "a_xmult", - vars = { card.ability.extra.x_mult + 0.2 * sliced_card.sell_cost }, - }), - colour = G.C.RED, - no_juice = true, + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "x_mult", + scalar_table = { + sell_cost = sliced_card.sell_cost * 0.2, + }, + scalar_value = "sell_cost", + message_key = "a_xmult", + message_colour = G.C.RED, }) return nil, true end + if context.forcetrigger and my_pos and G.jokers.cards[my_pos - 1] then + local sliced_card = G.jokers.cards[my_pos - 1] + sliced_card.getting_sliced = true + if sliced_card.config.center.rarity == "cry_exotic" then + check_for_unlock({ type = "what_have_you_done" }) + end + G.GAME.joker_buffer = G.GAME.joker_buffer - 1 + G.E_MANAGER:add_event(Event({ + func = function() + G.GAME.joker_buffer = 0 + card.ability.extra.x_mult = + lenient_bignum(to_big(card.ability.extra.x_mult) + sliced_card.sell_cost * 0.2) + card:juice_up(0.8, 0.8) + sliced_card:start_dissolve({ HEX("57ecab") }, nil, 1.6) + play_sound("slice1", 0.96 + math.random() * 0.08) + return true + end, + })) + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "x_mult", + scalar_table = { + sell_cost = sliced_card.sell_cost * 0.2, + }, + scalar_value = "sell_cost", + message_key = "a_xmult", + message_colour = G.C.RED, + }) + return { + Xmult_mod = lenient_bignum(card.ability.extra.x_mult), + } + end end, cry_credits = { idea = { @@ -2350,15 +3023,20 @@ local monkey_dagger = { order = 49, perishable_compat = false, blueprint_compat = true, + demicoloncompat = true, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.chips } } + return { vars = { number_format(center.ability.extra.chips) } } end, atlas = "atlastwo", calculate = function(self, card, context) if context.joker_main and (to_big(card.ability.extra.chips) > to_big(0)) then return { - message = localize({ type = "variable", key = "a_chips", vars = { card.ability.extra.chips } }), - chip_mod = card.ability.extra.chips, + message = localize({ + type = "variable", + key = "a_chips", + vars = { number_format(card.ability.extra.chips) }, + }), + chip_mod = lenient_bignum(card.ability.extra.chips), } end local my_pos = nil @@ -2373,7 +3051,7 @@ local monkey_dagger = { and not (context.blueprint_card or self).getting_sliced and my_pos and G.jokers.cards[my_pos - 1] - and not G.jokers.cards[my_pos - 1].ability.eternal + and not SMODS.is_eternal(G.jokers.cards[my_pos - 1]) and not G.jokers.cards[my_pos - 1].getting_sliced then local sliced_card = G.jokers.cards[my_pos - 1] @@ -2385,24 +3063,71 @@ local monkey_dagger = { G.E_MANAGER:add_event(Event({ func = function() G.GAME.joker_buffer = 0 - card.ability.extra.chips = card.ability.extra.chips + sliced_card.sell_cost * 10 + card.ability.extra.chips = + lenient_bignum(to_big(card.ability.extra.chips) + sliced_card.sell_cost * 10) card:juice_up(0.8, 0.8) sliced_card:start_dissolve({ HEX("57ecab") }, nil, 1.6) play_sound("slice1", 0.96 + math.random() * 0.08) return true end, })) - card_eval_status_text(card, "extra", nil, nil, nil, { - message = localize({ - type = "variable", - key = "a_chips", - vars = { card.ability.extra.chips + 10 * sliced_card.sell_cost }, - }), - colour = G.C.CHIPS, - no_juice = true, + local msg = SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "x_mult", + scalar_table = { + sell_cost = sliced_card.sell_cost * 10, + }, + scalar_value = "sell_cost", }) + if not msg or type(msg) == "string" then + card_eval_status_text(card, "extra", nil, nil, nil, { + message = msg or localize({ + type = "variable", + key = "a_chips", + vars = { + number_format( + lenient_bignum(to_big(card.ability.extra.chips) + 10 * sliced_card.sell_cost) + ), + }, + }), + colour = G.C.CHIPS, + no_juice = true, + }) + end return nil, true end + if context.forcetrigger and my_pos and G.jokers.cards[my_pos - 1] then + local sliced_card = G.jokers.cards[my_pos - 1] + sliced_card.getting_sliced = true + if sliced_card.config.center.rarity == "cry_exotic" then + check_for_unlock({ type = "what_have_you_done" }) + end + G.GAME.joker_buffer = G.GAME.joker_buffer - 1 + G.E_MANAGER:add_event(Event({ + func = function() + G.GAME.joker_buffer = 0 + card.ability.extra.chips = + lenient_bignum(to_big(card.ability.extra.chips) + sliced_card.sell_cost * 10) + card:juice_up(0.8, 0.8) + sliced_card:start_dissolve({ HEX("57ecab") }, nil, 1.6) + play_sound("slice1", 0.96 + math.random() * 0.08) + return true + end, + })) + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "chips", + scalar_table = { + sell_cost = sliced_card.sell_cost * 10, + }, + scalar_value = "sell_cost", + message_key = "a_chips", + message_colour = G.C.BLUE, + }) + return { + chip_mod = lenient_bignum(card.ability.extra.chips), + } + end end, cry_credits = { idea = { @@ -2432,15 +3157,20 @@ local pirate_dagger = { order = 103, perishable_compat = false, blueprint_compat = true, + demicoloncompat = true, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.x_chips } } + return { vars = { number_format(center.ability.extra.x_chips) } } end, atlas = "atlastwo", calculate = function(self, card, context) - if context.joker_main and (card.ability.extra.x_chips > 1) then + if context.joker_main and (to_big(card.ability.extra.x_chips) > to_big(1)) then return { - message = localize({ type = "variable", key = "a_xchips", vars = { card.ability.extra.x_chips } }), - Xchip_mod = card.ability.extra.x_chips, + message = localize({ + type = "variable", + key = "a_xchips", + vars = { number_format(card.ability.extra.x_chips) }, + }), + Xchip_mod = lenient_bignum(card.ability.extra.x_chips), } end local my_pos = nil @@ -2455,7 +3185,7 @@ local pirate_dagger = { and not (context.blueprint_card or self).getting_sliced and my_pos and G.jokers.cards[my_pos + 1] - and not G.jokers.cards[my_pos + 1].ability.eternal + and not SMODS.is_eternal(G.jokers.cards[my_pos + 1]) and not G.jokers.cards[my_pos + 1].getting_sliced then local sliced_card = G.jokers.cards[my_pos + 1] @@ -2467,24 +3197,58 @@ local pirate_dagger = { G.E_MANAGER:add_event(Event({ func = function() G.GAME.joker_buffer = 0 - card.ability.extra.x_chips = card.ability.extra.x_chips + sliced_card.sell_cost * 0.25 + card.ability.extra.x_chips = + lenient_bignum(to_big(card.ability.extra.x_chips) + sliced_card.sell_cost * 0.25) card:juice_up(0.8, 0.8) sliced_card:start_dissolve({ HEX("57ecab") }, nil, 1.6) play_sound("slice1", 0.96 + math.random() * 0.08) return true end, })) - card_eval_status_text(card, "extra", nil, nil, nil, { - message = localize({ - type = "variable", - key = "a_xchips", - vars = { card.ability.extra.x_chips + 0.25 * sliced_card.sell_cost }, - }), - colour = G.C.CHIPS, - no_juice = true, + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "x_chips", + scalar_table = { + sell_cost = sliced_card.sell_cost * 0.25, + }, + scalar_value = "sell_cost", + message_key = "a_xchips", + message_colour = G.C.BLUE, }) return nil, true end + if context.forcetrigger and my_pos and G.jokers.cards[my_pos + 1] then + local sliced_card = G.jokers.cards[my_pos + 1] + sliced_card.getting_sliced = true + if sliced_card.config.center.rarity == "cry_exotic" then + check_for_unlock({ type = "what_have_you_done" }) + end + G.GAME.joker_buffer = G.GAME.joker_buffer - 1 + G.E_MANAGER:add_event(Event({ + func = function() + G.GAME.joker_buffer = 0 + card.ability.extra.x_chips = + lenient_bignum(to_big(card.ability.extra.x_chips) + sliced_card.sell_cost * 0.25) + card:juice_up(0.8, 0.8) + sliced_card:start_dissolve({ HEX("57ecab") }, nil, 1.6) + play_sound("slice1", 0.96 + math.random() * 0.08) + return true + end, + })) + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "x_chips", + scalar_table = { + sell_cost = sliced_card.sell_cost * 0.25, + }, + scalar_value = "sell_cost", + message_key = "a_xchips", + message_colour = G.C.BLUE, + }) + return { + Xchip_mod = lenient_bignum(card.ability.extra.x_chips), + } + end end, cry_credits = { idea = { @@ -2508,21 +3272,36 @@ local mondrian = { name = "cry-mondrian", key = "mondrian", pos = { x = 5, y = 3 }, - config = { extra = { extra = 0.25, x_mult = 1 } }, + config = { + extra = { + extra = 0.25, + x_mult = 1, + }, + }, rarity = 2, cost = 7, order = 44, perishable_compat = false, blueprint_compat = true, + demicoloncompat = true, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.extra, center.ability.extra.x_mult } } + return { + vars = { + number_format(center.ability.extra.extra), + number_format(center.ability.extra.x_mult), + }, + } end, atlas = "atlastwo", calculate = function(self, card, context) if context.joker_main and (to_big(card.ability.extra.x_mult) > to_big(1)) then return { - message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.x_mult } }), - Xmult_mod = card.ability.extra.x_mult, + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.x_mult) }, + }), + Xmult_mod = lenient_bignum(card.ability.extra.x_mult), } end if @@ -2532,10 +3311,22 @@ local mondrian = { and not context.individual and not context.repetition then - card.ability.extra.x_mult = card.ability.extra.x_mult + card.ability.extra.extra + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "x_mult", + scalar_value = "extra", + }) + end + if context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "x_mult", + scalar_value = "extra", + message_key = "a_xmult", + message_colour = G.C.RED, + }) return { - message = localize("k_upgrade_ex"), - card = card, + Xmult_mod = lenient_bignum(card.ability.extra.x_mult), } end end, @@ -2561,17 +3352,24 @@ local sapling = { name = "cry-sapling", key = "sapling", pos = { x = 3, y = 2 }, --todo animations - config = { extra = { score = 0, req = 18, check = nil } }, + config = { + extra = { + req = 18, + check = nil, + }, + immutable = { score = 0 }, + }, rarity = 2, cost = 6, order = 42, blueprint_compat = false, eternal_compat = false, + demicoloncompat = true, loc_vars = function(self, info_queue, center) return { vars = { - center.ability.extra.score, - center.ability.extra.req, + number_format(center.ability.immutable.score), + number_format(center.ability.extra.req), Cryptid.enabled("set_cry_epic") == true and localize("k_cry_epic") or localize("k_rare"), colours = { G.C.RARITY[Cryptid.enabled("set_cry_epic") == true and "cry_epic" or 3] }, Cryptid.enabled("set_cry_epic") == true and localize("cry_sapling_an") or localize("cry_sapling_a"), @@ -2587,8 +3385,11 @@ local sapling = { and not context.retrigger_joker then if context.other_card.ability.effect ~= "Base" then - card.ability.extra.score = card.ability.extra.score + 1 - if card.ability.extra.score >= card.ability.extra.req and not card.ability.extra.check then + card.ability.immutable.score = lenient_bignum(card.ability.immutable.score + 1) + if + to_big(card.ability.immutable.score) >= to_big(card.ability.extra.req) + and not card.ability.extra.check + then card.ability.extra.check = true --Prevents violent juice up spam when playing enchanced cards while already active local eval = function(card) return not card.REMOVED @@ -2597,7 +3398,7 @@ local sapling = { end end elseif context.selling_self and not context.blueprint and not context.retrigger_joker then - if card.ability.extra.score >= card.ability.extra.req then + if to_big(card.ability.immutable.score) >= to_big(card.ability.extra.req) then local value = Cryptid.enabled("set_cry_epic") == true and "cry_epic" or 0.99 card_eval_status_text( card, @@ -2623,6 +3424,22 @@ local sapling = { ) end end + if context.forcetrigger then + card.ability.immutable.score = lenient_bignum(card.ability.immutable.score + 1) + local value = Cryptid.enabled("set_cry_epic") == true and "cry_epic" or 0.99 + card_eval_status_text( + card, + "extra", + nil, + nil, + nil, + { message = localize("k_plus_joker"), colour = G.C.RARITY["cry_epic"] } + ) + local card = create_card("Joker", G.jokers, nil, value, nil, nil, nil, "cry_sapling") + card:add_to_deck() + G.jokers:emplace(card) + card:start_materialize() + end end, cry_credits = { idea = { @@ -2647,17 +3464,24 @@ local spaceglobe = { name = "cry-spaceglobe", key = "spaceglobe", pos = { x = 1, y = 4 }, - config = { extra = { x_chips = 1, Xchipmod = 0.2, type = "High Card" } }, + config = { + extra = { + x_chips = 1, + Xchipmod = 0.2, + type = "High Card", + }, + }, rarity = 3, cost = 8, order = 73, blueprint_compat = true, perishable_compat = false, + demicoloncompat = true, loc_vars = function(self, info_queue, center) return { vars = { - center.ability.extra.x_chips, - center.ability.extra.Xchipmod, + number_format(center.ability.extra.x_chips), + number_format(center.ability.extra.Xchipmod), localize(center.ability.extra.type, "poker_hands"), }, } @@ -2670,7 +3494,12 @@ local spaceglobe = { _poker_hands[#_poker_hands + 1] = k end end - card.ability.extra.type = pseudorandom_element(_poker_hands, pseudoseed("cry_space_globe")) + card.ability.extra.type = pseudorandom_element( + _poker_hands, + pseudoseed( + (card.area and card.area.config.type == "title") and "false_cry_space_globe" or "cry_space_globe" + ) + ) end, calculate = function(self, card, context) if context.cardarea == G.jokers and context.before and not context.blueprint then @@ -2687,12 +3516,11 @@ local spaceglobe = { return true end, })) - card.ability.extra.x_chips = card.ability.extra.x_chips + card.ability.extra.Xchipmod - return { - message = localize("k_upgrade_ex"), - card = card, - colour = G.C.CHIPS, - } + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "x_chips", + scalar_value = "Xchipmod", + }) end end if context.joker_main and (to_big(card.ability.extra.x_chips) > to_big(1)) then @@ -2702,10 +3530,22 @@ local spaceglobe = { key = "a_xchips", vars = { number_format(card.ability.extra.x_chips) }, }), - Xchip_mod = card.ability.extra.x_chips, + Xchip_mod = lenient_bignum(card.ability.extra.x_chips), colour = G.C.CHIPS, } end + if context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "x_chips", + scalar_value = "Xchipmod", + message_key = "a_xchips", + message_colour = G.C.BLUE, + }) + return { + Xchip_mod = lenient_bignum(card.ability.extra.x_chips), + } + end end, cry_credits = { idea = { @@ -2731,10 +3571,16 @@ local happy = { pos = { x = 2, y = 1 }, rarity = 1, cost = 2, + gameset_config = { + modest = { + cost = 5, + }, + }, order = 63, immutable = true, blueprint_compat = true, eternal_compat = false, + demicoloncompat = true, atlas = "atlastwo", calculate = function(self, card, context) if context.selling_self and #G.jokers.cards + G.GAME.joker_buffer <= G.jokers.config.card_limit then @@ -2792,6 +3638,22 @@ local happy = { ) return nil, true end + if context.forcetrigger then + local roundcreatejoker = math.min(1, G.jokers.config.card_limit - (#G.jokers.cards + G.GAME.joker_buffer)) + G.GAME.joker_buffer = G.GAME.joker_buffer + roundcreatejoker + G.E_MANAGER:add_event(Event({ + func = function() + if roundcreatejoker > 0 then + local card = create_card("Joker", G.jokers, nil, nil, nil, nil, nil, "happy") + card:add_to_deck() + G.jokers:emplace(card) + card:start_materialize() + G.GAME.joker_buffer = 0 + end + return true + end, + })) + end end, cry_credits = { idea = { @@ -2820,12 +3682,13 @@ local meteor = { if not center.edition or (center.edition and not center.edition.foil) then info_queue[#info_queue + 1] = G.P_CENTERS.e_foil end - return { vars = { center.ability.extra.chips } } + return { vars = { number_format(center.ability.extra.chips) } } end, rarity = 1, cost = 4, order = 38, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) if context.other_joker @@ -2842,14 +3705,18 @@ local meteor = { })) end return { - message = localize({ type = "variable", key = "a_chips", vars = { card.ability.extra.chips } }), - chip_mod = card.ability.extra.chips, + message = localize({ + type = "variable", + key = "a_chips", + vars = { number_format(card.ability.extra.chips) }, + }), + chip_mod = lenient_bignum(card.ability.extra.chips), } end if context.individual and context.cardarea == G.play then if context.other_card.edition and context.other_card.edition.foil == true then return { - chips = card.ability.extra.chips, + chips = lenient_bignum(card.ability.extra.chips), colour = G.C.CHIPS, card = card, } @@ -2870,11 +3737,18 @@ local meteor = { } else return { - chips = card.ability.extra.chips, --this doesn't exist yet :pensive: if only... + chips = lenient_bignum(card.ability.extra.chips), --this doesn't exist yet :pensive: if only... card = card, } end end + if context.forcetrigger then + return { + chips = lenient_bignum(card.ability.extra.chips), + colour = G.C.CHIPS, + card = card, + } + end end, atlas = "atlastwo", cry_credits = { @@ -2904,12 +3778,13 @@ local exoplanet = { if not center.edition or (center.edition and not center.edition.holo) then info_queue[#info_queue + 1] = G.P_CENTERS.e_holo end - return { vars = { center.ability.extra.mult } } + return { vars = { number_format(center.ability.extra.mult) } } end, rarity = 1, order = 39, cost = 3, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) if context.other_joker @@ -2926,14 +3801,18 @@ local exoplanet = { })) end return { - message = localize({ type = "variable", key = "a_mult", vars = { card.ability.extra.mult } }), - mult_mod = card.ability.extra.mult, + message = localize({ + type = "variable", + key = "a_mult", + vars = { number_format(card.ability.extra.mult) }, + }), + mult_mod = lenient_bignum(card.ability.extra.mult), } end if context.individual and context.cardarea == G.play then if context.other_card.edition and context.other_card.edition.holo == true then return { - mult = card.ability.extra.mult, + mult = lenient_bignum(card.ability.extra.mult), colour = G.C.MULT, card = card, } @@ -2954,11 +3833,18 @@ local exoplanet = { } else return { - h_mult = card.ability.extra.mult, + h_mult = lenient_bignum(card.ability.extra.mult), card = card, } end end + if context.forcetrigger then + return { + mult = lenient_bignum(card.ability.extra.mult), + colour = G.C.MULT, + card = card, + } + end end, atlas = "atlastwo", cry_credits = { @@ -2988,12 +3874,13 @@ local stardust = { if not center.edition or (center.edition and not center.edition.polychrome) then info_queue[#info_queue + 1] = G.P_CENTERS.e_polychrome end - return { vars = { center.ability.extra.xmult } } + return { vars = { number_format(center.ability.extra.xmult) } } end, rarity = 1, cost = 2, order = 40, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) if context.other_joker @@ -3010,14 +3897,18 @@ local stardust = { })) end return { - message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.xmult } }), - Xmult_mod = card.ability.extra.xmult, + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.xmult) }, + }), + Xmult_mod = lenient_bignum(card.ability.extra.xmult), } end if context.individual and context.cardarea == G.play then if context.other_card.edition and context.other_card.edition.polychrome == true then return { - x_mult = card.ability.extra.xmult, + x_mult = lenient_bignum(card.ability.extra.xmult), colour = G.C.MULT, card = card, } @@ -3038,11 +3929,18 @@ local stardust = { } else return { - x_mult = card.ability.extra.xmult, + x_mult = lenient_bignum(card.ability.extra.xmult), card = card, } end end + if context.forcetrigger then + return { + x_mult = lenient_bignum(card.ability.extra.xmult), + colour = G.C.MULT, + card = card, + } + end end, atlas = "atlastwo", cry_credits = { @@ -3070,6 +3968,7 @@ local rnjoker = { config = {}, order = 59, loc_vars = function(self, info_queue, card) + local num, denom = SMODS.get_probability_vars(card, 1, card and card.ability.extra.cond_value or 0, "RNJoker") local vars = { vars = { (card.ability.extra and card.ability.extra.value_mod and card.ability.extra.value) or 0, @@ -3077,11 +3976,7 @@ local rnjoker = { or (card.ability.extra and card.ability.extra.value) or 0, card.ability.extra and card.ability.extra.cond_value or 0, - cry_prob( - card.ability.cry_prob, - card.ability.extra and card.ability.extra.cond_value or 0, - card.ability.cry_rigged - ), + num, }, } if card.ability.extra and card.ability.extra.color then @@ -3092,6 +3987,7 @@ local rnjoker = { rarity = 2, cost = 6, blueprint_compat = true, + immutable = true, set_ability = function(self, card, initial, delay_sprites) card.ability.abilities = {} Cryptid.rnjoker_randomize(card) @@ -3112,9 +4008,6 @@ local rnjoker = { if (j_context == "setting_blind") and card.getting_sliced then valid_context = false end - if (j_context == "setting_blind") and card.getting_sliced then - valid_context = false - end if (j_context == "before") and (card.area ~= G.jokers) then valid_context = false end @@ -3164,6 +4057,9 @@ local rnjoker = { if valid_context then local cond_passed = false local times_passed = 1 + if j_context == "playing_card_added" and context.cards and context.cards[1] then + times_passed = #context.cards + end if j.cond then if j.cond == "buy_common" then if @@ -3312,17 +4208,38 @@ local rnjoker = { cond_passed = true end elseif j.cond == "odds" then - if - pseudorandom("rnj") - < ( - cry_prob( - card.ability.cry_prob, - card.ability.extra.cond_value, - card.ability.cry_rigged - ) / card.ability.extra.cond_value - ) - then - cond_passed = true + if j_context == "playing_card_added" and context.cards and context.cards[1] then + for i = 1, #context.cards do + if + SMODS.pseudorandom_probability( + card, + "rnj", + 1, + card and card.ability.extra.cond_value or 0, + "RNJoker" + ) + then + else + times_passed = math.max(0, times_passed - 1) + end + end + if times_passed == 0 then + cond_passed = false + else + cond_passed = true + end + else + if + SMODS.pseudorandom_probability( + card, + "rnj", + 1, + card and card.ability.extra.cond_value or 0, + "RNJoker" + ) + then + cond_passed = true + end end end else @@ -3602,13 +4519,12 @@ local rnjoker = { end elseif j.cond == "odds" then if - pseudorandom("rnj") - < ( - cry_prob( - card.ability.cry_prob, - card.ability.extra.cond_value, - card.ability.cry_rigged - ) / card.ability.extra.cond_value + SMODS.pseudorandom_probability( + card, + "rnj", + 1, + card and card.ability.extra.cond_value or 0, + "RNJoker" ) then cond_passed = true @@ -3692,13 +4608,12 @@ local rnjoker = { end elseif j.cond == "odds" then if - pseudorandom("rnj") - < ( - cry_prob( - card.ability.cry_prob, - card.ability.extra.cond_value, - card.ability.cry_rigged - ) / card.ability.extra.cond_value + SMODS.pseudorandom_probability( + card, + "rnj", + 1, + card and card.ability.extra.cond_value or 0, + "RNJoker" ) then cond_passed = true @@ -3978,12 +4893,7 @@ local rnjoker = { "odds", } elseif context == "playing_card_added" then - conds = { - "suit", - "rank", - "face", - "odds", - } + conds = { "odds" } elseif context == "setting_blind" then conds = { "boss", @@ -4346,6 +5256,67 @@ local rnjoker = { end end, } +local filler = { + object_type = "Joker", + dependencies = { + items = { + "set_cry_misc_joker", + }, + }, + name = "cry-filler", + key = "filler", + pos = { x = 0, y = 1 }, + pools = { ["Meme"] = true }, + config = { + extra = { + Xmult = 1.00000000000003, + type = "High Card", + }, + }, + loc_vars = function(self, info_queue, card) + return { + vars = { + number_format(card.ability.extra.Xmult), + localize(card.ability.extra.type, "poker_hands"), + }, + } + end, + atlas = "atlasthree", + rarity = 3, + order = 89, + cost = 1, + blueprint_compat = true, + demicoloncompat = true, + calculate = function(self, card, context) + if + (context.joker_main and context.poker_hands and next(context.poker_hands[card.ability.extra.type])) + or context.forcetrigger + then + return { + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), + colour = G.C.RED, + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), + } + end + end, + cry_credits = { + idea = { + "Mathguy", + }, + art = { + "Mathguy", + }, + code = { + "Mathguy", + }, + }, + unlocked = false, + unlock_condition = { type = "win_no_hand", extra = "High Card" }, +} local duos = { object_type = "Joker", dependencies = { @@ -4357,27 +5328,53 @@ local duos = { key = "duos", order = 90, pos = { x = 0, y = 0 }, - config = { Xmult = 2.5, type = "Two Pair" }, + config = { + extra = { + Xmult = 2.5, + type = "Two Pair", + }, + }, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.x_mult, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.Xmult), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 3, cost = 8, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and (to_big(card.ability.x_mult) > to_big(1)) then + if context.joker_main and (to_big(card.ability.extra.Xmult) > to_big(1)) then if - context.poker_hands ~= nil and next(context.poker_hands[card.ability.type]) + context.poker_hands ~= nil and next(context.poker_hands[card.ability.extra.type]) or context.poker_hands ~= nil and next(context.poker_hands["Full House"]) then return { - message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.x_mult } }), + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), colour = G.C.RED, - Xmult_mod = card.ability.x_mult, + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), } end end + if context.forcetrigger then + return { + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), + colour = G.C.RED, + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), + } + end end, cry_credits = { idea = { @@ -4404,24 +5401,50 @@ local home = { key = "home", order = 91, pos = { x = 2, y = 0 }, - config = { Xmult = 3.5, type = "Full House" }, + config = { + extra = { + Xmult = 3.5, + type = "Full House", + }, + }, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.x_mult, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.Xmult), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 3, cost = 8, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and (to_big(card.ability.x_mult) > to_big(1)) then - if context.poker_hands ~= nil and next(context.poker_hands[card.ability.type]) then + if context.joker_main and (to_big(card.ability.extra.Xmult) > to_big(1)) then + if context.poker_hands ~= nil and next(context.poker_hands[card.ability.extra.type]) then return { - message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.x_mult } }), + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), colour = G.C.RED, - Xmult_mod = card.ability.x_mult, + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), } end end + if context.forcetrigger then + return { + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), + colour = G.C.RED, + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), + } + end end, cry_credits = { idea = { @@ -4448,24 +5471,50 @@ local nuts = { key = "nuts", order = 92, pos = { x = 1, y = 0 }, - config = { Xmult = 5, type = "Straight Flush" }, + config = { + extra = { + Xmult = 5, + type = "Straight Flush", + }, + }, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.x_mult, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.Xmult), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 3, cost = 8, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and (to_big(card.ability.x_mult) > to_big(1)) then - if context.poker_hands ~= nil and next(context.poker_hands[card.ability.type]) then + if context.joker_main and (to_big(card.ability.extra.Xmult) > to_big(1)) then + if context.poker_hands ~= nil and next(context.poker_hands[card.ability.extra.type]) then return { - message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.x_mult } }), + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), colour = G.C.RED, - Xmult_mod = card.ability.x_mult, + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), } end end + if context.forcetrigger then + return { + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), + colour = G.C.RED, + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), + } + end end, cry_credits = { idea = { @@ -4492,24 +5541,50 @@ local quintet = { key = "quintet", order = 93, pos = { x = 3, y = 0 }, - config = { Xmult = 5, type = "Five of a Kind" }, + config = { + extra = { + Xmult = 5, + type = "Five of a Kind", + }, + }, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.x_mult, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.Xmult), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 3, cost = 8, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and (to_big(card.ability.x_mult) > to_big(1)) then - if context.poker_hands ~= nil and next(context.poker_hands[card.ability.type]) then + if context.joker_main and (to_big(card.ability.extra.Xmult) > to_big(1)) then + if context.poker_hands ~= nil and next(context.poker_hands[card.ability.extra.type]) then return { - message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.x_mult } }), + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), colour = G.C.RED, - Xmult_mod = card.ability.x_mult, + Xmult_mod = number_format(card.ability.extra.Xmult), } end end + if context.forcetrigger then + return { + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), + colour = G.C.RED, + Xmult_mod = number_format(card.ability.extra.Xmult), + } + end end, in_pool = function(self) if G.GAME.hands["Five of a Kind"].played > 0 then @@ -4546,24 +5621,50 @@ local unity = { key = "unity", order = 94, pos = { x = 4, y = 0 }, - config = { Xmult = 9, type = "Flush House" }, + config = { + extra = { + Xmult = 9, + type = "Flush House", + }, + }, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.x_mult, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.Xmult), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 3, cost = 8, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and (to_big(card.ability.x_mult) > to_big(1)) then - if context.poker_hands ~= nil and next(context.poker_hands[card.ability.type]) then + if context.joker_main and (to_big(card.ability.extra.Xmult) > to_big(1)) then + if context.poker_hands ~= nil and next(context.poker_hands[card.ability.extra.type]) then return { - message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.x_mult } }), + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), colour = G.C.RED, - Xmult_mod = card.ability.x_mult, + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), } end end + if context.forcetrigger then + return { + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), + colour = G.C.RED, + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), + } + end end, in_pool = function(self) if G.GAME.hands["Flush House"].played > 0 then @@ -4600,24 +5701,50 @@ local swarm = { key = "swarm", order = 95, pos = { x = 5, y = 0 }, - config = { Xmult = 9, type = "Flush Five" }, + config = { + extra = { + Xmult = 9, + type = "Flush Five", + }, + }, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.x_mult, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.Xmult), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 3, cost = 8, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and (to_big(card.ability.x_mult) > to_big(1)) then - if context.poker_hands ~= nil and next(context.poker_hands[card.ability.type]) then + if context.joker_main and (to_big(card.ability.extra.Xmult) > to_big(1)) then + if context.poker_hands ~= nil and next(context.poker_hands[card.ability.extra.type]) then return { - message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.x_mult } }), + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), colour = G.C.RED, - Xmult_mod = card.ability.x_mult, + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), } end end + if context.forcetrigger then + return { + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), + colour = G.C.RED, + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), + } + end end, in_pool = function(self) if G.GAME.hands["Flush Five"].played > 0 then @@ -4647,7 +5774,6 @@ local stronghold = { object_type = "Joker", dependencies = { items = { - "set_cry_misc_joker", "set_cry_poker_hand_stuff", "c_cry_asteroidbelt", }, @@ -4656,24 +5782,50 @@ local stronghold = { key = "stronghold", order = 119, pos = { x = 8, y = 4 }, - config = { Xmult = 5, type = "cry_Bulwark" }, + config = { + extra = { + Xmult = 5, + type = "cry_Bulwark", + }, + }, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.x_mult, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.Xmult), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 3, cost = 8, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and (to_big(card.ability.x_mult) > to_big(1)) then - if context.poker_hands ~= nil and next(context.poker_hands[card.ability.type]) then + if context.joker_main and (to_big(card.ability.extra.Xmult) > to_big(1)) then + if context.poker_hands ~= nil and next(context.poker_hands[card.ability.extra.type]) then return { - message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.x_mult } }), + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), colour = G.C.RED, - Xmult_mod = card.ability.x_mult, + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), } end end + if context.forcetrigger then + return { + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), + colour = G.C.RED, + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), + } + end end, in_pool = function(self) if G.GAME.hands["cry_Bulwark"].played > 0 then @@ -4692,7 +5844,6 @@ local wtf = { object_type = "Joker", dependencies = { items = { - "set_cry_misc_joker", "set_cry_poker_hand_stuff", "c_cry_void", }, @@ -4701,21 +5852,43 @@ local wtf = { key = "wtf", order = 120, pos = { x = 7, y = 1 }, - config = { Xmult = 10, type = "cry_Clusterfuck" }, + config = { + extra = { + Xmult = 10, + type = "cry_Clusterfuck", + }, + }, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.x_mult, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.Xmult), + localize(card.ability.extra.type, "poker_hands"), + }, + } + end, + locked_loc_vars = function(self, info_queue, card) + return { + vars = { + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 3, cost = 8, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and (to_big(card.ability.x_mult) > to_big(1)) then - if context.poker_hands ~= nil and next(context.poker_hands[card.ability.type]) then + if context.joker_main and (to_big(card.ability.extra.Xmult) > to_big(1)) then + if context.poker_hands ~= nil and next(context.poker_hands[card.ability.extra.type]) then return { - message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.x_mult } }), + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), colour = G.C.RED, - Xmult_mod = card.ability.x_mult, + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), } end end @@ -4737,7 +5910,6 @@ local clash = { object_type = "Joker", dependencies = { items = { - "set_cry_misc_joker", "set_cry_poker_hand_stuff", "c_cry_marsmoons", }, @@ -4746,24 +5918,50 @@ local clash = { key = "clash", order = 121, pos = { x = 8, y = 1 }, - config = { Xmult = 12, type = "cry_UltPair" }, + config = { + extra = { + Xmult = 12, + type = "cry_UltPair", + }, + }, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.x_mult, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.Xmult), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 3, cost = 8, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and (to_big(card.ability.x_mult) > to_big(1)) then - if context.poker_hands ~= nil and next(context.poker_hands[card.ability.type]) then + if context.joker_main and (to_big(card.ability.extra.Xmult) > to_big(1)) then + if context.poker_hands ~= nil and next(context.poker_hands[card.ability.extra.type]) then return { - message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.x_mult } }), + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), colour = G.C.RED, - Xmult_mod = card.ability.x_mult, + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), } end end + if context.forcetrigger then + return { + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), + colour = G.C.RED, + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), + } + end end, in_pool = function(self) if G.GAME.hands["cry_UltPair"].played > 0 then @@ -4778,11 +5976,159 @@ local clash = { end, unlocked = false, } + +local the = { + object_type = "Joker", + dependencies = { + items = { + "set_cry_poker_hand_stuff", + "c_cry_nibiru", + }, + }, + name = "cry-the", + key = "the", + order = 121.5, + pos = { x = 5, y = 7 }, + config = { + extra = { + Xmult = 2, + type = "cry_None", + }, + }, + loc_vars = function(self, info_queue, card) + return { + vars = { + number_format(card.ability.extra.Xmult), + localize(card.ability.extra.type, "poker_hands"), + }, + } + end, + atlas = "atlasthree", + rarity = 3, + cost = 8, + blueprint_compat = true, + demicoloncompat = true, + calculate = function(self, card, context) + if context.joker_main and (to_big(card.ability.extra.Xmult) > to_big(1)) then + if context.scoring_name == "cry_None" then + return { + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), + colour = G.C.RED, + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), + } + end + end + if context.forcetrigger then + return { + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.Xmult) }, + }), + colour = G.C.RED, + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), + } + end + end, + in_pool = function(self) + if G.GAME.hands["cry_None"].played > 0 then + return true + end + return false + end, + check_for_unlock = function(self, args) + if args.type == "win" and G.GAME.last_hand_played == "cry_None" then + return true + end + end, + unlocked = false, + cry_credits = { + art = { "MarioFan597" }, + code = { "lord-ruby" }, + }, +} + +local annihalation = { + object_type = "Joker", + dependencies = { + items = { + "set_cry_poker_hand_stuff", + "c_cry_universe", + }, + }, + name = "cry-annihalation", + key = "annihalation", + order = 121.75, + pos = { x = 8, y = 7 }, + config = { + extra = { + emult = 5.2, + type = "cry_WholeDeck", + }, + }, + loc_vars = function(self, info_queue, card) + return { + vars = { + number_format(card.ability.extra.emult), + localize(card.ability.extra.type, "poker_hands"), + }, + } + end, + locked_loc_vars = function(self, info_queue, card) + return { + vars = { + localize(card.ability.extra.type, "poker_hands"), + }, + } + end, + atlas = "atlasthree", + rarity = 3, + cost = 8, + blueprint_compat = true, + demicoloncompat = true, + calculate = function(self, card, context) + if context.joker_main and (to_big(card.ability.extra.emult) > to_big(1)) then + if next(context.poker_hands["cry_WholeDeck"]) then + return { + colour = G.C.DARK_EDITION, + Emult = lenient_bignum(card.ability.extra.emult), + } + end + end + if context.forcetrigger then + return { + colour = G.C.DARK_EDITION, + Emult = lenient_bignum(card.ability.extra.emult), + } + end + end, + in_pool = function(self) + if G.GAME.hands["cry_WholeDeck"].played > 0 then + return true + end + return false + end, + check_for_unlock = function(self, args) + if args.type == "win" and G.GAME.last_hand_played == "cry_WholeDeck" then + return true + end + end, + unlocked = false, + cry_credits = { + art = { "luigicat11" }, + code = { "lord-ruby" }, + }, +} + local filler = { object_type = "Joker", dependencies = { items = { - "set_cry_misc_joker", + "set_cry_meme", }, }, name = "cry-filler", @@ -4798,8 +6144,12 @@ local filler = { order = 89, cost = 1, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and context.poker_hands and next(context.poker_hands[card.ability.type]) then + if + (context.joker_main and context.poker_hands and next(context.poker_hands[card.ability.type])) + or context.forcetrigger + then return { message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.x_mult } }), colour = G.C.RED, @@ -4832,21 +6182,39 @@ local giggly = { key = "giggly", effect = "Cry Type Mult", pos = { x = 0, y = 5 }, - config = { t_mult = 4, type = "High Card" }, + config = { + extra = { + t_mult = 4, + type = "High Card", + }, + }, order = 16, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.t_mult, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.t_mult), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 1, cost = 1, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and context.poker_hands and next(context.poker_hands["High Card"]) then + if + (context.joker_main and context.poker_hands and next(context.poker_hands["High Card"])) + or context.forcetrigger + then return { - message = localize({ type = "variable", key = "a_mult", vars = { card.ability.t_mult } }), + message = localize({ + type = "variable", + key = "a_mult", + vars = { number_format(card.ability.extra.t_mult) }, + }), colour = G.C.RED, - mult_mod = card.ability.t_mult, + mult_mod = lenient_bignum(card.ability.extra.t_mult), } end end, @@ -4874,20 +6242,38 @@ local nutty = { effect = "Cry Type Mult", pos = { x = 1, y = 5 }, order = 17, - config = { t_mult = 19, type = "Four of a Kind" }, + config = { + extra = { + t_mult = 19, + type = "Four of a Kind", + }, + }, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.t_mult, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.t_mult), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 1, cost = 4, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and context.poker_hands and next(context.poker_hands["Four of a Kind"]) then + if + (context.joker_main and context.poker_hands and next(context.poker_hands["Four of a Kind"])) + or context.forcetrigger + then return { - message = localize({ type = "variable", key = "a_mult", vars = { card.ability.t_mult } }), + message = localize({ + type = "variable", + key = "a_mult", + vars = { number_format(card.ability.extra.t_mult) }, + }), colour = G.C.RED, - mult_mod = card.ability.t_mult, + mult_mod = lenient_bignum(card.ability.extra.t_mult), } end end, @@ -4915,20 +6301,38 @@ local manic = { effect = "Cry Type Mult", pos = { x = 2, y = 5 }, order = 18, - config = { t_mult = 22, type = "Straight Flush" }, + config = { + extra = { + t_mult = 22, + type = "Straight Flush", + }, + }, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.t_mult, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.t_mult), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 1, cost = 4, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and context.poker_hands and next(context.poker_hands["Straight Flush"]) then + if + (context.joker_main and context.poker_hands and next(context.poker_hands["Straight Flush"])) + or context.forcetrigger + then return { - message = localize({ type = "variable", key = "a_mult", vars = { card.ability.t_mult } }), + message = localize({ + type = "variable", + key = "a_mult", + vars = { number_format(card.ability.extra.t_mult) }, + }), colour = G.C.RED, - mult_mod = card.ability.t_mult, + mult_mod = lenient_bignum(card.ability.extra.t_mult), } end end, @@ -4956,20 +6360,38 @@ local silly = { pos = { x = 3, y = 5 }, effect = "Cry Type Mult", order = 19, - config = { t_mult = 16, type = "Full House" }, + config = { + extra = { + t_mult = 16, + type = "Full House", + }, + }, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.t_mult, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.t_mult), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 1, cost = 4, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and context.poker_hands and next(context.poker_hands["Full House"]) then + if + (context.joker_main and context.poker_hands and next(context.poker_hands["Full House"])) + or context.forcetrigger + then return { - message = localize({ type = "variable", key = "a_mult", vars = { card.ability.t_mult } }), + message = localize({ + type = "variable", + key = "a_mult", + vars = { number_format(card.ability.extra.t_mult) }, + }), colour = G.C.RED, - mult_mod = card.ability.t_mult, + mult_mod = lenient_bignum(card.ability.extra.t_mult), } end end, @@ -4997,20 +6419,38 @@ local delirious = { effect = "Cry Type Mult", pos = { x = 4, y = 5 }, order = 20, - config = { t_mult = 22, type = "Five of a Kind" }, + config = { + extra = { + t_mult = 22, + type = "Five of a Kind", + }, + }, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.t_mult, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.t_mult), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 1, cost = 4, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and context.poker_hands and next(context.poker_hands["Five of a Kind"]) then + if + (context.joker_main and context.poker_hands and next(context.poker_hands["Five of a Kind"])) + or context.forcetrigger + then return { - message = localize({ type = "variable", key = "a_mult", vars = { card.ability.t_mult } }), + message = localize({ + type = "variable", + key = "a_mult", + vars = { number_format(card.ability.extra.t_mult) }, + }), colour = G.C.RED, - mult_mod = card.ability.t_mult, + mult_mod = lenient_bignum(card.ability.extra.t_mult), } end end, @@ -5043,21 +6483,39 @@ local wacky = { key = "wacky", pos = { x = 5, y = 5 }, order = 21, - config = { t_mult = 30, type = "Flush House" }, + config = { + extra = { + t_mult = 30, + type = "Flush House", + }, + }, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.t_mult, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.t_mult), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 1, cost = 4, effect = "Cry Type Mult", blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and context.poker_hands and next(context.poker_hands["Flush House"]) then + if + (context.joker_main and context.poker_hands and next(context.poker_hands["Flush House"])) + or context.forcetrigger + then return { - message = localize({ type = "variable", key = "a_mult", vars = { card.ability.t_mult } }), + message = localize({ + type = "variable", + key = "a_mult", + vars = { number_format(card.ability.extra.t_mult) }, + }), colour = G.C.RED, - mult_mod = card.ability.t_mult, + mult_mod = lenient_bignum(card.ability.extra.t_mult), } end end, @@ -5090,21 +6548,39 @@ local kooky = { key = "kooky", pos = { x = 6, y = 5 }, order = 22, - config = { t_mult = 30, type = "Flush Five" }, + config = { + extra = { + t_mult = 30, + type = "Flush Five", + }, + }, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.t_mult, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.t_mult), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 1, effect = "Cry Type Mult", cost = 4, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and context.poker_hands and next(context.poker_hands["Flush Five"]) then + if + (context.joker_main and context.poker_hands and next(context.poker_hands["Flush Five"])) + or context.forcetrigger + then return { - message = localize({ type = "variable", key = "a_mult", vars = { card.ability.t_mult } }), + message = localize({ + type = "variable", + key = "a_mult", + vars = { number_format(card.ability.extra.t_mult) }, + }), colour = G.C.RED, - mult_mod = card.ability.t_mult, + mult_mod = lenient_bignum(card.ability.extra.t_mult), } end end, @@ -5130,7 +6606,6 @@ local bonkers = { object_type = "Joker", dependencies = { items = { - "set_cry_misc_joker", "set_cry_poker_hand_stuff", "c_cry_asteroidbelt", }, @@ -5139,21 +6614,39 @@ local bonkers = { key = "bonkers", pos = { x = 8, y = 5 }, order = 113, - config = { t_mult = 20, type = "cry_Bulwark" }, + config = { + extra = { + t_mult = 20, + type = "cry_Bulwark", + }, + }, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.t_mult, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.t_mult), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 1, effect = "Cry Type Mult", cost = 4, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and context.poker_hands and next(context.poker_hands["cry_Bulwark"]) then + if + (context.joker_main and context.poker_hands and next(context.poker_hands["cry_Bulwark"])) + or context.forcetrigger + then return { - message = localize({ type = "variable", key = "a_mult", vars = { card.ability.t_mult } }), + message = localize({ + type = "variable", + key = "a_mult", + vars = { number_format(card.ability.extra.t_mult) }, + }), colour = G.C.RED, - mult_mod = card.ability.t_mult, + mult_mod = lenient_bignum(card.ability.extra.t_mult), } end end, @@ -5168,7 +6661,6 @@ local fuckedup = { object_type = "Joker", dependencies = { items = { - "set_cry_misc_joker", "set_cry_poker_hand_stuff", "c_cry_void", }, @@ -5177,21 +6669,39 @@ local fuckedup = { key = "fuckedup", pos = { x = 7, y = 2 }, order = 114, - config = { t_mult = 37, type = "cry_Clusterfuck" }, + config = { + extra = { + t_mult = 37, + type = "cry_Clusterfuck", + }, + }, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.t_mult, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.t_mult), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 1, effect = "Cry Type Mult", cost = 4, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and context.poker_hands and next(context.poker_hands["cry_Clusterfuck"]) then + if + (context.joker_main and context.poker_hands and next(context.poker_hands["cry_Clusterfuck"])) + or context.forcetrigger + then return { - message = localize({ type = "variable", key = "a_mult", vars = { card.ability.t_mult } }), + message = localize({ + type = "variable", + key = "a_mult", + vars = { number_format(card.ability.extra.t_mult) }, + }), colour = G.C.RED, - mult_mod = card.ability.t_mult, + mult_mod = lenient_bignum(card.ability.extra.t_mult), } end end, @@ -5206,7 +6716,6 @@ local foolhardy = { object_type = "Joker", dependencies = { items = { - "set_cry_misc_joker", "set_cry_poker_hand_stuff", "c_cry_marsmoons", }, @@ -5215,21 +6724,39 @@ local foolhardy = { key = "foolhardy", pos = { x = 8, y = 2 }, order = 115, - config = { t_mult = 42, type = "cry_UltPair" }, + config = { + extra = { + t_mult = 42, + type = "cry_UltPair", + }, + }, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.t_mult, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.t_mult), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 1, effect = "Cry Type Mult", cost = 4, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and context.poker_hands and next(context.poker_hands["cry_UltPair"]) then + if + (context.joker_main and context.poker_hands and next(context.poker_hands["cry_UltPair"])) + or context.forcetrigger + then return { - message = localize({ type = "variable", key = "a_mult", vars = { card.ability.t_mult } }), + message = localize({ + type = "variable", + key = "a_mult", + vars = { number_format(card.ability.extra.t_mult) }, + }), colour = G.C.RED, - mult_mod = card.ability.t_mult, + mult_mod = lenient_bignum(card.ability.extra.t_mult), } end end, @@ -5240,6 +6767,116 @@ local foolhardy = { return false end, } + +local undefined = { + object_type = "Joker", + dependencies = { + items = { + "set_cry_poker_hand_stuff", + "c_cry_nibiru", + }, + }, + name = "cry-undefined Joker", + key = "undefined", + pos = { x = 3, y = 7 }, + order = 115.5, + config = { + extra = { + t_mult = 5, + type = "cry_None", + }, + }, + loc_vars = function(self, info_queue, card) + return { + vars = { + number_format(card.ability.extra.t_mult), + localize(card.ability.extra.type, "poker_hands"), + }, + } + end, + atlas = "atlasthree", + rarity = 1, + effect = "Cry Type Mult", + cost = 4, + blueprint_compat = true, + demicoloncompat = true, + calculate = function(self, card, context) + if (context.joker_main and context.scoring_name == "cry_None") or context.forcetrigger then + return { + message = localize({ + type = "variable", + key = "a_mult", + vars = { number_format(card.ability.extra.t_mult) }, + }), + colour = G.C.RED, + mult_mod = lenient_bignum(card.ability.extra.t_mult), + } + end + end, + in_pool = function(self) + if G.GAME.hands["cry_None"].played > 0 then + return true + end + return false + end, + cry_credits = { + art = { "unexian" }, + code = { "lord-ruby" }, + }, +} + +local wordscanteven = { + object_type = "Joker", + dependencies = { + items = { + "set_cry_poker_hand_stuff", + "c_cry_universe", + }, + }, + name = "cry-Words Cant Even", + key = "words_cant_even", + pos = { x = 6, y = 7 }, + effect = "Cry Type Chips", + order = 115.75, + config = { + extra = { + x_mult = 52000000, + type = "cry_WholeDeck", + }, + }, + loc_vars = function(self, info_queue, card) + return { + vars = { + number_format(card.ability.extra.x_mult), + localize(card.ability.extra.type, "poker_hands"), + }, + } + end, + atlas = "atlasthree", + rarity = 1, + cost = 4, + blueprint_compat = true, + demicoloncompat = true, + calculate = function(self, card, context) + if (context.joker_main and next(context.poker_hands["cry_WholeDeck"])) or context.forcetrigger then + return { + colour = G.C.RED, + xmult = lenient_bignum(card.ability.extra.x_mult), + } + end + end, + in_pool = function(self) + if G.GAME.hands["cry_WholeDeck"].played > 0 then + return true + end + return false + end, + cry_credits = { + art = { "luigicat11" }, + code = { "lord-ruby" }, + }, +} + local dubious = { object_type = "Joker", dependencies = { @@ -5251,21 +6888,39 @@ local dubious = { key = "dubious", pos = { x = 0, y = 6 }, order = 24, - config = { t_chips = 20, type = "High Card" }, + config = { + extra = { + t_chips = 20, + type = "High Card", + }, + }, effect = "Cry Type Chips", loc_vars = function(self, info_queue, card) - return { vars = { card.ability.t_chips, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.t_chips), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 1, cost = 1, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and context.poker_hands and next(context.poker_hands["High Card"]) then + if + (context.joker_main and context.poker_hands and next(context.poker_hands["High Card"])) + or context.forcetrigger + then return { - message = localize({ type = "variable", key = "a_chips", vars = { card.ability.t_chips } }), + message = localize({ + type = "variable", + key = "a_chips", + vars = { number_format(card.ability.extra.t_chips) }, + }), colour = G.C.BLUE, - chip_mod = card.ability.t_chips, + chip_mod = lenient_bignum(card.ability.extra.t_chips), } end end, @@ -5293,20 +6948,38 @@ local shrewd = { pos = { x = 1, y = 6 }, order = 25, effect = "Cry Type Chips", - config = { t_chips = 150, type = "Four of a Kind" }, + config = { + extra = { + t_chips = 150, + type = "Four of a Kind", + }, + }, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.t_chips, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.t_chips), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 1, cost = 4, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and context.poker_hands and next(context.poker_hands["Four of a Kind"]) then + if + (context.joker_main and context.poker_hands and next(context.poker_hands["Four of a Kind"])) + or context.forcetrigger + then return { - message = localize({ type = "variable", key = "a_chips", vars = { card.ability.t_chips } }), + message = localize({ + type = "variable", + key = "a_chips", + vars = { number_format(card.ability.extra.t_chips) }, + }), colour = G.C.BLUE, - chip_mod = card.ability.t_chips, + chip_mod = lenient_bignum(card.ability.extra.t_chips), } end end, @@ -5334,20 +7007,38 @@ local tricksy = { effect = "Cry Type Chips", order = 26, pos = { x = 2, y = 6 }, - config = { t_chips = 170, type = "Straight Flush" }, + config = { + extra = { + t_chips = 170, + type = "Straight Flush", + }, + }, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.t_chips, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.t_chips), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 1, cost = 4, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and context.poker_hands and next(context.poker_hands["Straight Flush"]) then + if + (context.joker_main and context.poker_hands and next(context.poker_hands["Straight Flush"])) + or context.forcetrigger + then return { - message = localize({ type = "variable", key = "a_chips", vars = { card.ability.t_chips } }), + message = localize({ + type = "variable", + key = "a_chips", + vars = { number_format(card.ability.extra.t_chips) }, + }), colour = G.C.BLUE, - chip_mod = card.ability.t_chips, + chip_mod = lenient_bignum(card.ability.extra.t_chips), } end end, @@ -5375,20 +7066,38 @@ local foxy = { pos = { x = 3, y = 6 }, order = 27, effect = "Cry Type Chips", - config = { t_chips = 130, type = "Full House" }, + config = { + extra = { + t_chips = 130, + type = "Full House", + }, + }, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.t_chips, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.t_chips), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 1, cost = 4, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and context.poker_hands and next(context.poker_hands["Full House"]) then + if + (context.joker_main and context.poker_hands and next(context.poker_hands["Full House"])) + or context.forcetrigger + then return { - message = localize({ type = "variable", key = "a_chips", vars = { card.ability.t_chips } }), + message = localize({ + type = "variable", + key = "a_chips", + vars = { number_format(card.ability.extra.t_chips) }, + }), colour = G.C.BLUE, - chip_mod = card.ability.t_chips, + chip_mod = lenient_bignum(card.ability.extra.t_chips), } end end, @@ -5416,20 +7125,38 @@ local savvy = { pos = { x = 4, y = 6 }, effect = "Cry Type Chips", order = 28, - config = { t_chips = 170, type = "Five of a Kind" }, + config = { + extra = { + t_chips = 170, + type = "Five of a Kind", + }, + }, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.t_chips, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.t_chips), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 1, cost = 4, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and context.poker_hands and next(context.poker_hands["Five of a Kind"]) then + if + (context.joker_main and context.poker_hands and next(context.poker_hands["Five of a Kind"])) + or context.forcetrigger + then return { - message = localize({ type = "variable", key = "a_chips", vars = { card.ability.t_chips } }), + message = localize({ + type = "variable", + key = "a_chips", + vars = { number_format(card.ability.extra.t_chips) }, + }), colour = G.C.BLUE, - chip_mod = card.ability.t_chips, + chip_mod = lenient_bignum(card.ability.extra.t_chips), } end end, @@ -5463,20 +7190,38 @@ local subtle = { pos = { x = 5, y = 6 }, effect = "Cry Type Chips", order = 29, - config = { t_chips = 240, type = "Flush House" }, + config = { + extra = { + t_chips = 240, + type = "Flush House", + }, + }, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.t_chips, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.t_chips), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 1, cost = 4, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and context.poker_hands and next(context.poker_hands["Flush House"]) then + if + (context.joker_main and context.poker_hands and next(context.poker_hands["Flush House"])) + or context.forcetrigger + then return { - message = localize({ type = "variable", key = "a_chips", vars = { card.ability.t_chips } }), + message = localize({ + type = "variable", + key = "a_chips", + vars = { number_format(card.ability.extra.t_chips) }, + }), colour = G.C.BLUE, - chip_mod = card.ability.t_chips, + chip_mod = lenient_bignum(card.ability.extra.t_chips), } end end, @@ -5510,20 +7255,38 @@ local discreet = { pos = { x = 6, y = 6 }, effect = "Cry Type Chips", order = 30, - config = { t_chips = 240, type = "Flush Five" }, + config = { + extra = { + t_chips = 240, + type = "Flush Five", + }, + }, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.t_chips, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.t_chips), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 1, cost = 4, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and context.poker_hands and next(context.poker_hands["Flush Five"]) then + if + (context.joker_main and context.poker_hands and next(context.poker_hands["Flush Five"])) + or context.forcetrigger + then return { - message = localize({ type = "variable", key = "a_chips", vars = { card.ability.t_chips } }), + message = localize({ + type = "variable", + key = "a_chips", + vars = { number_format(card.ability.extra.t_chips) }, + }), colour = G.C.BLUE, - chip_mod = card.ability.t_chips, + chip_mod = lenient_bignum(card.ability.extra.t_chips), } end end, @@ -5549,7 +7312,6 @@ local adroit = { object_type = "Joker", dependencies = { items = { - "set_cry_misc_joker", "set_cry_poker_hand_stuff", "c_cry_asteroidbelt", }, @@ -5559,20 +7321,38 @@ local adroit = { pos = { x = 7, y = 4 }, effect = "Cry Type Chips", order = 116, - config = { t_chips = 170, type = "cry_Bulwark" }, + config = { + extra = { + t_chips = 170, + type = "cry_Bulwark", + }, + }, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.t_chips, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.t_chips), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 1, cost = 4, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and context.poker_hands and next(context.poker_hands["cry_Bulwark"]) then + if + (context.joker_main and context.poker_hands and next(context.poker_hands["cry_Bulwark"])) + or context.forcetrigger + then return { - message = localize({ type = "variable", key = "a_chips", vars = { card.ability.t_chips } }), + message = localize({ + type = "variable", + key = "a_chips", + vars = { number_format(card.ability.extra.t_chips) }, + }), colour = G.C.BLUE, - chip_mod = card.ability.t_chips, + chip_mod = lenient_bignum(card.ability.extra.t_chips), } end end, @@ -5587,7 +7367,6 @@ local penetrating = { object_type = "Joker", dependencies = { items = { - "set_cry_misc_joker", "set_cry_poker_hand_stuff", "c_cry_void", }, @@ -5597,20 +7376,38 @@ local penetrating = { pos = { x = 7, y = 3 }, effect = "Cry Type Chips", order = 117, - config = { t_chips = 270, type = "cry_Clusterfuck" }, + config = { + extra = { + t_chips = 270, + type = "cry_Clusterfuck", + }, + }, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.t_chips, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.t_chips), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 1, cost = 4, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and context.poker_hands and next(context.poker_hands["cry_Clusterfuck"]) then + if + (context.joker_main and context.poker_hands and next(context.poker_hands["cry_Clusterfuck"])) + or context.forcetrigger + then return { - message = localize({ type = "variable", key = "a_chips", vars = { card.ability.t_chips } }), + message = localize({ + type = "variable", + key = "a_chips", + vars = { number_format(card.ability.extra.t_chips) }, + }), colour = G.C.BLUE, - chip_mod = card.ability.t_chips, + chip_mod = lenient_bignum(card.ability.extra.t_chips), } end end, @@ -5625,7 +7422,6 @@ local treacherous = { object_type = "Joker", dependencies = { items = { - "set_cry_misc_joker", "set_cry_poker_hand_stuff", "c_cry_marsmoons", }, @@ -5635,20 +7431,38 @@ local treacherous = { pos = { x = 8, y = 3 }, effect = "Cry Type Chips", order = 118, - config = { t_chips = 300, type = "cry_UltPair" }, + config = { + extra = { + t_chips = 300, + type = "cry_UltPair", + }, + }, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.t_chips, localize(card.ability.type, "poker_hands") } } + return { + vars = { + number_format(card.ability.extra.t_chips), + localize(card.ability.extra.type, "poker_hands"), + }, + } end, atlas = "atlasthree", rarity = 1, cost = 4, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) - if context.joker_main and context.poker_hands and next(context.poker_hands["cry_UltPair"]) then + if + (context.joker_main and context.poker_hands and next(context.poker_hands["cry_UltPair"])) + or context.forcetrigger + then return { - message = localize({ type = "variable", key = "a_chips", vars = { card.ability.t_chips } }), + message = localize({ + type = "variable", + key = "a_chips", + vars = { number_format(card.ability.extra.t_chips) }, + }), colour = G.C.BLUE, - chip_mod = card.ability.t_chips, + chip_mod = lenient_bignum(card.ability.extra.t_chips), } end end, @@ -5659,6 +7473,115 @@ local treacherous = { return false end, } +local nebulous = { + object_type = "Joker", + dependencies = { + items = { + "set_cry_poker_hand_stuff", + "c_cry_nibiru", + }, + }, + name = "cry-nebulous Joker", + key = "nebulous", + pos = { x = 4, y = 7 }, + effect = "Cry Type Chips", + order = 118.5, + config = { + extra = { + t_chips = 30, + type = "cry_None", + }, + }, + loc_vars = function(self, info_queue, card) + return { + vars = { + number_format(card.ability.extra.t_chips), + localize(card.ability.extra.type, "poker_hands"), + }, + } + end, + atlas = "atlasthree", + rarity = 1, + cost = 4, + blueprint_compat = true, + demicoloncompat = true, + calculate = function(self, card, context) + if (context.joker_main and context.scoring_name == "cry_None") or context.forcetrigger then + return { + message = localize({ + type = "variable", + key = "a_chips", + vars = { number_format(card.ability.extra.t_chips) }, + }), + colour = G.C.BLUE, + chip_mod = lenient_bignum(card.ability.extra.t_chips), + } + end + end, + in_pool = function(self) + if G.GAME.hands["cry_None"].played > 0 then + return true + end + return false + end, + cry_credits = { + art = { "unexian" }, + code = { "lord-ruby" }, + }, +} + +local manylostminds = { + object_type = "Joker", + dependencies = { + items = { + "set_cry_poker_hand_stuff", + "c_cry_universe", + }, + }, + name = "cry-Many Lost Minds", + key = "many_lost_minds", + pos = { x = 7, y = 7 }, + order = 118.75, + config = { + extra = { + chips = 8.0658175e67, --52! + type = "cry_WholeDeck", + }, + }, + loc_vars = function(self, info_queue, card) + return { + vars = { + number_format(card.ability.extra.chips), + localize(card.ability.extra.type, "poker_hands"), + }, + } + end, + atlas = "atlasthree", + rarity = 1, + effect = "Cry Type Mult", + cost = 4, + blueprint_compat = true, + demicoloncompat = true, + calculate = function(self, card, context) + if (context.joker_main and next(context.poker_hands["cry_WholeDeck"])) or context.forcetrigger then + return { + colour = G.C.BLUE, + chips = lenient_bignum(card.ability.extra.chips), + } + end + end, + in_pool = function(self) + if G.GAME.hands["cry_WholeDeck"].played > 0 then + return true + end + return false + end, + cry_credits = { + art = { "luigicat11" }, + code = { "lord-ruby" }, + }, +} + local coin = { object_type = "Joker", dependencies = { @@ -5669,18 +7592,34 @@ local coin = { name = "cry-coin", key = "coin", pos = { x = 0, y = 2 }, - config = { extra = { money = 1 } }, + config = { + extra = { money = 1 }, + immutable = { money_mod = 10 }, + }, rarity = 1, order = 53, cost = 5, blueprint_compat = true, + demicoloncompat = true, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.money, center.ability.extra.money * 10 } } + return { + vars = { + number_format(center.ability.extra.money), + number_format( + center.ability.extra.money + * (Card.get_gameset(card) ~= "modest" and center.ability.immutable.money_mod or 4) + ), + }, + } end, atlas = "atlasthree", calculate = function(self, card, context) - if context.selling_card and context.card.ability.set == "Joker" then - local option = pseudorandom(pseudoseed("coin"), card.ability.extra.money, card.ability.extra.money * 10) + if (context.selling_card and context.card.ability.set == "Joker") or context.forcetrigger then + local mod = math.floor( + pseudorandom(pseudoseed("coin")) + * (Card.get_gameset(card) ~= "modest" and card.ability.immutable.money_mod or 4) + ) + 1 + local option = lenient_bignum(to_big(card.ability.extra.money) * mod) ease_dollars(option) card_eval_status_text( context.blueprint_card or card, @@ -5688,7 +7627,7 @@ local coin = { nil, nil, nil, - { message = localize("$") .. option, colour = G.C.MONEY, delay = 0.45 } + { message = localize("$") .. number_format(option), colour = G.C.MONEY, delay = 0.45 } ) return nil, true end @@ -5716,41 +7655,64 @@ local wheelhope = { name = "cry-wheelhope", key = "wheelhope", pos = { x = 1, y = 1 }, - config = { extra = { extra = 0.5, x_mult = 1 } }, + config = { + extra = { + extra = 0.5, + x_mult = 1, + }, + }, rarity = 2, cost = 5, order = 74, perishable_compat = false, blueprint_compat = true, + demicoloncompat = true, loc_vars = function(self, info_queue, center) - info_queue[#info_queue + 1] = G.P_CENTERS.c_wheel_of_fortune - return { vars = { center.ability.extra.extra, center.ability.extra.x_mult } } + local aaa, bbb = SMODS.get_probability_vars(nil, 1, 4, "wheel_of_fortune") + info_queue[#info_queue + 1] = { key = "alt_wheel_of_fortune", set = "Other", specific_vars = { aaa, bbb } } + return { + vars = { + number_format(center.ability.extra.extra), + number_format(center.ability.extra.x_mult), + }, + } end, atlas = "atlasthree", calculate = function(self, card, context) - if context.joker_main and (card.ability.extra.x_mult > 1) then + if context.joker_main and (to_big(card.ability.extra.x_mult) > to_big(1)) then return { - message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.x_mult } }), - Xmult_mod = card.ability.extra.x_mult, + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.x_mult) }, + }), + Xmult_mod = lenient_bignum(card.ability.extra.x_mult), } end - if context.consumeable then - if - context.consumeable.ability.name == "The Wheel of Fortune" - and not context.consumeable.cry_wheel_success - then - card.ability.extra.x_mult = card.ability.extra.x_mult + card.ability.extra.extra - card_eval_status_text( - card, - "extra", - nil, - nil, - nil, - { message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.x_mult } }) } - ) + if context.pseudorandom_result and not context.result then + if context.identifier and context.identifier == "wheel_of_fortune" then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "x_mult", + scalar_value = "extra", + message_key = "a_xmult", + message_colour = G.C.RED, + }) return nil, true end end + if context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "x_mult", + scalar_value = "extra", + message_key = "a_xmult", + message_colour = G.C.RED, + }) + return { + Xmult_mod = lenient_bignum(card.ability.extra.x_mult), + } + end end, cry_credits = { idea = { @@ -5778,29 +7740,19 @@ local oldblueprint = { rarity = 1, cost = 6, order = 83, - update = function(self, card, front) - if G.STAGE == G.STAGES.RUN then + blueprint_compat = true, + eternal_compat = false, + atlas = "atlasthree", + loc_vars = function(self, info_queue, card) + if card.area and card.area == G.jokers then + local other_joker for i = 1, #G.jokers.cards do if G.jokers.cards[i] == card then other_joker = G.jokers.cards[i + 1] end end - if other_joker and other_joker ~= card and other_joker.config.center.blueprint_compat then - card.ability.blueprint_compat = "compatible" - else - card.ability.blueprint_compat = "incompatible" - end - end - end, - loc_vars = function(self, info_queue, card) - card.ability.blueprint_compat_ui = card.ability.blueprint_compat_ui or "" - card.ability.blueprint_compat_check = nil - return { - vars = { - cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged), - card.ability.extra.odds, - }, - main_end = (card.area and card.area == G.jokers) and { + local compatible = other_joker and other_joker ~= card and other_joker.config.center.blueprint_compat + main_end = { { n = G.UIT.C, config = { align = "bm", minh = 0.4 }, @@ -5810,17 +7762,18 @@ local oldblueprint = { config = { ref_table = card, align = "m", - colour = G.C.JOKER_GREY, + colour = compatible and mix_colours(G.C.GREEN, G.C.JOKER_GREY, 0.8) + or mix_colours(G.C.RED, G.C.JOKER_GREY, 0.8), r = 0.05, padding = 0.06, - func = "blueprint_compat", }, nodes = { { n = G.UIT.T, config = { - ref_table = card.ability, - ref_value = "blueprint_compat_ui", + text = " " + .. localize("k_" .. (compatible and "compatible" or "incompatible")) + .. " ", colour = G.C.UI.TEXT_LIGHT, scale = 0.32 * 0.8, }, @@ -5829,25 +7782,26 @@ local oldblueprint = { }, }, }, - } or nil, + } + end + return { + vars = { + SMODS.get_probability_vars(card, 1, card.ability.extra.odds, "Old Blueprint"), + }, + main_end = main_end, } end, - blueprint_compat = true, - eternal_compat = false, - atlas = "atlasthree", calculate = function(self, card, context) if - context.end_of_round2 + context.end_of_round + and context.game_over == false + and context.main_eval + and not context.blueprint and not context.individual and not context.repetition - and not context.blueprint and not context.retrigger_joker then - if - pseudorandom("oldblueprint") - < cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged) - / card.ability.extra.odds - then + if SMODS.pseudorandom_probability(card, "oldblueprint", 1, card.ability.extra.odds, "Old Blueprint") then G.E_MANAGER:add_event(Event({ func = function() play_sound("tarot1") @@ -5863,32 +7817,17 @@ local oldblueprint = { G.jokers:remove_card(card) card:remove() card = nil - if G.P_CENTERS["j_blueprint"].unlocked then - G.GAME.oldbpfactor = (G.GAME.oldbpfactor or 1) * 3 - end return true end, })) return true end, })) - card_eval_status_text( - card, - "extra", - nil, - nil, - nil, - { message = localize("k_extinct_ex"), colour = G.C.FILTER } - ) + card_eval_status_text(card, "extra", nil, nil, nil, { message = localize("cry_destroyed_ex") }) else - card_eval_status_text( - card, - "extra", - nil, - nil, - nil, - { message = localize("k_safe_ex"), colour = G.C.FILTER } - ) + return { + message = localize("k_safe_ex"), + } end end local other_joker = nil @@ -5897,33 +7836,7 @@ local oldblueprint = { other_joker = G.jokers.cards[i + 1] end end - if other_joker and other_joker ~= card then - context.blueprint = (context.blueprint and (context.blueprint + 1)) or 1 - context.blueprint_card = context.blueprint_card or card - - if context.blueprint > #G.jokers.cards + 1 then - return - end - - local other_joker_ret, trig = other_joker:calculate_joker(context) - local eff_card = context.blueprint_card or card - - context.blueprint = nil - context.blueprint_card = nil - - if other_joker_ret == true then - return other_joker_ret - end - if other_joker_ret or trig then - if not other_joker_ret then - other_joker_ret = {} - end - other_joker_ret.card = eff_card - other_joker_ret.colour = darken(G.C.BLUE, 0.3) - other_joker_ret.no_callback = true - return other_joker_ret - end - end + return SMODS.blueprint_effect(card, other_joker, context) end, cry_credits = { idea = { @@ -5934,7 +7847,8 @@ local oldblueprint = { "unexian", }, code = { - "Math", + "Math", --original + "NaoRiley", --rewrite }, }, } @@ -5948,22 +7862,34 @@ local night = { name = "cry-night", key = "night", config = { extra = { mult = 3 } }, + gameset_config = { + modest = { + extra = { + mult = 2, + }, + }, + }, pos = { x = 3, y = 1 }, rarity = 3, cost = 6, order = 41, eternal_compat = false, blueprint_compat = true, + demicoloncompat = true, atlas = "atlasthree", loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.mult } } + return { vars = { number_format(center.ability.extra.mult) } } end, calculate = function(self, card, context) if context.joker_main and G.GAME.current_round.hands_left == 0 then - if card.ability.extra.mult > 1 then + if to_big(card.ability.extra.mult) > to_big(1) then return { - message = localize({ type = "variable", key = "a_powmult", vars = { card.ability.extra.mult } }), - Emult_mod = card.ability.extra.mult, + message = localize({ + type = "variable", + key = "a_powmult", + vars = { number_format(card.ability.extra.mult) }, + }), + Emult_mod = lenient_bignum(card.ability.extra.mult), colour = G.C.DARK_EDITION, } end @@ -6013,6 +7939,38 @@ local night = { juice_card_until(card, eval, true) end end + if context.forcetrigger then + G.E_MANAGER:add_event(Event({ + func = function() + play_sound("tarot1") + card.T.r = -0.2 + card:juice_up(0.3, 0.4) + card.states.drag.is = true + card.children.center.pinch.x = true + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.3, + blockable = false, + func = function() + G.jokers:remove_card(card) + card:remove() + card = nil + return true + end, + })) + return true + end, + })) + return { + message = localize({ + type = "variable", + key = "a_powmult", + vars = { number_format(card.ability.extra.mult) }, + }), + Emult_mod = lenient_bignum(card.ability.extra.mult), + colour = G.C.DARK_EDITION, + } + end end, cry_credits = { idea = { @@ -6042,20 +8000,21 @@ local busdriver = { order = 46, atlas = "atlasthree", blueprint_compat = true, + demicoloncompat = true, loc_vars = function(self, info_queue, card) local prob = cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged) local oddy = math.max(1, card.ability.extra.odds) return { vars = { (oddy - 1 / prob), - card.ability.extra.mult, + number_format(card.ability.extra.mult), oddy, (1 / prob), }, } end, calculate = function(self, card, context) - if context.joker_main and (card.ability.extra.mult > 0) then + if context.joker_main and (to_big(card.ability.extra.mult) > to_big(0)) then local oddy = math.max(1, card.ability.extra.odds) if pseudorandom("busdriver") @@ -6063,18 +8022,37 @@ local busdriver = { - (1 / (cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged) * oddy)) then return { - message = localize({ type = "variable", key = "a_mult", vars = { card.ability.extra.mult } }), - mult_mod = card.ability.extra.mult, + message = localize({ + type = "variable", + key = "a_mult", + vars = { number_format(card.ability.extra.mult) }, + }), + mult_mod = lenient_bignum(card.ability.extra.mult), colour = G.C.MULT, } else return { - message = localize({ type = "variable", key = "a_mult_minus", vars = { card.ability.extra.mult } }), - mult_mod = (card.ability.extra.mult * -1), + message = localize({ + type = "variable", + key = "a_mult_minus", + vars = { number_format(card.ability.extra.mult) }, + }), + mult_mod = lenient_bignum(to_big(card.ability.extra.mult) * -1), colour = G.C.MULT, } end end + if context.forcetrigger then + return { + message = localize({ + type = "variable", + key = "a_mult", + vars = { number_format(card.ability.extra.mult) }, + }), + mult_mod = lenient_bignum(card.ability.extra.mult), + colour = G.C.MULT, + } + end end, cry_credits = { idea = { @@ -6103,10 +8081,28 @@ local translucent = { cost = 4, order = 52, immutable = true, + blueprint_compat = true, eternal_compat = false, + demicoloncompat = true, atlas = "atlasthree", + loc_vars = function(self, info_queue, card) + local aaa + if G.jokers then + for k, v in ipairs(G.jokers.cards) do + if (v.edition and v.edition.negative) and G.localization.descriptions.Other.remove_negative then + aaa = {} + localize({ type = "other", key = "remove_negative", nodes = aaa, vars = {} }) + aaa = aaa[1] + break + end + end + end + return { + main_end = aaa, + } + end, calculate = function(self, card, context) - if context.selling_self and not (context.retrigger_joker or context.blueprint) then + if context.selling_self and not context.retrigger_joker or context.forcetrigger then local jokers = {} for i = 1, #G.jokers.cards do if G.jokers.cards[i] ~= card and not G.jokers.cards[i].debuff then @@ -6115,7 +8111,14 @@ local translucent = { end if #jokers > 0 then if #G.jokers.cards <= G.jokers.config.card_limit then - card_eval_status_text(card, "extra", nil, nil, nil, { message = localize("k_duplicated_ex") }) + card_eval_status_text( + context.blueprint_card or card, + "extra", + nil, + nil, + nil, + { message = localize("k_duplicated_ex") } + ) local chosen_joker = pseudorandom_element(jokers, pseudoseed("trans")) local _card = copy_card(chosen_joker, nil, nil, nil, chosen_joker.edition and chosen_joker.edition.negative) @@ -6126,10 +8129,24 @@ local translucent = { G.jokers:emplace(_card) return nil, true else - card_eval_status_text(card, "extra", nil, nil, nil, { message = localize("k_no_room_ex") }) + card_eval_status_text( + context.blueprint_card or card, + "extra", + nil, + nil, + nil, + { message = localize("k_no_room_ex") } + ) end else - card_eval_status_text(card, "extra", nil, nil, nil, { message = localize("k_no_other_jokers") }) + card_eval_status_text( + context.blueprint_card or card, + "extra", + nil, + nil, + nil, + { message = localize("k_no_other_jokers") } + ) end end end, @@ -6155,30 +8172,56 @@ local morse = { name = "cry-morse", key = "morse", pos = { x = 5, y = 1 }, - config = { extra = { bonus = 2, money = 1 } }, + config = { + extra = { + bonus = 2, + money = 1, + }, + }, + gameset_config = { + modest = { + extra = { + bonus = 1, + money = 1, + }, + }, + }, rarity = 1, cost = 5, order = 57, perishable_compat = false, blueprint_compat = false, + demicoloncompat = true, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.bonus, center.ability.extra.money } } + return { + vars = { + number_format(center.ability.extra.bonus), + number_format(center.ability.extra.money), + }, + } end, atlas = "atlastwo", calculate = function(self, card, context) if context.selling_card and context.card.edition and not context.blueprint then - card.ability.extra.money = card.ability.extra.money + card.ability.extra.bonus - return { - card_eval_status_text(card, "extra", nil, nil, nil, { - message = localize("k_upgrade_ex"), - colour = G.C.MONEY, - }), - } + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "money", + scalar_value = "bonus", + }) + end + if context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "money", + scalar_value = "bonus", + no_message = true, + }) + ease_dollars(lenient_bignum(card.ability.extra.money)) end end, calc_dollar_bonus = function(self, card) - if card.ability.extra.money > 0 then - return card.ability.extra.money + if to_big(card.ability.extra.money) > to_big(0) then + return lenient_bignum(card.ability.extra.money) end end, cry_credits = { @@ -6209,19 +8252,39 @@ local membershipcard = { cost = 20, order = 35, blueprint_compat = true, + demicoloncompat = true, atlas = "atlasthree", loc_vars = function(self, info_queue, card) - return { vars = { card.ability.extra.Xmult_mod, card.ability.extra.Xmult_mod * Cryptid.member_count } } + local aaa + if not Cryptid_config.HTTPS then + if G.localization.descriptions.Other.cry_https_disabled then + aaa = {} + localize({ type = "other", key = "cry_https_disabled", nodes = aaa, vars = {} }) + aaa = aaa[1] + end + end + return { + vars = { + number_format(card.ability.extra.Xmult_mod), + number_format(lenient_bignum(to_big(card.ability.extra.Xmult_mod) * Cryptid.member_count)), + }, + main_end = aaa, + } end, calculate = function(self, card, context) - if context.joker_main and card.ability.extra.Xmult_mod * Cryptid.member_count > 1 then + if + (context.joker_main and to_big(card.ability.extra.Xmult_mod) * to_big(Cryptid.member_count) > to_big(1)) + or context.forcetrigger + then return { message = localize({ type = "variable", key = "a_xmult", - vars = { card.ability.extra.Xmult_mod * Cryptid.member_count }, + vars = { + number_format(lenient_bignum(to_big(card.ability.extra.Xmult_mod) * Cryptid.member_count)), + }, }), - Xmult_mod = card.ability.extra.Xmult_mod * Cryptid.member_count, + Xmult_mod = lenient_bignum(to_big(card.ability.extra.Xmult_mod) * Cryptid.member_count), } end end, @@ -6251,9 +8314,18 @@ local kscope = { cost = 7, order = 55, atlas = "atlasthree", + demicoloncompat = true, immutable = true, calculate = function(self, card, context) - if context.end_of_round and G.GAME.blind.boss and not context.individual and not context.repetition then + if + ( + context.end_of_round + and G.GAME.blind.boss + and not context.individual + and not context.repetition + and not context.blueprint + ) or context.forcetrigger + then local eligiblejokers = {} for k, v in pairs(G.jokers.cards) do if v.ability.set == "Joker" and not v.edition and v ~= card then @@ -6267,6 +8339,9 @@ local kscope = { local edition = { polychrome = true } eligible_card:set_edition(edition, true) check_for_unlock({ type = "have_edition" }) + if not context.retrigger_joker then + card:juice_up(0.5, 0.5) + end end end end, @@ -6292,25 +8367,37 @@ local cryptidmoment = { name = "cry_cryptidmoment", key = "cryptidmoment", pos = { x = 6, y = 0 }, - config = { extra = { money = 1 } }, + config = { + extra = { money = 1 }, + immutable = { max_added_val = 1 }, + }, loc_vars = function(self, info_queue, center) - return { vars = { math.max(1, math.floor(center.ability.extra.money)) } } + return { vars = { math.max(center.ability.immutable.max_added_val, math.floor(center.ability.extra.money)) } } end, rarity = 1, cost = 4, order = 65, + blueprint_compat = true, eternal_compat = false, + demicoloncompat = true, atlas = "atlasthree", calculate = function(self, card, context) - if context.selling_self and not context.blueprint then + if context.selling_self or context.forcetrigger then for k, v in ipairs(G.jokers.cards) do if v.set_cost then v.ability.extra_value = (v.ability.extra_value or 0) - + math.max(1, math.floor(card.ability.extra.money)) + + math.max(card.ability.immutable.max_added_val, math.floor(card.ability.extra.money)) v:set_cost() end end - card_eval_status_text(card, "extra", nil, nil, nil, { message = localize("k_val_up"), colour = G.C.MONEY }) + card_eval_status_text( + context.blueprint_card or card, + "extra", + nil, + nil, + nil, + { message = localize("k_val_up"), colour = G.C.MONEY } + ) end end, cry_credits = { @@ -6347,24 +8434,29 @@ local flipside = { add_to_deck = function(self, card, from_debuff) for i = 1, #G.jokers.cards do if G.jokers.cards[i].edition and G.jokers.cards[i].edition.cry_double_sided then - G.jokers.cards[i]:init_dbl_side() G.jokers.cards[i]:remove_from_deck(true) - G.jokers.cards[i].dbl_side:add_to_deck(true) + local dummy = G.jokers.cards[i]:get_other_side_dummy() + if dummy then + Card.add_to_deck(dummy, true) + end end end end, remove_from_deck = function(self, card, from_debuff) for i = 1, #G.jokers.cards do if G.jokers.cards[i].edition and G.jokers.cards[i].edition.cry_double_sided then - G.jokers.cards[i]:init_dbl_side() G.jokers.cards[i]:add_to_deck(true) - G.jokers.cards[i].dbl_side:remove_from_deck(true) + local dummy = G.jokers.cards[i]:get_other_side_dummy(true) + if dummy then + dummy.added_to_deck = true + Card.remove_from_deck(dummy, true) + end end end end, calculate = function(self, card, context) if context.retrigger_joker_check and not context.retrigger_joker and context.other_card ~= self then - if context.other_context and context.other_context.dbl_side then + if context.other_context and context.other_card.edition and context.other_card.edition.cry_double_sided then return { message = localize("k_again_ex"), repetitions = 1, @@ -6384,6 +8476,7 @@ local flipside = { }, code = { "Math", + "lord-ruby", }, }, } @@ -6403,15 +8496,18 @@ local oldinvisible = { order = 78, atlas = "atlasthree", immutable = true, + demicoloncompat = true, loc_vars = function(self, info_queue, center) return { vars = { center.ability.extra } } end, calculate = function(self, card, context) if - context.selling_card - and context.card.ability.set == "Joker" - and not context.blueprint - and not context.retrigger_joker + ( + context.selling_card + and context.card.ability.set == "Joker" + and not context.blueprint + and not context.retrigger_joker + ) or context.forcetrigger then if card.ability.extra >= 3 then card.ability.extra = 0 @@ -6484,7 +8580,6 @@ local fractal = { object_type = "Joker", dependencies = { items = { - "set_cry_misc_joker", "set_cry_poker_hand_stuff", }, }, @@ -6500,14 +8595,13 @@ local fractal = { return { vars = { center.ability.extra } } end, add_to_deck = function(self, card, from_debuff) - card.ability.extra = math.floor(card.ability.extra) - G.hand.config.highlighted_limit = G.hand.config.highlighted_limit + card.ability.extra + card.ability.extra = math.min(math.floor(card.ability.extra), 1000) + SMODS.change_play_limit(card.ability.extra) + SMODS.change_discard_limit(card.ability.extra) end, remove_from_deck = function(self, card, from_debuff) - G.hand.config.highlighted_limit = G.hand.config.highlighted_limit - card.ability.extra - if G.hand.config.highlighted_limit < 5 then - G.hand.config.highlighted_limit = 5 - end + SMODS.change_play_limit(-1 * card.ability.extra) + SMODS.change_discard_limit(-1 * card.ability.extra) if not G.GAME.before_play_buffer then G.hand:unhighlight_all() end @@ -6546,12 +8640,13 @@ local universe = { if not center.edition or (center.edition and not center.edition.cry_astral) then info_queue[#info_queue + 1] = G.P_CENTERS.e_cry_astral end - return { vars = { center.ability.extra.emult } } + return { vars = { number_format(center.ability.extra.emult) } } end, rarity = 3, cost = 6, order = 121, blueprint_compat = true, + demicoloncompat = true, calculate = function(self, card, context) if context.other_joker @@ -6568,15 +8663,19 @@ local universe = { })) end return { - message = localize({ type = "variable", key = "a_powmult", vars = { card.ability.extra.emult } }), - Emult_mod = card.ability.extra.emult, + message = localize({ + type = "variable", + key = "a_powmult", + vars = { number_format(card.ability.extra.emult) }, + }), + Emult_mod = lenient_bignum(card.ability.extra.emult), colour = G.C.DARK_EDITION, } end if context.individual and context.cardarea == G.play then if context.other_card.edition and context.other_card.edition.cry_astral == true then return { - e_mult = card.ability.extra.emult, + e_mult = lenient_bignum(card.ability.extra.emult), colour = G.C.DARK_EDITION, card = card, } @@ -6597,12 +8696,19 @@ local universe = { } else return { - e_mult = card.ability.extra.emult, + e_mult = lenient_bignum(card.ability.extra.emult), colour = G.C.DARK_EDITION, card = card, } end end + if context.forcetrigger then + return { + e_mult = lenient_bignum(card.ability.extra.emult), + colour = G.C.DARK_EDITION, + card = card, + } + end end, } local astral_bottle = { @@ -6628,6 +8734,7 @@ local astral_bottle = { cost = 6, order = 122, blueprint_compat = false, + demicoloncompat = true, loc_vars = function(self, info_queue, center) if not center.edition or (center.edition and not center.edition.cry_astral) then info_queue[#info_queue + 1] = G.P_CENTERS.e_cry_astral @@ -6640,7 +8747,7 @@ local astral_bottle = { } end, calculate = function(self, card, context) - if context.selling_self and not context.retrigger_joker and not context.blueprint then + if (context.selling_self and not context.retrigger_joker and not context.blueprint) or context.forcetrigger then local g = Cryptid.gameset(card) local effect = { { astral = true, perishable = true } } if g == "exp_modest" or g == "exp_mainline" then @@ -6696,18 +8803,19 @@ local kittyprinter = { atlas = "atlasone", order = 133, blueprint_compat = true, + demicoloncompat = true, loc_vars = function(self, info_queue, card) - return { vars = { card.ability.extra.Xmult } } + return { vars = { number_format(card.ability.extra.Xmult) } } end, calculate = function(self, card, context) - if context.joker_main then + if context.joker_main or context.forcetrigger then return { message = localize({ type = "variable", key = "a_xmult", - vars = { card.ability.extra.Xmult }, + vars = { number_format(card.ability.extra.Xmult) }, }), - Xmult_mod = card.ability.extra.Xmult, + Xmult_mod = lenient_bignum(card.ability.extra.Xmult), } end end, @@ -6724,12 +8832,30 @@ local kidnap = { order = 23, pos = { x = 1, y = 2 }, config = { - extra = 4, + extra = { money = 4 }, + }, + gameset_config = { + modest = { + extra = { + money = 1, + }, + }, }, rarity = 1, cost = 4, blueprint_compat = false, + demicoloncompat = true, loc_vars = function(self, info_queue, center) + info_queue[#info_queue + 1] = G.P_CENTERS.j_jolly + info_queue[#info_queue + 1] = G.P_CENTERS.j_zany + info_queue[#info_queue + 1] = G.P_CENTERS.j_mad + info_queue[#info_queue + 1] = G.P_CENTERS.j_crazy + info_queue[#info_queue + 1] = G.P_CENTERS.j_droll + info_queue[#info_queue + 1] = G.P_CENTERS.j_sly + info_queue[#info_queue + 1] = G.P_CENTERS.j_wily + info_queue[#info_queue + 1] = G.P_CENTERS.j_clever + info_queue[#info_queue + 1] = G.P_CENTERS.j_devious + info_queue[#info_queue + 1] = G.P_CENTERS.j_crafty local value = 0 if G.GAME and G.GAME.jokers_sold then for _, v in ipairs(G.GAME.jokers_sold) do @@ -6750,9 +8876,37 @@ local kidnap = { end end end - return { vars = { center.ability.extra, center.ability.extra * value } } + return { + vars = { + number_format(center.ability.extra.money), + number_format(lenient_bignum(to_big(center.ability.extra.money) * value)), + }, + } end, atlas = "atlasone", + calculate = function(self, card, context) + if context.forcetrigger then + local value = 0 + for _, v in ipairs(G.GAME.jokers_sold) do + if + G.P_CENTERS[v].effect == "Type Mult" + or G.P_CENTERS[v].effect == "Cry Type Mult" + or G.P_CENTERS[v].effect == "Cry Type Chips" + or G.P_CENTERS[v].effect == "Boost Kidnapping" + or ( + G.P_CENTERS[v].name == "Sly Joker" + or G.P_CENTERS[v].name == "Wily Joker" + or G.P_CENTERS[v].name == "Clever Joker" + or G.P_CENTERS[v].name == "Devious Joker" + or G.P_CENTERS[v].name == "Crafty Joker" + ) + then + value = value + 1 + end + end + ease_dollars(lenient_bignum(to_big(card.ability.extra.money) * value) or 0) + end + end, calc_dollar_bonus = function(self, card) local value = 0 for _, v in ipairs(G.GAME.jokers_sold) do @@ -6775,7 +8929,7 @@ local kidnap = { if value == 0 then return end - return card.ability.extra * value + return lenient_bignum(to_big(card.ability.extra.money) * value) end, cry_credits = { idea = { @@ -6799,14 +8953,17 @@ local exposed = { name = "cry-Exposed", key = "exposed", pos = { x = 0, y = 5 }, - config = { extra = 2 }, + config = { + extra = { retriggers = 2 }, + immutable = { max_retriggers = 40 }, + }, rarity = 3, cost = 8, order = 123, atlas = "atlastwo", blueprint_compat = true, loc_vars = function(self, info_queue, center) - return { vars = { math.min(40, center.ability.extra) } } + return { vars = { math.min(center.ability.immutable.max_retriggers, center.ability.extra.retriggers) } } end, update = function(self, card, dt) if G.deck and card.added_to_deck then @@ -6829,7 +8986,9 @@ local exposed = { if not context.other_card:is_face() then return { message = localize("k_again_ex"), - repetitions = math.min(40, card.ability.extra), + repetitions = to_number( + math.min(card.ability.immutable.max_retriggers, card.ability.extra.retriggers) + ), card = card, } end @@ -6846,14 +9005,17 @@ local mask = { name = "cry-Mask", key = "mask", pos = { x = 1, y = 5 }, - config = { extra = 3 }, + config = { + extra = { retriggers = 3 }, + immutable = { max_retriggers = 40 }, + }, rarity = 3, cost = 7, atlas = "atlastwo", order = 124, blueprint_compat = true, loc_vars = function(self, info_queue, center) - return { vars = { math.min(40, center.ability.extra) } } + return { vars = { math.min(center.ability.immutable.max_retriggers, center.ability.extra.retriggers) } } end, update = function(self, card, dt) if G.deck and card.added_to_deck then @@ -6876,7 +9038,9 @@ local mask = { if context.other_card:is_face() then return { message = localize("k_again_ex"), - repetitions = math.min(40, card.ability.extra), + repetitions = to_number( + math.min(card.ability.immutable.max_retriggers, card.ability.extra.retriggers) + ), card = card, } end @@ -6896,27 +9060,21 @@ local tropical_smoothie = { config = { extra = 1.5 }, rarity = 3, eternal_compat = false, + demicoloncompat = true, cost = 5, order = 125, atlas = "atlastwo", pools = { ["Food"] = true }, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra } } + return { vars = { number_format(center.ability.extra) } } end, calculate = function(self, card, context) - if context.selling_self then + if context.selling_self or context.forcetrigger then local check = false for i, v in pairs(G.jokers.cards) do if v ~= card then if not Card.no(v, "immutable", true) then - Cryptid.with_deck_effects(v, function(cards) - Cryptid.misprintize( - cards, - { min = card.ability.extra, max = card.ability.extra }, - nil, - true - ) - end) + Cryptid.manipulate(v, { value = card.ability.extra }) check = true end end @@ -6933,6 +9091,11 @@ local tropical_smoothie = { end end end, + cry_credits = { + art = { + "Ori", + }, + }, } local pumpkin = { object_type = "Joker", @@ -6947,15 +9110,23 @@ local pumpkin = { cost = 10, atlas = "atlastwo", order = 131, - config = { extra = { scoreReq = 50, enabled = true } }, + config = { + extra = { + scoreReq = 50, + enabled = true, + }, + }, blueprint_compat = true, eternal_compat = false, perishable_compat = false, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.scoreReq } } + return { vars = { number_format(center.ability.extra.scoreReq) } } end, calculate = function(self, card, context) - if context.game_over and G.GAME.chips / G.GAME.blind.chips >= to_big(card.ability.extra.scoreReq / 100) then + if + context.game_over + and to_big(G.GAME.chips / G.GAME.blind.chips) >= to_big(card.ability.extra.scoreReq / 100) + then G.E_MANAGER:add_event(Event({ func = function() G.hand_text_area.blind_chips:juice_up() @@ -7011,12 +9182,12 @@ local carved_pumpkin = { eternal_compat = false, perishable_compat = false, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.disables } } + return { vars = { number_format(center.ability.extra.disables) } } end, calculate = function(self, card, context) if context.end_of_round and not context.blueprint and not context.individual and not context.repetition then if G.GAME.blind:get_type() == "Boss" then - card.ability.extra.disables = card.ability.extra.disables - 1 + card.ability.extra.disables = lenient_bignum(to_big(card.ability.extra.disables) - 1) card:juice_up() if card.ability.extra.disables <= 0 then card:start_dissolve() @@ -7063,24 +9234,36 @@ local cookie = { cost = 4, atlas = "atlastwo", order = 133, - config = { extra = { chips = 200, chip_mod = 1 } }, + config = { + extra = { + chips = 200, + chip_mod = 1, + }, + }, blueprint_compat = true, eternal_compat = false, perishable_compat = false, + demicoloncompat = true, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.chips, center.ability.extra.chip_mod } } + return { + vars = { + number_format(center.ability.extra.chips), + number_format(center.ability.extra.chip_mod), + }, + } end, calculate = function(self, card, context) - if context.joker_main then + if context.joker_main or context.forcetrigger then return { card = card, - chip_mod = card.ability.extra.chips, - message = "+" .. card.ability.extra.chips, + chip_mod = lenient_bignum(card.ability.extra.chips), + message = "+" .. number_format(card.ability.extra.chips), colour = G.C.CHIPS, + operation = "-", } end if context.cry_press then - if card.ability.extra.chips - card.ability.extra.chip_mod <= 0 then + if to_big(card.ability.extra.chips) - to_big(card.ability.extra.chip_mod) <= to_big(0) then G.E_MANAGER:add_event(Event({ func = function() play_sound("tarot1") @@ -7111,15 +9294,16 @@ local cookie = { { message = localize("k_eaten_ex"), colour = G.C.CHIPS } ) else - card.ability.extra.chips = card.ability.extra.chips - card.ability.extra.chip_mod - card_eval_status_text( - card, - "extra", - nil, - nil, - nil, - { message = "-" .. card.ability.extra.chip_mod, colour = G.C.CHIPS } - ) + SMODS.scale_card(card, { + operation = "-", + ref_table = card.ability.extra, + ref_value = "chips", + scalar_value = "chip_mod", + scaling_message = { + message = "-" .. number_format(card.ability.extra.chip_mod), + colour = G.C.CHIPS, + }, + }) end end end, @@ -7145,26 +9329,29 @@ local necromancer = { name = "cry-Necromancer", key = "necromancer", pos = { x = 3, y = 5 }, - config = {}, + config = { + extra = {}, + immutable = { sell_cost_min = 0 }, + }, rarity = 2, cost = 5, atlas = "atlastwo", order = 126, immutable = true, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra } } + return { vars = { center.ability.immutable.sell_cost_min } } end, calculate = function(self, card, context) if context.selling_card - and context.card.sell_cost > 0 + and context.card.sell_cost > card.ability.immutable.sell_cost_min and context.card.config.center.set == "Joker" and G.GAME.jokers_sold and #G.GAME.jokers_sold > 0 and not context.blueprint and not context.retrigger_joker then - local card = create_card( + local new_card = create_card( "Joker", G.jokers, nil, @@ -7173,10 +9360,10 @@ local necromancer = { nil, G.GAME.jokers_sold[pseudorandom("cry_necromancer", 1, #G.GAME.jokers_sold)] ) - card.sell_cost = 0 - card:add_to_deck() - G.jokers:emplace(card) - card:start_materialize() + new_card.sell_cost = card.ability.immutable.sell_cost_min + new_card:add_to_deck() + G.jokers:emplace(new_card) + new_card:start_materialize() end end, cry_credits = { @@ -7206,11 +9393,12 @@ local oil_lamp = { --You want it? It's yours my friend cost = 10, order = 127, atlas = "atlastwo", + demicoloncompat = true, loc_vars = function(self, info_queue, card) card.ability.blueprint_compat_ui = card.ability.blueprint_compat_ui or "" card.ability.blueprint_compat_check = nil return { - vars = { card.ability.extra.increase }, + vars = { number_format(card.ability.extra.increase) }, main_end = (card.area and card.area == G.jokers) and { { n = G.UIT.C, @@ -7258,21 +9446,17 @@ local oil_lamp = { --You want it? It's yours my friend end end, calculate = function(self, card, context) - if context.end_of_round and not context.repetition and not context.individual and not context.blueprint then + if + (context.end_of_round and not context.repetition and not context.individual and not context.blueprint) + or context.forcetrigger + then local check = false for i = 1, #G.jokers.cards do if G.jokers.cards[i] == card then if i < #G.jokers.cards then if not Card.no(G.jokers.cards[i + 1], "immutable", true) then check = true - Cryptid.with_deck_effects(G.jokers.cards[i + 1], function(cards) - Cryptid.misprintize( - cards, - { min = card.ability.extra.increase, max = card.ability.extra.increase }, - nil, - true - ) - end) + Cryptid.manipulate(G.jokers.cards[i + 1], { value = card.ability.extra.increase }) end end end @@ -7316,6 +9500,7 @@ local tax_fraud = { cost = 10, order = 128, atlas = "atlastwo", + demicoloncompat = true, in_pool = function(self) if not G.GAME.modifiers.enable_rentals_in_shop then return false @@ -7323,11 +9508,22 @@ local tax_fraud = { return true end, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.money } } + return { vars = { number_format(center.ability.extra.money) } } + end, + calculate = function(self, card, context) + if context.forcetrigger then + ease_dollars( + lenient_bignum( + to_big(card.ability.extra.money) * #Cryptid.advanced_find_joker(nil, nil, nil, { "rental" }, true) + ) + ) + end end, calc_dollar_bonus = function(self, card) if #Cryptid.advanced_find_joker(nil, nil, nil, { "rental" }, true) ~= 0 then - return card.ability.extra.money * #Cryptid.advanced_find_joker(nil, nil, nil, { "rental" }, true) + return lenient_bignum( + to_big(card.ability.extra.money) * #Cryptid.advanced_find_joker(nil, nil, nil, { "rental" }, true) + ) end end, cry_credits = { @@ -7352,22 +9548,29 @@ local pity_prize = { }, name = "cry-Pity-Prize", key = "pity_prize", - blueprint_compat = true, pos = { x = 5, y = 5 }, config = {}, rarity = 1, cost = 2, atlas = "atlastwo", order = 129, + blueprint_compat = true, + demicoloncompat = true, loc_vars = function(self, info_queue, center) - return { vars = {} } + return { key = Cryptid.gameset_loc(self, { modest = "modest" }), vars = {} } end, calculate = function(self, card, context) - if context.skipping_booster then + if context.skipping_booster or context.forcetrigger then local tag_key repeat tag_key = get_next_tag_key("cry_pity_prize") until tag_key ~= "tag_boss" --I saw pickle not generating boss tags because it apparently causes issues, so I did the same here + + local tag = Cryptid.get_next_tag() + if tag then + tag_key = tag + end + -- this is my first time seeing repeat... wtf local tag = Tag(tag_key) tag.ability.shiny = Cryptid.is_shiny() @@ -7381,7 +9584,10 @@ local pity_prize = { tag.ability.orbital_hand = pseudorandom_element(_poker_hands, pseudoseed("cry_pity_prize")) end add_tag(tag) - if Card.get_gameset(card) == "modest" and not context.blueprint and not context.retrigger_joker then + if + Card.get_gameset(card) == "modest" + and ((not context.blueprint and not context.retrigger_joker) or context.forcetrigger) + then G.E_MANAGER:add_event(Event({ func = function() play_sound("tarot1") @@ -7441,7 +9647,7 @@ local digitalhallucinations = { config = { odds = 2 }, loc_vars = function(self, info_queue, card) return { - vars = { cry_prob(card.ability.cry_prob, card.ability.odds, card.ability.cry_rigged), card.ability.odds }, + vars = { SMODS.get_probability_vars(card, 1, card.ability.odds, "Digital Hallucinations") }, } end, atlas = "atlasthree", @@ -7451,13 +9657,9 @@ local digitalhallucinations = { calculate = function(self, card, context) -- you know, i was totally ready to do something smart here but vanilla hardcodes this stuff, so i will too -- some cards need to be handled slightly differently anyway, adding mod support can't really be automatic in some circumstances - if context.open_booster - and ( - pseudorandom("digi") - < cry_prob(card.ability.cry_prob, card.ability.odds, card.ability.cry_rigged) / card.ability.odds - ) + and (SMODS.pseudorandom_probability(card, "digi", 1, card.ability.odds, "Digital Hallucinations")) then local boosty = context.card -- finally mod compat? @@ -7616,7 +9818,7 @@ local arsonist = { if context.destroying_card then local eval = evaluate_poker_hand(context.full_hand) if next(eval["Full House"]) then - return not context.destroying_card.ability.eternal + return not SMODS.is_eternal(context.destroying_card) end end end, @@ -7642,16 +9844,28 @@ local zooble = { name = "cry-Zooble", key = "zooble", pos = { x = 1, y = 5 }, - config = { extra = { mult = 0, a_mult = 1 } }, + config = { + extra = { + mult = 0, + a_mult = 1, + }, + }, rarity = 2, cost = 6, atlas = "atlasone", order = 132, + blueprint_compat = true, + demicoloncompat = true, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.mult, center.ability.extra.a_mult } } + return { + vars = { + number_format(center.ability.extra.mult), + number_format(center.ability.extra.a_mult), + }, + } end, calculate = function(self, card, context) - if context.before and context.cardarea == G.jokers then + if context.before and context.cardarea == G.jokers and not context.blueprint then if not (next(context.poker_hands["Straight"]) or next(context.poker_hands["Straight Flush"])) then local unique_ranks = {} for i, v in pairs(context.scoring_hand) do @@ -7668,19 +9882,34 @@ local zooble = { end end if #unique_ranks >= 1 then - card.ability.extra.mult = card.ability.extra.mult + (#unique_ranks * card.ability.extra.a_mult) - return { - message = localize("k_upgrade_ex"), - colour = G.C.RED, - card = card, - } + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "mult", + scalar_value = "a_mult", + }) end end end - if context.joker_main and card.ability.extra.mult > 0 then + if context.joker_main and to_big(card.ability.extra.mult) > to_big(0) then return { - message = localize({ type = "variable", key = "a_mult", vars = { card.ability.extra.mult } }), - mult_mod = card.ability.extra.mult, + message = localize({ + type = "variable", + key = "a_mult", + vars = { number_format(card.ability.extra.mult) }, + }), + mult_mod = lenient_bignum(card.ability.extra.mult), + } + end + if context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "mult", + scalar_value = "a_mult", + message_key = "a_mult", + message_colour = G.C.RED, + }) + return { + mult_mod = lenient_bignum(card.ability.extra.mult), } end end, @@ -7700,31 +9929,47 @@ local lebaron_james = { object_type = "Joker", dependencies = { items = { - "set_cry_misc_joker", + "set_cry_meme", }, }, name = "cry-LeBaron James", pools = { ["Meme"] = true }, key = "lebaron_james", pos = { x = 2, y = 5 }, - config = { extra = { h_mod = 1 } }, + config = { + extra = { h_mod = 1 }, + immutable = { + max_h_mod = 1000, + added_h = 0, + }, + }, blueprint_compat = true, rarity = 3, cost = 6, atlas = "atlasone", order = 133, no_dbl = true, - immutable = true, -- has issues with value manip and not easy to fix loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.h_mod } } + return { vars = { center.ability.extra.h_mod, center.ability.immutable.added_h } } end, calculate = function(self, card, context) if context.cardarea == G.play and context.individual then if context.other_card:get_id() == 13 then - local h_size = math.max(0, math.min(1000 - 0, card.ability.extra.h_mod)) - G.hand:change_size(math.floor(h_size)) - G.GAME.round_resets.temp_handsize = (G.GAME.round_resets.temp_handsize or 0) + math.floor(h_size) - if math.floor(h_size) > 0 then + local h_mod = card.ability.extra.h_mod + local added_h = card.ability.immutable.added_h + local max_h_mod = card.ability.immutable.max_h_mod + + local available_h = math.max(0, max_h_mod - added_h) + local h_size = to_number(math.max(0, math.min(available_h, h_mod))) + + if h_size > 0 then + -- Apply hand size bonus + G.hand:change_size(math.floor(h_size)) + G.GAME.round_resets.temp_handsize = (G.GAME.round_resets.temp_handsize or 0) + math.floor(h_size) + + -- Update the added_h tracker + card.ability.immutable.added_h = added_h + math.floor(h_size) + return { message = localize({ type = "variable", key = "a_handsize", vars = { math.floor(h_size) } }), colour = G.C.FILTER, @@ -7791,7 +10036,7 @@ local huntingseason = { -- If played hand contains three cards, destroy the midd and not context.blueprint and not context.retrigger_joker then - return { remove = not context.destroy_card.ability.eternal } + return { remove = not SMODS.is_eternal(context.destroy_card) } end end, cry_credits = { @@ -7810,7 +10055,7 @@ local cat_owl = { -- Lucky Cards are considered Echo Cards and vice versa object_type = "Joker", dependencies = { items = { - "set_cry_misc_joker", + "set_cry_meme", "m_cry_echo", "set_cry_misc", }, @@ -7896,7 +10141,81 @@ local eyeofhagane = { art = { "Soren" }, }, } - +-- At the end of round: if the player has more than 19$ take away 19$ and make a random meme Joker +local familiar_currency = { + object_type = "Joker", + dependencies = { + items = { + "set_cry_meme", + }, + }, + name = "cry-Familiar Currency", + key = "familiar_currency", + pos = { x = 0, y = 6 }, + config = { extra = 19 }, + order = 137, + rarity = 3, + cost = 0, + blueprint_compat = true, + demicoloncompat = true, + atlas = "atlasone", + loc_vars = function(self, info_queue, center) + return { vars = { center.ability.extra } } + end, + calculate = function(self, card, context) + if + context.end_of_round + and not context.individual + and not context.repetition + and not (context.blueprint_card or card).getting_sliced + then + if + to_big(G.GAME.dollars - G.GAME.bankrupt_at) >= to_big(card.ability.extra) + and #G.jokers.cards + G.GAME.joker_buffer < G.jokers.config.card_limit + then + G.GAME.joker_buffer = G.GAME.joker_buffer + 1 + ease_dollars(-card.ability.extra) + G.E_MANAGER:add_event(Event({ + func = function() + SMODS.add_card({ set = "Meme", key_append = "fcc" }) + G.GAME.joker_buffer = 0 + return true + end, + })) + card_eval_status_text( + context.blueprint_card or card, + "extra", + nil, + nil, + nil, + { message = localize("k_plus_joker"), colour = G.C.BLUE } + ) + end + end + if context.forcetrigger then + ease_dollars(-card.ability.extra) + G.E_MANAGER:add_event(Event({ + func = function() + SMODS.add_card({ set = "Meme", key_append = "fcc" }) + G.GAME.joker_buffer = 0 + return true + end, + })) + end + end, + cry_credits = { + idea = { + "Gud Username", + "y_not_tony", + }, + code = { + "SDM_0", + }, + art = { + "Gud Username", + }, + }, +} local highfive = { object_type = "Joker", dependencies = { @@ -7966,6 +10285,538 @@ local highfive = { code = { "astrapboy" }, }, } +local sock_and_sock = { + cry_credits = { + idea = { + "lolxddj", + }, + art = { + "lolxddj", + }, + code = { + "70UNIK", + }, + }, + object_type = "Joker", + dependencies = { + items = { + "set_cry_misc_joker", + "m_cry_abstract", + }, + }, + name = "cry-sock_and_sock", + key = "sock_and_sock", + pos = { x = 6, y = 6 }, + config = { + extra = { retriggers = 1 }, + immutable = { max_retriggers = 40 }, + }, + enhancement_gate = "m_cry_abstract", + rarity = 2, + cost = 7, + order = 138, + atlas = "atlastwo", + blueprint_compat = true, + loc_vars = function(self, info_queue, center) + info_queue[#info_queue + 1] = G.P_CENTERS.m_cry_abstract + return { vars = { math.min(center.ability.immutable.max_retriggers, center.ability.extra.retriggers) } } + end, + calculate = function(self, card, context) + if context.repetition and context.cardarea == G.play then + if SMODS.has_enhancement(context.other_card, "m_cry_abstract") then + return { + message = localize("k_again_ex"), + repetitions = to_number( + math.min(card.ability.immutable.max_retriggers, card.ability.extra.retriggers) + ), + card = card, + } + end + end + end, +} +local brokenhome = { -- X11.4 Mult, 1 in 4 chance to self-destruct at end of round + cry_credits = { + idea = { + "Poppip10", + }, + art = { + "GeorgeTheRat", + }, + code = { + "gemstonez", + }, + }, + object_type = "Joker", + dependencies = { + items = { + "set_cry_meme", + }, + }, + name = "cry_brokenhome", + key = "brokenhome", + atlas = "atlasthree", + pos = { x = 1, y = 7 }, + rarity = 3, + cost = 8, + order = 139, + blueprint_compat = true, + eternal_compat = false, + demicoloncompat = true, + config = { extra = { Xmult = 11.4, odds = 4 } }, + gameset_config = { + modest = { + extra = { + Xmult = 3, + odds = 4, + }, + }, + }, + loc_vars = function(self, info_queue, card) -- the humble cavendish example mod: + return { + vars = { + card.ability.extra.Xmult, + SMODS.get_probability_vars(card, 1, card.ability.extra.odds, "Broken Home"), + }, + } + end, + calculate = function(self, card, context) + if context.joker_main then + return { + message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.Xmult } }), + Xmult_mod = card.ability.extra.Xmult, + } + end + if context.end_of_round and context.game_over == false and not context.repetition and not context.blueprint then + if SMODS.pseudorandom_probability(card, "brokenhome", 1, card.ability.extra.odds, "Broken Home") then + G.E_MANAGER:add_event(Event({ + func = function() + play_sound("tarot1") + card.T.r = -0.2 + card:juice_up(0.3, 0.4) + card.states.drag.is = true + card.children.center.pinch.x = true + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.3, + blockable = false, + func = function() + G.jokers:remove_card(card) + card:remove() + card = nil + return true + end, + })) + return true + end, + })) + return { + message = localize("cry_divorced"), + colour = G.C.FILTER, + } + else + return { + message = localize("k_safe_ex"), + colour = G.C.FILTER, + } + end + end + if context.forcetrigger then + if SMODS.pseudorandom_probability(card, "brokenhome", 1, card.ability.extra.odds, "Broken Home") then + G.E_MANAGER:add_event(Event({ + func = function() + play_sound("tarot1") + card.T.r = -0.2 + card:juice_up(0.3, 0.4) + card.states.drag.is = true + card.children.center.pinch.x = true + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.3, + blockable = false, + func = function() + G.jokers:remove_card(card) + card:remove() + card = nil + return true + end, + })) + return true + end, + })) + end + return { + message = localize({ type = "variable", key = "a_xmult", vars = { card.ability.extra.Xmult } }), + Xmult_mod = card.ability.extra.Xmult, + } + end + end, +} + +local yarnball = { -- +1 to all listed probabilities for the highest cat tag level + cry_credits = { + idea = { + "Saturn", + }, + art = { + "Darren_The_Frog", + }, + code = { + "Lily Felli", + }, + }, + object_type = "Joker", + dependencies = { + items = { + "tag_cry_cat", + }, + }, + name = "cry_yarnball", + key = "yarnball", + atlas = "atlasthree", + pos = { x = 2, y = 7 }, + rarity = 3, + cost = 8, + order = 140, + demicoloncompat = false, + in_pool = function(self) + if not G.GAME.tags or #G.GAME.tags == 0 then + return false + end + for _, tag in pairs(G.GAME.tags) do + if tag.key == "tag_cry_cat" then + return true + end + end + return false + end, + calculate = function(self, card, context) + if context.mod_probability and not context.blueprint then + local highest_cat_lvl = 0 + for _, tag in pairs(G.GAME.tags) do + local lvl = tag.ability.level + if highest_cat_lvl < 1 and tag.key == "tag_cry_cat" then + highest_cat_lvl = 1 + end + if lvl and lvl > highest_cat_lvl then + highest_cat_lvl = lvl + end + end + + return { + numerator = context.numerator + highest_cat_lvl, + } + end + end, +} + +local pizza = { + cry_credits = { + idea = { + "Enemui", + }, + art = { + "George The Rat", + }, + code = { + "lord.ruby", + }, + }, + object_type = "Joker", + dependencies = { + items = { + "set_cry_misc_joker", + "j_cry_pizza_slice", + }, + }, + name = "cry-pizza", + key = "pizza", + atlas = "atlastwo", + pos = { x = 6, y = 5 }, + rarity = 3, + cost = 8, + order = 141, + demicoloncompat = true, + eternal_compat = false, + blueprint_compat = true, + config = { extra = { rounds_needed = 3, rounds_left = 3, slices = 6 }, immutable = { max_spawn = 100 } }, + loc_vars = function(self, info_queue, card) + info_queue[#info_queue + 1] = G.P_CENTERS.j_cry_pizza_slice + return { + vars = { + number_format(card.ability.extra.rounds_needed), + number_format(card.ability.extra.rounds_left), + number_format(math.min(card.ability.extra.slices, card.ability.immutable.max_spawn)), + }, + } + end, + calculate = function(self, card, context) + if + context.end_of_round + and not context.retrigger_joker + and not context.blueprint + and not context.individual + and not context.repetition + then + card.ability.extra.rounds_left = card.ability.extra.rounds_left - 1 + if to_big(card.ability.extra.rounds_left) < to_big(0) then + card.ability.extra.rounds_left = 0 + else + return { + message = number_format(card.ability.extra.rounds_needed - card.ability.extra.rounds_left) + .. "/" + .. number_format(card.ability.extra.rounds_needed), + colour = G.C.FILTER, + } + end + end + if context.selling_self or context.forcetrigger then + if to_big(card.ability.extra.rounds_left) <= to_big(0) or context.forcetrigger then + for i = 1, to_number( + math.min( + math.min(card.ability.extra.slices, card.ability.immutable.max_spawn), + G.jokers.config.card_limit - #G.jokers.cards + 1 + ) + ) do + SMODS.add_card({ + key = "j_cry_pizza_slice", + area = G.jokers, + }) + end + end + end + end, +} + +local pizza_slice = { + cry_credits = { + idea = { + "Enemui", + }, + art = { + "George The Rat", + }, + code = { + "lord.ruby", + }, + }, + object_type = "Joker", + dependencies = { + items = { + "set_cry_misc_joker", + "j_cry_pizza", + }, + }, + name = "cry-pizza_slice", + key = "pizza_slice", + atlas = "atlastwo", + pos = { x = 6, y = 4 }, + rarity = 3, + cost = 8, + order = 141, + in_pool = function() + return false + end, + demicoloncompat = true, + eternal_compat = false, + blueprint_compat = true, + config = { extra = { xmult = 1, xmult_mod = 0.5 } }, + loc_vars = function(self, info_queue, card) + return { vars = { number_format(card.ability.extra.xmult_mod), number_format(card.ability.extra.xmult) } } + end, + calculate = function(self, card, context) + if context.selling_card and context.card and context.card.config.center.key == "j_cry_pizza_slice" then + if context.card ~= card then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "xmult", + scalar_value = "xmult_mod", + message_key = "a_xmult", + message_colour = G.C.RED, + no_message = context.forcetrigger, + }) + end + end + if context.joker_main or context.forcetrigger then + return { + Xmult_mod = lenient_bignum(card.ability.extra.xmult), + } + end + end, +} + +local paved_joker = { -- +1 to all listed probabilities for the highest cat tag level + cry_credits = { + idea = { + "InspectorB", + }, + art = { + "gemstonez", + }, + code = { + "lord.ruby", + }, + }, + object_type = "Joker", + dependencies = { + items = { + "set_cry_misc_joker", + }, + }, + name = "cry-paved_joker", + key = "paved_joker", + atlas = "atlasone", + pos = { x = 1, y = 6 }, + rarity = 1, + cost = 4, + order = 142, + config = { extra = 1 }, + loc_vars = function(self, info_queue, card) + return { vars = { number_format(math.floor(card.ability.extra)) } } + end, +} + +local fading_joker = { -- +1 to all listed probabilities for the highest cat tag level + cry_credits = { + idea = { + "DoNotSus", + }, + art = { + "lord.ruby", + }, + code = { + "lord.ruby", + }, + }, + object_type = "Joker", + dependencies = { + items = { + "set_cry_misc_joker", + }, + }, + name = "cry-paved_joker", + key = "fading_joker", + atlas = "atlasone", + pos = { x = 2, y = 6 }, + rarity = 2, + cost = 6, + order = 143, + demicoloncompat = true, + blueprint_compat = true, + config = { extra = { xmult = 1, xmult_mod = 1 } }, + loc_vars = function(self, info_queue, card) + return { vars = { number_format(card.ability.extra.xmult_mod), number_format(card.ability.extra.xmult) } } + end, + calculate = function(self, card, context) + if context.perishable_debuffed or context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "xmult", + scalar_value = "xmult_mod", + message_key = "a_xmult", + message_colour = G.C.RED, + no_message = context.forcetrigger, + }) + end + if context.joker_main or context.forcetrigger then + return { + message = localize({ + type = "variable", + key = "a_xmult", + vars = { number_format(card.ability.extra.xmult) }, + }), + Xmult_mod = lenient_bignum(card.ability.extra.xmult), + } + end + end, + in_pool = function() + for i, v in pairs(G.I.CARD) do + if v.perishable and v.perish_tally and to_big(v.perish_tally) > to_big(0) then + return true + end + end + end, + init = function() + local calcuate_parishable_ref = Card.calculate_perishable + function Card:calculate_perishable(...) + if self.ability.perish_tally == 1 then + SMODS.calculate_context({ perishable_debuffed = true, other_card = self, cardarea = self.area }) + end + return calcuate_parishable_ref(self, ...) + end + end, +} + +local poor_joker = { -- +1 to all listed probabilities for the highest cat tag level + cry_credits = { + idea = { + "DoNotSus", + }, + art = { + "Darren_the_frog", + }, + code = { + "lord.ruby", + }, + }, + object_type = "Joker", + dependencies = { + items = { + "set_cry_misc_joker", + }, + }, + name = "cry-poor_joker", + key = "poor_joker", + atlas = "atlasone", + pos = { x = 3, y = 6 }, + rarity = 2, + cost = 6, + order = 144, + demicoloncompat = true, + blueprint_compat = true, + config = { extra = { mult = 0, mult_mod = 4 } }, + loc_vars = function(self, info_queue, card) + return { vars = { number_format(card.ability.extra.mult_mod), number_format(card.ability.extra.mult) } } + end, + calculate = function(self, card, context) + if context.rental or context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "mult", + scalar_value = "mult_mod", + message_key = "a_mult", + message_colour = G.C.RED, + no_message = context.forcetrigger, + }) + end + if context.joker_main or context.forcetrigger then + return { + message = localize({ + type = "variable", + key = "a_mult", + vars = { number_format(card.ability.extra.mult) }, + }), + mult_mod = lenient_bignum(card.ability.extra.mult), + } + end + end, + in_pool = function() + for i, v in pairs(G.I.CARD) do + if v.rental then + return true + end + end + end, + init = function() + local calcuate_rental_ref = Card.calculate_rental + function Card:calculate_rental(...) + local ret = calcuate_rental_ref(self, ...) + SMODS.calculate_context({ rental = true, other_card = self, cardarea = self.area }) + return ret + end + end, +} + local miscitems = { jimball_sprite, dropshot, @@ -8070,6 +10921,12 @@ local miscitems = { stronghold, wtf, clash, + the, + annihalation, + undefined, + manylostminds, + nebulous, + wordscanteven, adroit, penetrating, treacherous, @@ -8081,8 +10938,18 @@ local miscitems = { huntingseason, --cat_owl, --eyeofhagane, (apparently this wasn't screened) + familiar_currency, highfive, + sock_and_sock, + brokenhome, + yarnball, + pizza, + pizza_slice, + paved_joker, + fading_joker, + poor_joker, } + return { name = "Misc. Jokers", init = function() diff --git a/Cryptid/items/planet.lua b/Cryptid/items/planet.lua index 7bbcb51..a24231c 100644 --- a/Cryptid/items/planet.lua +++ b/Cryptid/items/planet.lua @@ -1,322 +1,6 @@ -local timantti = { - cry_credits = { - idea = { - "Jevonn", - }, - art = { - "jenwalter666", - }, - code = { - "Math", - }, - }, - dependencies = { - items = { - "set_cry_planet", - }, - }, - object_type = "Consumable", - set = "Planet", - name = "cry-Timantti", - key = "Timantti", - pos = { x = 0, y = 2 }, - config = { hand_types = { "High Card", "Pair", "Two Pair" } }, - cost = 4, - aurinko = true, - atlas = "atlasnotjokers", - order = 8, - can_use = function(self, card) - return true - end, - loc_vars = function(self, info_queue, center) - return { - vars = { - localize("High Card", "poker_hands"), - localize("Pair", "poker_hands"), - localize("Two Pair", "poker_hands"), - number_format(G.GAME.hands["High Card"].level), - number_format(G.GAME.hands["Pair"].level), - number_format(G.GAME.hands["Two Pair"].level), - colours = { - ( - to_big(G.GAME.hands["High Card"].level) == to_big(1) and G.C.UI.TEXT_DARK - or G.C.HAND_LEVELS[to_big(math.min(7, G.GAME.hands["High Card"].level)):to_number()] - ), - (to_big(G.GAME.hands["Pair"].level) == to_big(1) and G.C.UI.TEXT_DARK or G.C.HAND_LEVELS[to_big( - math.min(7, G.GAME.hands["Pair"].level) - ):to_number()]), - ( - to_big(G.GAME.hands["Two Pair"].level) == to_big(1) and G.C.UI.TEXT_DARK - or G.C.HAND_LEVELS[to_big(math.min(7, G.GAME.hands["Two Pair"].level)):to_number()] - ), - }, - }, - } - end, - use = function(self, card, area, copier) - Cryptid.suit_level_up(card, copier, 1, card.config.center.config.hand_types) - end, - bulk_use = function(self, card, area, copier, number) - Cryptid.suit_level_up(card, copier, number, card.config.center.config.hand_types) - end, - calculate = function(self, card, context) - if - G.GAME.used_vouchers.v_observatory - and context.joker_main - and ( - context.scoring_name == "High Card" - or context.scoring_name == "Pair" - or context.scoring_name == "Two Pair" - ) - then - local value = G.P_CENTERS.v_observatory.config.extra - return { - message = localize({ type = "variable", key = "a_xmult", vars = { value } }), - Xmult_mod = value, - } - end - end, -} -local klubi = { - cry_credits = { - idea = { - "Jevonn", - }, - art = { - "jenwalter666", - }, - code = { - "Math", - }, - }, - dependencies = { - items = { - "set_cry_planet", - }, - }, - object_type = "Consumable", - set = "Planet", - name = "cry-Klubi", - key = "Klubi", - pos = { x = 1, y = 2 }, - config = { hand_types = { "Three of a Kind", "Straight", "Flush" } }, - cost = 4, - aurinko = true, - atlas = "atlasnotjokers", - order = 9, - can_use = function(self, card) - return true - end, - loc_vars = function(self, info_queue, center) - return { - vars = { - localize("Three of a Kind", "poker_hands"), - localize("Straight", "poker_hands"), - localize("Flush", "poker_hands"), - number_format(G.GAME.hands["Three of a Kind"].level), - number_format(G.GAME.hands["Straight"].level), - number_format(G.GAME.hands["Flush"].level), - colours = { - ( - to_big(G.GAME.hands["Three of a Kind"].level) == to_big(1) and G.C.UI.TEXT_DARK - or G.C.HAND_LEVELS[to_big(math.min(7, G.GAME.hands["Three of a Kind"].level)):to_number()] - ), - ( - to_big(G.GAME.hands["Straight"].level) == to_big(1) and G.C.UI.TEXT_DARK - or G.C.HAND_LEVELS[to_big(math.min(7, G.GAME.hands["Straight"].level)):to_number()] - ), - (to_big(G.GAME.hands["Flush"].level) == to_big(1) and G.C.UI.TEXT_DARK or G.C.HAND_LEVELS[to_big( - math.min(7, G.GAME.hands["Flush"].level) - ):to_number()]), - }, - }, - } - end, - use = function(self, card, area, copier) - Cryptid.suit_level_up(card, copier, 1, card.config.center.config.hand_types) - end, - bulk_use = function(self, card, area, copier, number) - Cryptid.suit_level_up(card, copier, number, card.config.center.config.hand_types) - end, - calculate = function(self, card, context) - if - G.GAME.used_vouchers.v_observatory - and context.joker_main - and ( - context.scoring_name == "Three of a Kind" - or context.scoring_name == "Straight" - or context.scoring_name == "Flush" - ) - then - local value = G.P_CENTERS.v_observatory.config.extra - return { - message = localize({ type = "variable", key = "a_xmult", vars = { value } }), - Xmult_mod = value, - } - end - end, -} -local sydan = { - cry_credits = { - idea = { - "Jevonn", - }, - art = { - "jenwalter666", - }, - code = { - "Math", - }, - }, - dependencies = { - items = { - "set_cry_planet", - }, - }, - object_type = "Consumable", - set = "Planet", - name = "cry-Sydan", - key = "Sydan", - pos = { x = 2, y = 2 }, - config = { hand_types = { "Full House", "Four of a Kind", "Straight Flush" } }, - cost = 4, - aurinko = true, - atlas = "atlasnotjokers", - order = 10, - can_use = function(self, card) - return true - end, - loc_vars = function(self, info_queue, center) - return { - vars = { - localize("Full House", "poker_hands"), - localize("Four of a Kind", "poker_hands"), - localize("Straight Flush", "poker_hands"), - number_format(G.GAME.hands["Full House"].level), - number_format(G.GAME.hands["Four of a Kind"].level), - number_format(G.GAME.hands["Straight Flush"].level), - colours = { - ( - to_big(G.GAME.hands["Full House"].level) == to_big(1) and G.C.UI.TEXT_DARK - or G.C.HAND_LEVELS[to_big(math.min(7, G.GAME.hands["Full House"].level)):to_number()] - ), - ( - to_big(G.GAME.hands["Four of a Kind"].level) == to_big(1) and G.C.UI.TEXT_DARK - or G.C.HAND_LEVELS[to_big(math.min(7, G.GAME.hands["Four of a Kind"].level)):to_number()] - ), - ( - to_big(G.GAME.hands["Straight Flush"].level) == to_big(1) and G.C.UI.TEXT_DARK - or G.C.HAND_LEVELS[to_big(math.min(7, G.GAME.hands["Straight Flush"].level)):to_number()] - ), - }, - }, - } - end, - use = function(self, card, area, copier) - Cryptid.suit_level_up(card, copier, 1, card.config.center.config.hand_types) - end, - bulk_use = function(self, card, area, copier, number) - Cryptid.suit_level_up(card, copier, number, card.config.center.config.hand_types) - end, - calculate = function(self, card, context) - if - G.GAME.used_vouchers.v_observatory - and context.joker_main - and ( - context.scoring_name == "Full House" - or context.scoring_name == "Four of a Kind" - or context.scoring_name == "Straight Flush" - ) - then - local value = G.P_CENTERS.v_observatory.config.extra - return { - message = localize({ type = "variable", key = "a_xmult", vars = { value } }), - Xmult_mod = value, - } - end - end, -} -local lapio = { - cry_credits = { - idea = { - "Jevonn", - }, - art = { - "jenwalter666", - }, - code = { - "Math", - }, - }, - dependencies = { - items = { - "set_cry_planet", - }, - }, - object_type = "Consumable", - set = "Planet", - name = "cry-Lapio", - key = "Lapio", - pos = { x = 3, y = 2 }, - config = { hand_types = { "Five of a Kind", "Flush House", "Flush Five" }, softlock = true }, - cost = 4, - aurinko = true, - atlas = "atlasnotjokers", - order = 11, - can_use = function(self, card) - return true - end, - loc_vars = function(self, info_queue, center) - return { - vars = { - localize("Five of a Kind", "poker_hands"), - localize("Flush House", "poker_hands"), - localize("Flush Five", "poker_hands"), - number_format(G.GAME.hands["Five of a Kind"].level), - number_format(G.GAME.hands["Flush House"].level), - number_format(G.GAME.hands["Flush Five"].level), - colours = { - ( - to_big(G.GAME.hands["Five of a Kind"].level) == to_big(1) and G.C.UI.TEXT_DARK - or G.C.HAND_LEVELS[to_big(math.min(7, G.GAME.hands["Five of a Kind"].level)):to_number()] - ), - ( - to_big(G.GAME.hands["Flush House"].level) == to_big(1) and G.C.UI.TEXT_DARK - or G.C.HAND_LEVELS[to_big(math.min(7, G.GAME.hands["Flush House"].level)):to_number()] - ), - ( - to_big(G.GAME.hands["Flush Five"].level) == to_big(1) and G.C.UI.TEXT_DARK - or G.C.HAND_LEVELS[to_big(math.min(7, G.GAME.hands["Flush Five"].level)):to_number()] - ), - }, - }, - } - end, - use = function(self, card, area, copier) - Cryptid.suit_level_up(card, copier, 1, card.config.center.config.hand_types) - end, - bulk_use = function(self, card, area, copier, number) - Cryptid.suit_level_up(card, copier, number, card.config.center.config.hand_types) - end, - calculate = function(self, card, context) - if - G.GAME.used_vouchers.v_observatory - and context.joker_main - and ( - context.scoring_name == "Five of a Kind" - or context.scoring_name == "Flush House" - or context.scoring_name == "Flush Five" - ) - then - local value = G.P_CENTERS.v_observatory.config.extra - return { - message = localize({ type = "variable", key = "a_xmult", vars = { value } }), - Xmult_mod = value, - } - end - end, -} -local kaikki = { +-- Asteroid Belt +-- Levels up Bulwark (+50/+1) +local abelt = { cry_credits = { idea = { "HexaCryonic", @@ -330,80 +14,277 @@ local kaikki = { }, dependencies = { items = { - "set_cry_planet", "set_cry_poker_hand_stuff", + "set_cry_planet", }, }, object_type = "Consumable", set = "Planet", - name = "cry-Kaikki", - key = "Kaikki", - pos = { x = 3, y = 5 }, - config = { hand_types = { "cry_Bulwark", "cry_Clusterfuck", "cry_UltPair" }, softlock = true }, - cost = 4, - aurinko = true, + key = "asteroidbelt", + config = { hand_type = "cry_Bulwark", softlock = true }, + pos = { x = 1, y = 5 }, + order = 1, atlas = "atlasnotjokers", - order = 12, - can_use = function(self, card) - return true + aurinko = true, + set_card_type_badge = function(self, card, badges) + badges[1] = create_badge(localize("k_planet_disc"), get_type_colour(self or card.config, card), nil, 1.2) end, loc_vars = function(self, info_queue, center) - local levelone = G.GAME.hands["cry_Bulwark"].level or 1 - local leveltwo = G.GAME.hands["cry_Clusterfuck"].level or 1 - local levelthree = G.GAME.hands["cry_UltPair"].level or 1 - local planetcolourone = G.C.HAND_LEVELS[math.min(levelone, 7)] - local planetcolourtwo = G.C.HAND_LEVELS[math.min(leveltwo, 7)] - local planetcolourthree = G.C.HAND_LEVELS[math.min(levelthree, 7)] - return { vars = { - localize("cry_Bulwark", "poker_hands"), - localize("cry_Clusterfuck", "poker_hands"), - localize("cry_UltPair", "poker_hands"), + localize("cry_hand_bulwark"), G.GAME.hands["cry_Bulwark"].level, - G.GAME.hands["cry_Clusterfuck"].level, - G.GAME.hands["cry_UltPair"].level, + G.GAME.hands["cry_Bulwark"].l_mult, + G.GAME.hands["cry_Bulwark"].l_chips, colours = { ( to_big(G.GAME.hands["cry_Bulwark"].level) == to_big(1) and G.C.UI.TEXT_DARK - or G.C.HAND_LEVELS[to_big(math.min(7, G.GAME.hands["cry_Bulwark"].level)):to_number()] - ), - ( - to_big(G.GAME.hands["cry_Clusterfuck"].level) == to_big(1) and G.C.UI.TEXT_DARK - or G.C.HAND_LEVELS[to_big(math.min(7, G.GAME.hands["cry_Clusterfuck"].level)):to_number()] - ), - ( - to_big(G.GAME.hands["cry_UltPair"].level) == to_big(1) and G.C.UI.TEXT_DARK - or G.C.HAND_LEVELS[to_big(math.min(7, G.GAME.hands["cry_UltPair"].level)):to_number()] + or G.C.HAND_LEVELS[to_number(math.min(7, G.GAME.hands["cry_Bulwark"].level))] ), }, }, } end, - use = function(self, card, area, copier) - Cryptid.suit_level_up(card, copier, 1, card.config.center.config.hand_types) - end, - bulk_use = function(self, card, area, copier, number) - Cryptid.suit_level_up(card, copier, number, card.config.center.config.hand_types) - end, - calculate = function(self, card, context) - if - G.GAME.used_vouchers.v_observatory - and context.joker_main - and ( - context.scoring_name == "cry_Bulwark" - or context.scoring_name == "cry_Clusterfuck" - or context.scoring_name == "cry_UltPair" - ) - then - local value = G.P_CENTERS.v_observatory.config.extra - return { - message = localize({ type = "variable", key = "a_xmult", vars = { value } }), - Xmult_mod = value, - } - end + generate_ui = 0, + demicoloncompat = true, + force_use = function(self, card, area) + card:use_consumeable(area) end, } +-- Void +-- Upgrades Clusterfuck (+40/+4) +local void = { + cry_credits = { + idea = { + "HexaCryonic", + }, + art = { + "HexaCryonic", + }, + code = { + "HexaCryonic", + }, + }, + dependencies = { + items = { + "set_cry_poker_hand_stuff", + "set_cry_planet", + }, + }, + object_type = "Consumable", + set = "Planet", + key = "void", + order = 2, + config = { hand_type = "cry_Clusterfuck", softlock = true }, + pos = { x = 0, y = 5 }, + atlas = "atlasnotjokers", + aurinko = true, + set_card_type_badge = function(self, card, badges) + badges[1] = create_badge("", get_type_colour(self or card.config, card), nil, 1.2) + end, + loc_vars = function(self, info_queue, center) + return { + vars = { + localize("cry_Clusterfuck"), + G.GAME.hands["cry_Clusterfuck"].level, + G.GAME.hands["cry_Clusterfuck"].l_mult, + G.GAME.hands["cry_Clusterfuck"].l_chips, + colours = { + ( + to_big(G.GAME.hands["cry_Clusterfuck"].level) == to_big(1) and G.C.UI.TEXT_DARK + or G.C.HAND_LEVELS[to_number(math.min(7, G.GAME.hands["cry_Clusterfuck"].level))] + ), + }, + }, + } + end, + generate_ui = 0, + demicoloncompat = true, + force_use = function(self, card, area) + card:use_consumeable(area) + end, +} +-- Phobos & Deimos +-- Upgrades Ultimate Pair (+40/+4) +local marsmoons = { + cry_credits = { + idea = { + "HexaCryonic", + }, + art = { + "HexaCryonic", + }, + code = { + "HexaCryonic", + }, + }, + dependencies = { + items = { + "set_cry_poker_hand_stuff", + "set_cry_planet", + }, + }, + object_type = "Consumable", + set = "Planet", + key = "marsmoons", + order = 3, + config = { hand_type = "cry_UltPair", softlock = true }, + pos = { x = 2, y = 5 }, + atlas = "atlasnotjokers", + aurinko = true, + set_card_type_badge = function(self, card, badges) + badges[1] = create_badge(localize("k_planet_satellite"), get_type_colour(self or card.config, card), nil, 1.2) + end, + loc_vars = function(self, info_queue, center) + local levelone = G.GAME.hands["cry_UltPair"].level or 1 + local planetcolourone = G.C.HAND_LEVELS[math.min(levelone, 7)] + if levelone == 1 then + planetcolourone = G.C.UI.TEXT_DARK + end + return { + vars = { + localize("cry_UltPair"), + G.GAME.hands["cry_UltPair"].level, + G.GAME.hands["cry_UltPair"].l_mult, + G.GAME.hands["cry_UltPair"].l_chips, + colours = { + ( + to_big(G.GAME.hands["cry_UltPair"].level) == to_big(1) and G.C.UI.TEXT_DARK + or G.C.HAND_LEVELS[to_number(math.min(7, G.GAME.hands["cry_UltPair"].level))] + ), + }, + }, + } + end, + generate_ui = 0, + demicoloncompat = true, + force_use = function(self, card, area) + card:use_consumeable(area) + end, +} + +-- Order 4 reserved for possible None planet +-- hehehehehehe +local nibiru = { + cry_credits = { + idea = { + "cassknows", + }, + art = { + "cassknows", + }, + }, + dependencies = { + items = { + "set_cry_poker_hand_stuff", + "set_cry_planet", + }, + }, + object_type = "Consumable", + set = "Planet", + key = "nibiru", + order = 4, + config = { hand_type = "cry_None", softlock = true }, + pos = { x = 0, y = 6 }, + atlas = "atlasnotjokers", + aurinko = true, + set_card_type_badge = function(self, card, badges) + --use whichever of these fits best, the second literally just removes the badge, and the first is a blank badge + --badges[1] = create_badge("", get_type_colour(self or card.config, card), nil, 1.2) + + if badges[1] and badges[1].remove then + badges[1]:remove() + end + badges[1] = nil + end, + loc_vars = function(self, info_queue, center) + local levelone = G.GAME.hands["cry_None"].level or 1 + local planetcolourone = G.C.HAND_LEVELS[math.min(levelone, 7)] + if levelone == 1 then + planetcolourone = G.C.UI.TEXT_DARK + end + return { + vars = { + localize("cry_None"), + G.GAME.hands["cry_None"].level, + G.GAME.hands["cry_None"].l_mult, + G.GAME.hands["cry_None"].l_chips, + colours = { + ( + to_big(G.GAME.hands["cry_None"].level) == to_big(1) and G.C.UI.TEXT_DARK + or G.C.HAND_LEVELS[to_number(math.min(7, G.GAME.hands["cry_None"].level))] + ), + }, + }, + } + end, + generate_ui = 0, + demicoloncompat = true, + force_use = function(self, card, area) + card:use_consumeable(area) + end, + cry_credits = { + art = { "cassknows" }, + code = { "lord-ruby" }, + }, +} + +-- The Universe In Its Fucking Entirety +-- Upgrades The Entire Fucking Deck (+5.25252e28/+5.25252e27) +local universe = { + cry_credits = { + idea = { + "HexaCryonic", + }, + art = { + "HexaCryonic", + }, + code = { + "HexaCryonic", + }, + }, + dependencies = { + items = { + "set_cry_poker_hand_stuff", + "set_cry_planet", + }, + }, + object_type = "Consumable", + set = "Planet", + key = "universe", + config = { hand_type = "cry_WholeDeck", softlock = true }, + pos = { x = 4, y = 5 }, + order = 5, + atlas = "atlasnotjokers", + aurinko = true, + set_card_type_badge = function(self, card, badges) + badges[1] = create_badge(localize("k_planet_universe"), get_type_colour(self or card.config, card), nil, 1.2) + end, + loc_vars = function(self, info_queue, center) + return { + vars = { + localize("cry_WholeDeck"), + G.GAME.hands["cry_WholeDeck"].level, + G.GAME.hands["cry_WholeDeck"].l_mult, + G.GAME.hands["cry_WholeDeck"].l_chips, + colours = { + ( + to_big(G.GAME.hands["cry_WholeDeck"].level) == to_big(1) and G.C.UI.TEXT_DARK + or G.C.HAND_LEVELS[to_number(math.min(7, G.GAME.hands["cry_WholeDeck"].level))] + ), + }, + }, + } + end, + generate_ui = 0, + demicoloncompat = true, + force_use = function(self, card, area) + card:use_consumeable(area) + end, +} + +-- Planet.lua +-- 1 in 5 to upgrade Every poker hand local planetlua = { cry_credits = { idea = { @@ -430,12 +311,80 @@ local planetlua = { cost = 4, aurinko = true, atlas = "atlasnotjokers", - order = 1, + order = 101, loc_vars = function(self, info_queue, card) + local aaa, bbb = SMODS.get_probability_vars(card, 1, card.ability.extra.odds, "Planet.lua") + local xmulttexts = {} + local loc_mult = " " .. (localize("k_mult")) .. " " + for i = 0, 100 do + xmulttexts[#xmulttexts + 1] = "X" .. (1 + (i / 100)) + end + local o_plua = { + -- For people "borrowing" this code: There's a lovely patch done in order to get this to work properly on infoqueues, if you don't need this on infoqueues then ignore this line + -- Small "Correction" to center text a bit more + { n = G.UIT.T, config = { text = " ", colour = G.C.WHITE, scale = 0.32 } }, + -- Xmult text + { + n = G.UIT.C, + config = { align = "m", colour = G.C.RED, r = 0.05, padding = 0.03, res = 0.15 }, + nodes = { + { + n = G.UIT.O, + config = { + object = DynaText({ + string = xmulttexts, + colours = { G.C.WHITE }, + pop_in_rate = 9999999, + silent = true, + random_element = true, + pop_delay = 0.5, + scale = 0.32, + min_cycle_time = 0, + }), + }, + }, + }, + }, + -- Mult Text + { + n = G.UIT.O, + config = { + object = DynaText({ + string = { + { string = "rand()", colour = G.C.JOKER_GREY }, + { string = "#@" .. (Cryptid.get_m_jokers()) .. "M", colour = G.C.RED }, + loc_mult, + loc_mult, + loc_mult, + loc_mult, + loc_mult, + loc_mult, + loc_mult, + loc_mult, + loc_mult, + loc_mult, + loc_mult, + loc_mult, + loc_mult, + }, + colours = { G.C.UI.TEXT_DARK }, + pop_in_rate = 9999999, + silent = true, + random_element = true, + pop_delay = 0.2011, + scale = 0.32, + min_cycle_time = 0, + }), + }, + }, + } + if Cryptid.safe_get(G, "GAME", "used_vouchers", "v_observatory") then + info_queue[#info_queue + 1] = { key = "o_planetlua", set = "Other", plua_extra = o_plua } + end return { vars = { - card and cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged) or 1, - card and card.ability.extra.odds or self.config.extra.odds, + aaa, + bbb, }, } end, @@ -444,11 +393,7 @@ local planetlua = { end, use = function(self, card, area, copier) local used_consumable = copier or card - if - pseudorandom("planetlua") - < cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged) - / card.ability.extra.odds - then --Code "borrowed" from black hole + if SMODS.pseudorandom_probability(card, "planetlua", 1, card.ability.extra.odds, "Planet.lua") then --Code "borrowed" from black hole update_hand_text( { sound = "button", volume = 0.7, pitch = 0.8, delay = 0.3 }, { handname = localize("k_all_hands"), chips = "...", mult = "...", level = "" } @@ -592,8 +537,7 @@ local planetlua = { for i = 1, number do quota = quota + ( - pseudorandom("planetlua") - < cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged) / card.ability.extra.odds + SMODS.pseudorandom_probability(card, "planetlua", 1, card.ability.extra.odds, "Planet.lua") and 1 or 0 ) @@ -691,24 +635,36 @@ local planetlua = { end end end, - calculate = function(self, card, context) --Observatory effect: (G.GAME.probabilities.normal) in (odds) chance for (G.P_CENTERS.v_observatory.config.extra) Mult - if - G.GAME.used_vouchers.v_observatory - and context.joker_main - and ( - pseudorandom("nstar") - < cry_prob(card.ability.cry_prob, card.ability.extra.odds, card.ability.cry_rigged) - / card.ability.extra.odds - ) - then - local value = G.P_CENTERS.v_observatory.config.extra + calculate = function(self, card, context) --Observatory effect: Variable XMult + if G.GAME.used_vouchers.v_observatory and context.joker_main then + pseudorandom("cry_googol_play") + local aaa = pseudorandom("mstar") + local limit = Card.get_gameset(card) == "modest" and 2 or 1e100 + local formula = aaa + (0.07 * (aaa ^ 5 / (1 - aaa ^ 2))) + local value = Cryptid.nuke_decimals(math.min(limit, 1.7 ^ formula), 2) + --[[ + + OverFlow Compat TODO + It needs to be done in a way that keep expected score consistent between having 1 big stack and several smaller stacks + and ideally doesn't cause a lot of lag at large stacks like the bulk_use does + + if Overflow then + value = value ^ to_big(card:getQty()) + end + ]] return { message = localize({ type = "variable", key = "a_xmult", vars = { value } }), Xmult_mod = value, } end end, + demicoloncompat = true, + force_use = function(self, card, area) + card:use_consumeable(area) + end, } +-- Neutron Star +-- Upgrades a random hand by 1 per Neutron Star used this run local nstar = { cry_credits = { idea = { @@ -742,13 +698,14 @@ local nstar = { return true end, loc_vars = function(self, info_queue, center) - return { vars = { (G.GAME and G.GAME.neutronstarsusedinthisrun or 0) } } + local aaa = Cryptid.safe_get(G, "GAME", "neutronstarsusedinthisrun") or 0 + if Cryptid.safe_get(G, "GAME", "used_vouchers", "v_observatory") then + info_queue[#info_queue + 1] = { key = "o_nstar", set = "Other", specific_vars = { 0.1, (1 + (0.1 * aaa)) } } + end + return { vars = { aaa } } end, use = function(self, card, area, copier) local used_consumable = copier or card - --Get amount of Neutron stars use this run or set to 0 if nil - G.GAME.neutronstarsusedinthisrun = G.GAME.neutronstarsusedinthisrun or 0 - --Add +1 to amount of neutron stars used this run G.GAME.neutronstarsusedinthisrun = G.GAME.neutronstarsusedinthisrun + 1 local neutronhand = Cryptid.get_random_hand(nil, "nstar" .. G.GAME.round_resets.ante) --Random poker hand @@ -767,8 +724,6 @@ local nstar = { end, bulk_use = function(self, card, area, copier, number) local used_consumable = copier or card - G.GAME.neutronstarsusedinthisrun = G.GAME.neutronstarsusedinthisrun or 0 - local handstolv = {} local neutronhand = "n/a" for i = 1, number do @@ -806,14 +761,18 @@ local nstar = { })) end, calculate = function(self, card, context) --Observatory effect: X0.1 mult for each neutron star used this run - if G.GAME.used_vouchers.v_observatory and G.GAME.neutronstarsusedinthisrun ~= nil and context.joker_main then + if G.GAME.used_vouchers.v_observatory and G.GAME.neutronstarsusedinthisrun > 0 and context.joker_main then + local value = G.GAME.neutronstarsusedinthisrun + if Overflow then + value = value ^ to_big(card:getQty()) + end return { message = localize({ type = "variable", key = "a_xmult", - vars = { 1 + (0.10 * G.GAME.neutronstarsusedinthisrun) }, + vars = { 1 + (0.10 * value) }, }), - Xmult_mod = 1 + (0.10 * G.GAME.neutronstarsusedinthisrun), + Xmult_mod = 1 + (0.10 * value), } end end, @@ -843,7 +802,13 @@ local nstar = { return chosen_hand end end, + demicoloncompat = true, + force_use = function(self, card, area) + card:use_consumeable(area) + end, } +-- Sol +-- Upgrades Ascended Hand Power local sunplanet = { cry_credits = { idea = { @@ -857,7 +822,6 @@ local sunplanet = { "Toneblock", }, }, - --TODO: disable ascendant hands if this is disabled dependencies = { items = { "set_cry_planet", @@ -872,9 +836,9 @@ local sunplanet = { cost = 4, aurinko = true, atlas = "atlasnotjokers", - order = 7, + order = 150, config = { - extra = 0.05, + extra = { modest = 0.1, not_modest = 0.05 }, }, set_card_type_badge = function(self, card, badges) badges[1] = create_badge(localize("cry_p_star"), get_type_colour(self or card.config, card), nil, 1.2) @@ -884,12 +848,13 @@ local sunplanet = { end, use = function(self, card, area, copier) local used_consumable = copier or card - local sunlevel = (G.GAME.sunlevel and G.GAME.sunlevel or 0) + 1 - G.GAME.sunlevel = (G.GAME.sunlevel or 0) + 1 + G.GAME.sunlevel = G.GAME.sunlevel + 1 + G.GAME.sunnumber.modest = G.GAME.sunnumber.modest + card.ability.extra.modest + G.GAME.sunnumber.not_modest = G.GAME.sunnumber.not_modest + card.ability.extra.not_modest delay(0.4) update_hand_text( { sound = "button", volume = 0.7, pitch = 0.8, delay = 0.3 }, - { handname = localize("cry_asc_hands"), chips = "...", mult = "...", level = to_big(sunlevel) } + { handname = localize("cry_asc_hands"), chips = "...", mult = "...", level = to_big(G.GAME.sunlevel - 1) } ) delay(1.0) G.E_MANAGER:add_event(Event({ @@ -899,48 +864,7 @@ local sunplanet = { play_sound("tarot1") ease_colour(G.C.UI_CHIPS, copy_table(G.C.GOLD), 0.1) ease_colour(G.C.UI_MULT, copy_table(G.C.GOLD), 0.1) - Cryptid.pulse_flame(0.01, sunlevel) - used_consumable:juice_up(0.8, 0.5) - G.E_MANAGER:add_event(Event({ - trigger = "after", - blockable = false, - blocking = false, - delay = 1.2, - func = function() - ease_colour(G.C.UI_CHIPS, G.C.BLUE, 1) - ease_colour(G.C.UI_MULT, G.C.RED, 1) - return true - end, - })) - return true - end, - })) - update_hand_text({ sound = "button", volume = 0.7, pitch = 0.9, delay = 0 }, { level = to_big(sunlevel + 1) }) - delay(2.6) - G.GAME.sunnumber = G.GAME.sunnumber ~= nil and G.GAME.sunnumber + card.ability.extra or card.ability.extra - update_hand_text( - { sound = "button", volume = 0.7, pitch = 1.1, delay = 0 }, - { mult = 0, chips = 0, handname = "", level = "" } - ) - end, - bulk_use = function(self, card, area, copier, number) - local used_consumable = copier or card - local sunlevel = (G.GAME.sunlevel and G.GAME.sunlevel or 0) + 1 - G.GAME.sunlevel = (G.GAME.sunlevel or 0) + 1 - delay(0.4) - update_hand_text( - { sound = "button", volume = 0.7, pitch = 0.8, delay = 0.3 }, - { handname = localize("cry_asc_hands"), chips = "...", mult = "...", level = to_big(sunlevel) } - ) - delay(1.0) - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.2, - func = function() - play_sound("tarot1") - ease_colour(G.C.UI_CHIPS, copy_table(G.C.GOLD), 0.1) - ease_colour(G.C.UI_MULT, copy_table(G.C.GOLD), 0.1) - Cryptid.pulse_flame(0.01, (sunlevel - 1) + number) + Cryptid.pulse_flame(0.01, G.GAME.sunlevel) used_consumable:juice_up(0.8, 0.5) G.E_MANAGER:add_event(Event({ trigger = "after", @@ -958,43 +882,117 @@ local sunplanet = { })) update_hand_text( { sound = "button", volume = 0.7, pitch = 0.9, delay = 0 }, - { level = to_big(sunlevel + number) } + { level = to_big(G.GAME.sunlevel) } ) delay(2.6) - G.GAME.sunnumber = G.GAME.sunnumber ~= nil and G.GAME.sunnumber + number * card.ability.extra - or number * card.ability.extra update_hand_text( { sound = "button", volume = 0.7, pitch = 1.1, delay = 0 }, { mult = 0, chips = 0, handname = "", level = "" } ) end, - calculate = function(self, card, context) --Observatory effect: X1.5 mult if hand is an ascended hand - if - G.GAME.used_vouchers.v_observatory - and G.GAME.current_round.current_hand.cry_asc_num ~= 0 - and context.joker_main - then - local value = G.P_CENTERS.v_observatory.config.extra - return { - message = localize({ type = "variable", key = "a_xmult", vars = { value } }), - Xmult_mod = value, - } - end + bulk_use = function(self, card, area, copier, number) + local used_consumable = copier or card + G.GAME.sunlevel = G.GAME.sunlevel + number + G.GAME.sunnumber.modest = G.GAME.sunnumber.modest + number * card.ability.extra.modest + G.GAME.sunnumber.not_modest = G.GAME.sunnumber.not_modest + number * card.ability.extra.not_modest + delay(0.4) + update_hand_text({ sound = "button", volume = 0.7, pitch = 0.8, delay = 0.3 }, { + handname = localize("cry_asc_hands"), + chips = "...", + mult = "...", + level = to_big(G.GAME.sunlevel - number), + }) + delay(1.0) + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.2, + func = function() + play_sound("tarot1") + ease_colour(G.C.UI_CHIPS, copy_table(G.C.GOLD), 0.1) + ease_colour(G.C.UI_MULT, copy_table(G.C.GOLD), 0.1) + Cryptid.pulse_flame(0.01, G.GAME.sunlevel) + used_consumable:juice_up(0.8, 0.5) + G.E_MANAGER:add_event(Event({ + trigger = "after", + blockable = false, + blocking = false, + delay = 1.2, + func = function() + ease_colour(G.C.UI_CHIPS, G.C.BLUE, 1) + ease_colour(G.C.UI_MULT, G.C.RED, 1) + return true + end, + })) + return true + end, + })) + update_hand_text( + { sound = "button", volume = 0.7, pitch = 0.9, delay = 0 }, + { level = to_big(G.GAME.sunlevel) } + ) + delay(2.6) + update_hand_text( + { sound = "button", volume = 0.7, pitch = 1.1, delay = 0 }, + { mult = 0, chips = 0, handname = "", level = "" } + ) end, loc_vars = function(self, info_queue, center) - local levelone = (G.GAME.sunlevel and G.GAME.sunlevel or 0) + 1 + local levelone = Cryptid.safe_get(G, "GAME", "sunlevel") or 1 local planetcolourone = G.C.HAND_LEVELS[math.min(levelone, 7)] + if G.STAGE == G.STAGES.RUN then + local modest = Cryptid.gameset(G.P_CENTERS.c_cry_sunplanet) == "modest" + local current_power = Cryptid.safe_get(G, "GAME", "current_round", "current_hand", "cry_asc_num") + or Cryptid.calculate_ascension_power( + nil, + nil, + nil, + G.GAME.used_vouchers.v_cry_hyperspacetether, + G.GAME.bonus_asc_power + ) + local multiplier = modest and 1 + ((0.25 + G.GAME.sunnumber.modest) * current_power) + or (1.25 + G.GAME.sunnumber.not_modest) ^ current_power + info_queue[#info_queue + 1] = { + key = "asc_misc" .. (modest and 2 or ""), + set = "Other", + specific_vars = { + current_power, + multiplier, + modest and (G.GAME.sunnumber.modest + 0.25) or (G.GAME.sunnumber.not_modest + 1.25), + }, + } + end + if Cryptid.safe_get(G, "GAME", "used_vouchers", "v_observatory") then + local observatory_power = 0 + if #find_joker("cry-sunplanet") == 1 then + observatory_power = 1 + elseif #find_joker("cry-sunplanet") > 1 then + observatory_power = Cryptid.funny_log(2, #find_joker("cry-sunplanet") + 1) + end + info_queue[#info_queue + 1] = { key = "o_sunplanet", set = "Other", specific_vars = { observatory_power } } + end if levelone == 1 then planetcolourone = G.C.UI.TEXT_DARK end - return { - vars = { - (G.GAME.sunlevel or 0) + 1, - center.ability.extra or 0.05, - (G.GAME.sunnumber and G.GAME.sunnumber or 0) + 1.25, - colours = { planetcolourone }, - }, - } + if Cryptid.gameset(center) == "modest" then + return { + vars = { + levelone, + center.ability.extra.modest, + (Cryptid.safe_get(G, "GAME", "sunnumber", "modest") or 0) + 0.25, + colours = { planetcolourone }, + }, + key = "c_cry_sunplanet2", + } + else + return { + vars = { + levelone, + center.ability.extra.not_modest, + (Cryptid.safe_get(G, "GAME", "sunnumber", "not_modest") or 0) + 1.25, + colours = { planetcolourone }, + }, + } + end end, in_pool = function(self) if G.GAME.cry_asc_played and G.GAME.cry_asc_played > 0 then @@ -1002,54 +1000,370 @@ local sunplanet = { end return false end, + demicoloncompat = true, + force_use = function(self, card, area) + card:use_consumeable(area) + end, } -local abelt = { +-- Ruutu +-- Upgrades High Card, Pair and Two Pair +local ruutu = { cry_credits = { idea = { - "HexaCryonic", + "Jevonn", }, art = { - "HexaCryonic", + "jenwalter666", }, code = { - "HexaCryonic", + "Math", }, }, dependencies = { items = { - "set_cry_poker_hand_stuff", + "set_cry_planet", }, }, object_type = "Consumable", set = "Planet", - key = "asteroidbelt", - config = { hand_type = "cry_Bulwark", softlock = true }, - pos = { x = 1, y = 5 }, - order = 2, - atlas = "atlasnotjokers", + name = "cry-Ruutu", + key = "Timantii", + pos = { x = 0, y = 2 }, + config = { hand_types = { "High Card", "Pair", "Two Pair" } }, + cost = 4, aurinko = true, - set_card_type_badge = function(self, card, badges) - badges[1] = create_badge(localize("k_planet_disc"), get_type_colour(self or card.config, card), nil, 1.2) + atlas = "atlasnotjokers", + order = 151, + can_use = function(self, card) + return true end, loc_vars = function(self, info_queue, center) return { vars = { - localize("cry_hand_bulwark"), - G.GAME.hands["cry_Bulwark"].level, - G.GAME.hands["cry_Bulwark"].l_mult, - G.GAME.hands["cry_Bulwark"].l_chips, + localize("High Card", "poker_hands"), + localize("Pair", "poker_hands"), + localize("Two Pair", "poker_hands"), + number_format(G.GAME.hands["High Card"].level), + number_format(G.GAME.hands["Pair"].level), + number_format(G.GAME.hands["Two Pair"].level), colours = { ( - to_big(G.GAME.hands["cry_Bulwark"].level) == to_big(1) and G.C.UI.TEXT_DARK - or G.C.HAND_LEVELS[to_big(math.min(7, G.GAME.hands["cry_Bulwark"].level)):to_number()] + to_big(G.GAME.hands["High Card"].level) == to_big(1) and G.C.UI.TEXT_DARK + or G.C.HAND_LEVELS[to_number(math.min(7, G.GAME.hands["High Card"].level))] + ), + ( + to_big(G.GAME.hands["Pair"].level) == to_big(1) and G.C.UI.TEXT_DARK + or G.C.HAND_LEVELS[to_number(math.min(7, G.GAME.hands["Pair"].level))] + ), + ( + to_big(G.GAME.hands["Two Pair"].level) == to_big(1) and G.C.UI.TEXT_DARK + or G.C.HAND_LEVELS[to_number(math.min(7, G.GAME.hands["Two Pair"].level))] ), }, }, } end, - generate_ui = 0, + use = function(self, card, area, copier) + Cryptid.suit_level_up(card, copier, 1, card.config.center.config.hand_types) + end, + bulk_use = function(self, card, area, copier, number) + Cryptid.suit_level_up(card, copier, number, card.config.center.config.hand_types) + end, + calculate = function(self, card, context) + if + G.GAME.used_vouchers.v_observatory + and context.joker_main + and ( + context.scoring_name == "High Card" + or context.scoring_name == "Pair" + or context.scoring_name == "Two Pair" + ) + then + local value = G.P_CENTERS.v_observatory.config.extra + if Overflow then + value = value ^ to_big(card:getQty()) + end + return { + message = localize({ type = "variable", key = "a_xmult", vars = { value } }), + Xmult_mod = value, + } + end + end, + demicoloncompat = true, + force_use = function(self, card, area) + card:use_consumeable(area) + end, } -local void = { +-- Risti +-- Upgrades Three Of A Kind, Straight and Flush +local risti = { + cry_credits = { + idea = { + "Jevonn", + }, + art = { + "jenwalter666", + }, + code = { + "Math", + }, + }, + dependencies = { + items = { + "set_cry_planet", + }, + }, + object_type = "Consumable", + set = "Planet", + name = "cry-Risti", + key = "Klubi", + pos = { x = 1, y = 2 }, + config = { hand_types = { "Three of a Kind", "Straight", "Flush" } }, + cost = 4, + aurinko = true, + atlas = "atlasnotjokers", + order = 152, + can_use = function(self, card) + return true + end, + loc_vars = function(self, info_queue, center) + return { + vars = { + localize("Three of a Kind", "poker_hands"), + localize("Straight", "poker_hands"), + localize("Flush", "poker_hands"), + number_format(G.GAME.hands["Three of a Kind"].level), + number_format(G.GAME.hands["Straight"].level), + number_format(G.GAME.hands["Flush"].level), + colours = { + ( + to_big(G.GAME.hands["Three of a Kind"].level) == to_big(1) and G.C.UI.TEXT_DARK + or G.C.HAND_LEVELS[to_number(math.min(7, G.GAME.hands["Three of a Kind"].level))] + ), + ( + to_big(G.GAME.hands["Straight"].level) == to_big(1) and G.C.UI.TEXT_DARK + or G.C.HAND_LEVELS[to_number(math.min(7, G.GAME.hands["Straight"].level))] + ), + ( + to_big(G.GAME.hands["Flush"].level) == to_big(1) and G.C.UI.TEXT_DARK + or G.C.HAND_LEVELS[to_number(math.min(7, G.GAME.hands["Flush"].level))] + ), + }, + }, + } + end, + use = function(self, card, area, copier) + Cryptid.suit_level_up(card, copier, 1, card.config.center.config.hand_types) + end, + bulk_use = function(self, card, area, copier, number) + Cryptid.suit_level_up(card, copier, number, card.config.center.config.hand_types) + end, + calculate = function(self, card, context) + if + G.GAME.used_vouchers.v_observatory + and context.joker_main + and ( + context.scoring_name == "Three of a Kind" + or context.scoring_name == "Straight" + or context.scoring_name == "Flush" + ) + then + local value = G.P_CENTERS.v_observatory.config.extra + if Overflow then + value = value ^ to_big(card:getQty()) + end + return { + message = localize({ type = "variable", key = "a_xmult", vars = { value } }), + Xmult_mod = value, + } + end + end, + demicoloncompat = true, + force_use = function(self, card, area) + card:use_consumeable(area) + end, +} +-- Hertta +-- Upgrades Full House, Four Of A Kind and Straight Flush +local hertta = { + cry_credits = { + idea = { + "Jevonn", + }, + art = { + "jenwalter666", + }, + code = { + "Math", + }, + }, + dependencies = { + items = { + "set_cry_planet", + }, + }, + object_type = "Consumable", + set = "Planet", + name = "cry-Hertta", + key = "Sydan", + pos = { x = 2, y = 2 }, + config = { hand_types = { "Full House", "Four of a Kind", "Straight Flush" } }, + cost = 4, + aurinko = true, + atlas = "atlasnotjokers", + order = 153, + can_use = function(self, card) + return true + end, + loc_vars = function(self, info_queue, center) + return { + vars = { + localize("Full House", "poker_hands"), + localize("Four of a Kind", "poker_hands"), + localize("Straight Flush", "poker_hands"), + number_format(G.GAME.hands["Full House"].level), + number_format(G.GAME.hands["Four of a Kind"].level), + number_format(G.GAME.hands["Straight Flush"].level), + colours = { + ( + to_big(G.GAME.hands["Full House"].level) == to_big(1) and G.C.UI.TEXT_DARK + or G.C.HAND_LEVELS[to_number(math.min(7, G.GAME.hands["Full House"].level))] + ), + ( + to_big(G.GAME.hands["Four of a Kind"].level) == to_big(1) and G.C.UI.TEXT_DARK + or G.C.HAND_LEVELS[to_number(math.min(7, G.GAME.hands["Four of a Kind"].level))] + ), + ( + to_big(G.GAME.hands["Straight Flush"].level) == to_big(1) and G.C.UI.TEXT_DARK + or G.C.HAND_LEVELS[to_number(math.min(7, G.GAME.hands["Straight Flush"].level))] + ), + }, + }, + } + end, + use = function(self, card, area, copier) + Cryptid.suit_level_up(card, copier, 1, card.config.center.config.hand_types) + end, + bulk_use = function(self, card, area, copier, number) + Cryptid.suit_level_up(card, copier, number, card.config.center.config.hand_types) + end, + calculate = function(self, card, context) + if + G.GAME.used_vouchers.v_observatory + and context.joker_main + and ( + context.scoring_name == "Full House" + or context.scoring_name == "Four of a Kind" + or context.scoring_name == "Straight Flush" + ) + then + local value = G.P_CENTERS.v_observatory.config.extra + if Overflow then + value = value ^ to_big(card:getQty()) + end + return { + message = localize({ type = "variable", key = "a_xmult", vars = { value } }), + Xmult_mod = value, + } + end + end, + demicoloncompat = true, + force_use = function(self, card, area) + card:use_consumeable(area) + end, +} +-- Pata +-- Upgrades Five Of A Kind, Flush House and Flush Five +local pata = { + cry_credits = { + idea = { + "Jevonn", + }, + art = { + "jenwalter666", + }, + code = { + "Math", + }, + }, + dependencies = { + items = { + "set_cry_planet", + }, + }, + object_type = "Consumable", + set = "Planet", + name = "cry-Pata", + key = "Lapio", + pos = { x = 3, y = 2 }, + config = { hand_types = { "Five of a Kind", "Flush House", "Flush Five" }, softlock = true }, + cost = 4, + aurinko = true, + atlas = "atlasnotjokers", + order = 154, + can_use = function(self, card) + return true + end, + loc_vars = function(self, info_queue, center) + return { + vars = { + localize("Five of a Kind", "poker_hands"), + localize("Flush House", "poker_hands"), + localize("Flush Five", "poker_hands"), + number_format(G.GAME.hands["Five of a Kind"].level), + number_format(G.GAME.hands["Flush House"].level), + number_format(G.GAME.hands["Flush Five"].level), + colours = { + ( + to_big(G.GAME.hands["Five of a Kind"].level) == to_big(1) and G.C.UI.TEXT_DARK + or G.C.HAND_LEVELS[to_number(math.min(7, G.GAME.hands["Five of a Kind"].level))] + ), + ( + to_big(G.GAME.hands["Flush House"].level) == to_big(1) and G.C.UI.TEXT_DARK + or G.C.HAND_LEVELS[to_number(math.min(7, G.GAME.hands["Flush House"].level))] + ), + ( + to_big(G.GAME.hands["Flush Five"].level) == to_big(1) and G.C.UI.TEXT_DARK + or G.C.HAND_LEVELS[to_number(math.min(7, G.GAME.hands["Flush Five"].level))] + ), + }, + }, + } + end, + use = function(self, card, area, copier) + Cryptid.suit_level_up(card, copier, 1, card.config.center.config.hand_types) + end, + bulk_use = function(self, card, area, copier, number) + Cryptid.suit_level_up(card, copier, number, card.config.center.config.hand_types) + end, + calculate = function(self, card, context) + if + G.GAME.used_vouchers.v_observatory + and context.joker_main + and ( + context.scoring_name == "Five of a Kind" + or context.scoring_name == "Flush House" + or context.scoring_name == "Flush Five" + ) + then + local value = G.P_CENTERS.v_observatory.config.extra + if Overflow then + value = value ^ to_big(card:getQty()) + end + return { + message = localize({ type = "variable", key = "a_xmult", vars = { value } }), + Xmult_mod = value, + } + end + end, + demicoloncompat = true, + force_use = function(self, card, area) + card:use_consumeable(area) + end, +} +-- Kaikki +-- Upgrades Bulwark, Clusterfuck and Ultimate Pair +local kaikki = { cry_credits = { idea = { "HexaCryonic", @@ -1063,135 +1377,217 @@ local void = { }, dependencies = { items = { + "set_cry_planet", "set_cry_poker_hand_stuff", }, }, object_type = "Consumable", set = "Planet", - key = "void", - order = 3, - config = { hand_type = "cry_Clusterfuck", softlock = true }, - pos = { x = 0, y = 5 }, - atlas = "atlasnotjokers", + name = "cry-Kaikki", + key = "Kaikki", + pos = { x = 3, y = 5 }, + config = { hand_types = { "cry_Bulwark", "cry_Clusterfuck", "cry_UltPair" }, softlock = true }, + cost = 4, aurinko = true, - set_card_type_badge = function(self, card, badges) - badges[1] = create_badge("", get_type_colour(self or card.config, card), nil, 1.2) + atlas = "atlasnotjokers", + order = 155, + can_use = function(self, card) + return true end, loc_vars = function(self, info_queue, center) + local levelone = G.GAME.hands["cry_Bulwark"].level or 1 + local leveltwo = G.GAME.hands["cry_Clusterfuck"].level or 1 + local levelthree = G.GAME.hands["cry_UltPair"].level or 1 + local planetcolourone = G.C.HAND_LEVELS[math.min(levelone, 7)] + local planetcolourtwo = G.C.HAND_LEVELS[math.min(leveltwo, 7)] + local planetcolourthree = G.C.HAND_LEVELS[math.min(levelthree, 7)] + return { vars = { - localize("cry_Clusterfuck"), + localize("cry_Bulwark", "poker_hands"), + localize("cry_Clusterfuck", "poker_hands"), + localize("cry_UltPair", "poker_hands"), + G.GAME.hands["cry_Bulwark"].level, G.GAME.hands["cry_Clusterfuck"].level, - G.GAME.hands["cry_Clusterfuck"].l_mult, - G.GAME.hands["cry_Clusterfuck"].l_chips, + G.GAME.hands["cry_UltPair"].level, colours = { + ( + to_big(G.GAME.hands["cry_Bulwark"].level) == to_big(1) and G.C.UI.TEXT_DARK + or G.C.HAND_LEVELS[to_number(math.min(7, G.GAME.hands["cry_Bulwark"].level))] + ), ( to_big(G.GAME.hands["cry_Clusterfuck"].level) == to_big(1) and G.C.UI.TEXT_DARK - or G.C.HAND_LEVELS[to_big(math.min(7, G.GAME.hands["cry_Clusterfuck"].level)):to_number()] + or G.C.HAND_LEVELS[to_number(math.min(7, G.GAME.hands["cry_Clusterfuck"].level))] ), - }, - }, - } - end, - generate_ui = 0, -} -local marsmoons = { - cry_credits = { - idea = { - "HexaCryonic", - }, - art = { - "HexaCryonic", - }, - code = { - "HexaCryonic", - }, - }, - dependencies = { - items = { - "set_cry_poker_hand_stuff", - }, - }, - object_type = "Consumable", - set = "Planet", - key = "marsmoons", - order = 4, - config = { hand_type = "cry_UltPair", softlock = true }, - pos = { x = 2, y = 5 }, - atlas = "atlasnotjokers", - aurinko = true, - set_card_type_badge = function(self, card, badges) - badges[1] = create_badge(localize("k_planet_satellite"), get_type_colour(self or card.config, card), nil, 1.2) - end, - loc_vars = function(self, info_queue, center) - local levelone = G.GAME.hands["cry_UltPair"].level or 1 - local planetcolourone = G.C.HAND_LEVELS[math.min(levelone, 7)] - if levelone == 1 then - planetcolourone = G.C.UI.TEXT_DARK - end - return { - vars = { - localize("cry_UltPair"), - G.GAME.hands["cry_UltPair"].level, - G.GAME.hands["cry_UltPair"].l_mult, - G.GAME.hands["cry_UltPair"].l_chips, - colours = { ( to_big(G.GAME.hands["cry_UltPair"].level) == to_big(1) and G.C.UI.TEXT_DARK - or G.C.HAND_LEVELS[to_big(math.min(7, G.GAME.hands["cry_UltPair"].level)):to_number()] + or G.C.HAND_LEVELS[to_number(math.min(7, G.GAME.hands["cry_UltPair"].level))] ), }, }, } end, - generate_ui = 0, + use = function(self, card, area, copier) + Cryptid.suit_level_up(card, copier, 1, card.config.center.config.hand_types) + end, + bulk_use = function(self, card, area, copier, number) + Cryptid.suit_level_up(card, copier, number, card.config.center.config.hand_types) + end, + calculate = function(self, card, context) + if + G.GAME.used_vouchers.v_observatory + and context.joker_main + and ( + context.scoring_name == "cry_Bulwark" + or context.scoring_name == "cry_Clusterfuck" + or context.scoring_name == "cry_UltPair" + ) + then + local value = G.P_CENTERS.v_observatory.config.extra + if Overflow then + value = value ^ to_big(card:getQty()) + end + return { + message = localize({ type = "variable", key = "a_xmult", vars = { value } }), + Xmult_mod = value, + } + end + end, + demicoloncompat = true, + force_use = function(self, card, area) + card:use_consumeable(area) + end, } -local universe = { +-- order 166 reserved for suit planet of TEFD, None and Sol +local voxel = { cry_credits = { idea = { "HexaCryonic", }, art = { "HexaCryonic", + "Icyethics", }, code = { - "HexaCryonic", + "lord.ruby", }, }, dependencies = { items = { - "set_cry_poker_hand_stuff", + "set_cry_planet", + "set_cry_code", + "c_cry_declare", }, }, object_type = "Consumable", set = "Planet", - key = "universe", - config = { hand_type = "cry_WholeDeck", softlock = true }, - pos = { x = 4, y = 5 }, - order = 5, - atlas = "atlasnotjokers", + name = "cry-Voxel", + key = "voxel", + pos = { x = 1, y = 6 }, + config = { hand_types = { "cry_Declare0", "cry_Declare1", "cry_Declare2" }, softlock = true }, + cost = 4, aurinko = true, - set_card_type_badge = function(self, card, badges) - badges[1] = create_badge(localize("k_planet_universe"), get_type_colour(self or card.config, card), nil, 1.2) + atlas = "atlasnotjokers", + order = 167, + can_use = function(self, card) + return true end, loc_vars = function(self, info_queue, center) + local levelone = G.GAME.hands["cry_Declare0"] and G.GAME.hands["cry_Declare0"].level or 1 + local leveltwo = G.GAME.hands["cry_Declare1"] and G.GAME.hands["cry_Declare1"].level or 1 + local levelthree = G.GAME.hands["cry_Declare2"] and G.GAME.hands["cry_Declare2"].level or 1 + local planetcolourone = G.C.HAND_LEVELS[math.min(levelone, 7)] + local planetcolourtwo = G.C.HAND_LEVELS[math.min(leveltwo, 7)] + local planetcolourthree = G.C.HAND_LEVELS[math.min(levelthree, 7)] + return { vars = { - localize("cry_UltPair"), - G.GAME.hands["cry_WholeDeck"].level, - G.GAME.hands["cry_WholeDeck"].l_mult, - G.GAME.hands["cry_WholeDeck"].l_chips, + G.GAME.hands["cry_Declare0"] and G.GAME.hands["cry_Declare0"].declare_cards and localize( + "cry_Declare0", + "poker_hands" + ) or localize("cry_code_empty"), + G.GAME.hands["cry_Declare1"] and G.GAME.hands["cry_Declare1"].declare_cards and localize( + "cry_Declare1", + "poker_hands" + ) or localize("cry_code_empty"), + G.GAME.hands["cry_Declare2"] and G.GAME.hands["cry_Declare2"].declare_cards and localize( + "cry_Declare2", + "poker_hands" + ) or localize("cry_code_empty"), + G.GAME.hands["cry_Declare0"] and G.GAME.hands["cry_Declare0"].level or 1, + G.GAME.hands["cry_Declare1"] and G.GAME.hands["cry_Declare1"].level or 1, + G.GAME.hands["cry_Declare2"] and G.GAME.hands["cry_Declare2"].level or 1, colours = { ( - to_big(G.GAME.hands["cry_Bulwark"].level) == to_big(1) and G.C.UI.TEXT_DARK - or G.C.HAND_LEVELS[to_big(math.min(7, G.GAME.hands["cry_WholeDeck"].level)):to_number()] + to_big(G.GAME.hands["cry_Declare0"] and G.GAME.hands["cry_Declare0"].level or 1) + == to_big(1) + and G.C.UI.TEXT_DARK + or G.C.HAND_LEVELS[to_number( + math.min(7, G.GAME.hands["cry_Declare0"] and G.GAME.hands["cry_Declare0"].level or 1) + )] + ), + ( + to_big(G.GAME.hands["cry_Declare1"] and G.GAME.hands["cry_Declare1"].level or 1) + == to_big(1) + and G.C.UI.TEXT_DARK + or G.C.HAND_LEVELS[to_number( + math.min(7, G.GAME.hands["cry_Declare1"] and G.GAME.hands["cry_Declare1"].level or 1) + )] + ), + ( + to_big(G.GAME.hands["cry_Declare2"] and G.GAME.hands["cry_Declare2"].level or 1) + == to_big(1) + and G.C.UI.TEXT_DARK + or G.C.HAND_LEVELS[to_number( + math.min(7, G.GAME.hands["cry_Declare2"] and G.GAME.hands["cry_Declare2"].level or 1) + )] ), }, }, } end, - generate_ui = 0, + use = function(self, card, area, copier) + local hand_types = { + G.GAME.hands.cry_Declare0 and G.GAME.hands.cry_Declare0.declare_cards and "cry_Declare0", + G.GAME.hands.cry_Declare1 and G.GAME.hands.cry_Declare1.declare_cards and "cry_Declare1", + G.GAME.hands.cry_Declare2 and G.GAME.hands.cry_Declare2.declare_cards and "cry_Declare2", + } + Cryptid.suit_level_up(card, copier, 1, hand_types) + end, + bulk_use = function(self, card, area, copier, number) + local hand_types = { + G.GAME.hands.cry_Declare0 and G.GAME.hands.cry_Declare0.declare_cards and "cry_Declare0", + G.GAME.hands.cry_Declare1 and G.GAME.hands.cry_Declare1.declare_cards and "cry_Declare1", + G.GAME.hands.cry_Declare2 and G.GAME.hands.cry_Declare2.declare_cards and "cry_Declare2", + } + Cryptid.suit_level_up(card, copier, number, hand_types) + end, + calculate = function(self, card, context) + if + G.GAME.used_vouchers.v_observatory + and context.joker_main + and ( + context.scoring_name == "cry_Declare0" + or context.scoring_name == "cry_Declare1" + or context.scoring_name == "cry_Declare2" + ) + then + local value = G.P_CENTERS.v_observatory.config.extra + if Overflow then + value = value ^ to_big(card:getQty()) + end + return { + message = localize({ type = "variable", key = "a_xmult", vars = { value } }), + Xmult_mod = value, + } + end + end, + demicoloncompat = true, + force_use = function(self, card, area) + card:use_consumeable(area) + end, } + function Cryptid.suit_level_up(card, copier, number, poker_hands, message) local used_consumable = copier or card if not number then @@ -1224,6 +1620,28 @@ function Cryptid.suit_level_up(card, copier, number, poker_hands, message) { mult = 0, chips = 0, handname = "", level = "" } ) end -local planet_cards = - { planetlua, nstar, timantti, klubi, sydan, lapio, sunplanet, kaikki, abelt, void, marsmoons, universe } -return { name = "Planets", init = function() end, items = planet_cards } +local planet_cards = { + abelt, + void, + marsmoons, + -- reserved for None + nibiru, + universe, + + planetlua, + nstar, + + sunplanet, + ruutu, + risti, + hertta, + pata, + kaikki, + -- reserved for tefd/none/sol suit planet + voxel, +} +return { + name = "Planets", + init = function() end, + items = planet_cards, +} diff --git a/Cryptid/items/pointer.lua b/Cryptid/items/pointer.lua new file mode 100644 index 0000000..d0e3883 --- /dev/null +++ b/Cryptid/items/pointer.lua @@ -0,0 +1,2725 @@ +local pointer = { + cry_credits = { + idea = { + "HexaCryonic", + }, + art = { + "HexaCryonic", + }, + code = { + "Math", + }, + }, + dependencies = { + items = { + "set_cry_code", + "set_cry_spectral", + }, + }, + object_type = "Consumable", + set = "Spectral", + name = "cry-Pointer", + key = "pointer", + pos = { x = 11, y = 3 }, + hidden = true, + soul_set = "Code", + order = 20001, + atlas = "atlasnotjokers", + can_use = function(self, card) + return true + end, + use = function(self, card, area, copier) + if not card.ability.cry_multiuse or to_big(card.ability.cry_multiuse) <= to_big(1) then + G.GAME.CODE_DESTROY_CARD = copy_card(card) + G.consumeables:emplace(G.GAME.CODE_DESTROY_CARD) + else + card.ability.cry_multiuse = card.ability.cry_multiuse + 1 + end + G.GAME.USING_CODE = true + G.OVERLAY_MENU_POINTER = true + G.E_MANAGER:add_event(Event({ + func = function() + G.GAME.USING_POINTER = true + G.FUNCS.overlay_menu({ definition = create_UIBox_your_collection() }) + return true + end, + })) + G.E_MANAGER:add_event(Event({ + func = function() + check_for_unlock({ cry_used_consumable = "c_cry_pointer" }) + return true + end, + })) + G.GAME.POINTER_SUBMENU = nil + end, + init = function(self) + local ccl = Card.click + function Card:click() + if G.GAME.USING_POINTER then + if not self.debuff then + if self.config.center.consumeable then + local copy = copy_card(self) + copy:add_to_deck() + G.consumeables:emplace(copy) + G.FUNCS.exit_overlay_menu_code() + ccl(self) + elseif self.config.center.set == "Booster" then + G.FUNCS.exit_overlay_menu_code() + local card = copy_card(self) + card.cost = 0 + card.from_tag = true + G.FUNCS.use_card({ config = { ref_table = card } }) + card:start_materialize() + created = true + ccl(self) + elseif + self.config.center.key == "c_base" + or self.config.center.set == "Enhanced" + or self.edition + or G.GAME.POINTER_SUBMENU == "Edition" + then + --submenu stuff + if G.GAME.POINTER_SUBMENU == "Rank" then + G.GAME.POINTER_PLAYING.rank = self.base.value + G.FUNCS.overlay_menu({ + definition = create_UIBox_pointer_suit(), + }) + elseif G.GAME.POINTER_SUBMENU == "Suit" then + G.GAME.POINTER_PLAYING.suit = self.base.suit + G.FUNCS.overlay_menu({ + definition = create_UIBox_pointer_enhancement(), + }) + elseif G.GAME.POINTER_SUBMENU == "Enhancement" then + G.GAME.POINTER_PLAYING.center = self.config.center.key + G.FUNCS.overlay_menu({ + definition = create_UIBox_pointer_edition(), + }) + elseif G.GAME.POINTER_SUBMENU == "Edition" then + if self.edition then + G.GAME.POINTER_PLAYING.edition = self.edition.key + end + G.FUNCS.overlay_menu({ + definition = create_UIBox_pointer_seal(), + }) + elseif G.GAME.POINTER_SUBMENU == "Seal" then + G.GAME.POINTER_PLAYING.seal = self.seal + local card = SMODS.create_card({ + key = G.GAME.POINTER_PLAYING.center, + rank = G.GAME.POINTER_PLAYING.rank, + suit = G.GAME.POINTER_PLAYING.suit, + }) + card:set_ability(G.P_CENTERS[G.GAME.POINTER_PLAYING.center]) + if G.GAME.POINTER_PLAYING.seal then + card:set_seal(G.GAME.POINTER_PLAYING.seal) + end + if G.GAME.POINTER_PLAYING.edition then + card:set_edition(G.GAME.POINTER_PLAYING.edition) + end + if G.STATE == G.STATES.SELECTING_HAND then + G.hand:emplace(card) + else + G.deck:emplace(card) + end + table.insert(G.playing_cards, card) + G.FUNCS.exit_overlay_menu_code() + G.GAME.POINTER_PLAYING = nil + end + else + G.ENTERED_CARD = self.config.center.key + local ret = G.FUNCS.pointer_apply() + G.FUNCS.pointer_cancel() + if ret then + G.FUNCS.exit_overlay_menu_code() + ccl(self) + else + G.GAME.USING_CODE = true + G.GAME.USING_POINTER = true + end + end + end + else + ccl(self) + end + end + local emplace_ref = CardArea.emplace + function CardArea:emplace(card, ...) + if G.GAME.USING_POINTER then + if Cryptid.pointergetblist(card.config.center.key)[1] then + card.debuff = true + end + end + return emplace_ref(self, card, ...) + end + + function create_UIBox_pointer(card) + G.E_MANAGER:add_event(Event({ + blockable = false, + func = function() + G.REFRESH_ALERTS = true + return true + end, + })) + local t = create_UIBox_generic_options({ + no_back = true, + colour = HEX("04200c"), + outline_colour = G.C.SECONDARY_SET.Code, + contents = { + { + n = G.UIT.R, + nodes = { + create_text_input({ + colour = G.C.SET.Code, + hooked_colour = darken(copy_table(G.C.SET.Code), 0.3), + w = 4.5, + h = 1, + max_length = 100, + extended_corpus = true, + prompt_text = localize("cry_code_enter_card"), + ref_table = G, + ref_value = "ENTERED_CARD", + keyboard_offset = 1, + }), + }, + }, + { + n = G.UIT.R, + config = { align = "cm" }, + nodes = { + UIBox_button({ + colour = G.C.SET.Code, + button = "pointer_apply", + label = { localize("cry_code_create") }, + minw = 4.5, + focus_args = { snap_to = true }, + }), + }, + }, + { + n = G.UIT.R, + config = { align = "cm" }, + nodes = { + UIBox_button({ + colour = G.C.SET.Code, + button = "your_collection", + label = { localize("b_collection_cap") }, + minw = 4.5, + focus_args = { snap_to = true }, + }), + }, + }, + { + n = G.UIT.R, + config = { align = "cm" }, + nodes = { + UIBox_button({ + colour = G.C.RED, + button = "pointer_apply_previous", + label = { localize("cry_code_create_previous") }, + minw = 4.5, + focus_args = { snap_to = true }, + }), + }, + }, + { + n = G.UIT.R, + config = { align = "cm" }, + nodes = { + UIBox_button({ + colour = G.C.RED, + button = "pointer_cancel", + label = { localize("cry_code_cancel") }, + minw = 4.5, + focus_args = { snap_to = true }, + }), + }, + }, + }, + }) + return t + end + G.FUNCS.pointer_cancel = function() + if G.CHOOSE_CARD then + G.CHOOSE_CARD:remove() + end + G.GAME.USING_CODE = false + G.GAME.USING_POINTER = false + G.DEBUG_POINTER = false + end + G.FUNCS.pointer_apply_previous = function() + if G.PREVIOUS_ENTERED_CARD then + G.ENTERED_CARD = G.PREVIOUS_ENTERED_CARD or "" + end + G.FUNCS.pointer_apply() + end + G.FUNCS.pointer_apply = function() + local function apply_lower(strn) + if type(strn) ~= string then -- safety + strn = tostring(strn) + end + -- Remove content within {} and any remaining spaces + strn = strn:gsub("%b{}", ""):gsub("%s+", "") + --this weirdness allows you to get m and M separately + if string.len(strn) == 1 then + return strn + end + return string.lower(strn) + end + local current_card -- j_cry_dropshot + local entered_card = G.ENTERED_CARD + local valid_check = {} + G.PREVIOUS_ENTERED_CARD = G.ENTERED_CARD + current_card = Cryptid.pointergetalias(entered_card) or nil + valid_check = Cryptid.pointergetblist(current_card) + if not valid_check[3] then + current_card = nil + end + --if enhancement has a suit or rank override, override above and make nil, so it can proceed with playing card creation + if current_card ~= nil and string.sub(current_card, 1, 1) == "m" then + if + G.P_CENTERS[current_card] and G.P_CENTERS[current_card].specific_suit + or G.P_CENTERS[current_card].specific_rank + then + current_card = nil + end + end + + if current_card then -- non-playing card cards + local created = false -- Joker check + if not valid_check[1] and valid_check[2] == "Joker" and valid_check[3] then + local card = create_card("Joker", G.jokers, nil, nil, nil, nil, current_card) + card:add_to_deck() + G.jokers:emplace(card) + created = true + end + if -- Consumeable check + not valid_check[1] + and valid_check[2] == "Consumeable" + and valid_check[3] + then + local card = create_card("Consumeable", G.consumeables, nil, nil, nil, nil, current_card) + if card.ability.name and card.ability.name == "cry-Chambered" then + card.ability.extra.num_copies = 1 + end + card:add_to_deck() + G.consumeables:emplace(card) + created = true + end + if -- Voucher check + not valid_check[1] + and valid_check[2] == "Voucher" + and valid_check[3] + then + local area + if G.STATE == G.STATES.HAND_PLAYED then + if not G.redeemed_vouchers_during_hand then + G.redeemed_vouchers_during_hand = CardArea( + G.play.T.x, + G.play.T.y, + G.play.T.w, + G.play.T.h, + { type = "play", card_limit = 5 } + ) + end + area = G.redeemed_vouchers_during_hand + else + area = G.play + end + local card = create_card("Voucher", area, nil, nil, nil, nil, current_card) + card:start_materialize() + area:emplace(card) + card.cost = 0 + card.shop_voucher = false + local current_round_voucher = G.GAME.current_round.voucher + card:redeem() + G.GAME.current_round.voucher = current_round_voucher + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0, + func = function() + card:start_dissolve() + return true + end, + })) + created = true + end + if -- Booster check + not valid_check[1] + and valid_check[2] == "Booster" + and valid_check[3] + then + local card = create_card("Booster", G.hand, nil, nil, nil, nil, current_card) + card.cost = 0 + card.from_tag = true + G.FUNCS.use_card({ config = { ref_table = card } }) + card:start_materialize() + created = true + end + if created then + if G.CHOOSE_CARD then + G.CHOOSE_CARD:remove() + end + G.GAME.USING_CODE = false + G.GAME.USING_POINTER = false + G.DEBUG_POINTER = false + return true + end + end + + for i, v in pairs(G.P_TAGS) do -- TAGS + local blacklist = Cryptid.pointergetblist(i) + -- gonna be real w/ you idk why pointergetblist is a table now so im just gonna check if everything in it is falsey + local can_spawn = true + for _, val in pairs(blacklist) do + can_spawn = can_spawn and not val + end + + if Cryptid.pointergetalias(i) and can_spawn then + if v.name and apply_lower(entered_card) == apply_lower(v.name) then + current_card = i + break --no clue why this wasn't done before, you can't create 2 tags with one pointer + end + if apply_lower(entered_card) == apply_lower(i) then + current_card = i + break + end + if + apply_lower(entered_card) == apply_lower(localize({ type = "name_text", set = v.set, key = i })) + then + current_card = i + break + end + end + end + + if + current_card + and (G.DEBUG_POINTER or (not G.P_CENTERS[current_card] and not G.GAME.banned_keys[current_card])) + then + local created = false + local t = Tag(current_card, nil, "Big") + add_tag(t) + if current_card == "tag_orbital" then + local _poker_hands = {} + for k, v in pairs(G.GAME.hands) do + if v.visible then + _poker_hands[#_poker_hands + 1] = k + end + end + t.ability.orbital_hand = pseudorandom_element(_poker_hands, pseudoseed("cry_pointer_orbital")) + end + if current_card == "tag_cry_rework" then + --tbh this is the most unbalanced part of the card + t.ability.rework_edition = + pseudorandom_element(G.P_CENTER_POOLS.Edition, pseudoseed("cry_pointer_edition")).key + t.ability.rework_key = + pseudorandom_element(G.P_CENTER_POOLS.Joker, pseudoseed("cry_pointer_joker")).key + end + G.CHOOSE_CARD:remove() + G.GAME.USING_CODE = false + G.GAME.USING_POINTER = false + G.DEBUG_POINTER = false + return + end + for i, v in pairs(G.P_BLINDS) do + if Cryptid.pointergetalias(i) and not Cryptid.pointergetblist(i) then + if v.name and apply_lower(entered_card) == apply_lower(v.name) then + current_card = i + end + if apply_lower(entered_card) == apply_lower(i) then + current_card = i + end + if + apply_lower(entered_card) + == apply_lower(localize({ type = "name_text", set = "Blind", key = i })) + then + current_card = i + end + end + end + if + current_card + and not G.P_CENTERS[current_card] + and not G.P_TAGS[current_card] + and (G.DEBUG_POINTER or not Cryptid.pointergetblist(current_card)) + then + local created = false + if not G.GAME.blind or (G.GAME.blind.name == "" or not G.GAME.blind.blind_set) then + --from debugplus + local par = G.blind_select_opts.boss.parent + G.GAME.round_resets.blind_choices.Boss = current_card + + G.blind_select_opts.boss:remove() + G.blind_select_opts.boss = UIBox({ + T = { par.T.x, 0, 0, 0 }, + definition = { + n = G.UIT.ROOT, + config = { + align = "cm", + colour = G.C.CLEAR, + }, + nodes = { + UIBox_dyn_container( + { create_UIBox_blind_choice("Boss") }, + false, + get_blind_main_colour("Boss"), + mix_colours(G.C.BLACK, get_blind_main_colour("Boss"), 0.8) + ), + }, + }, + config = { + align = "bmi", + offset = { + x = 0, + y = G.ROOM.T.y + 9, + }, + major = par, + xy_bond = "Weak", + }, + }) + par.config.object = G.blind_select_opts.boss + par.config.object:recalculate() + G.blind_select_opts.boss.parent = par + G.blind_select_opts.boss.alignment.offset.y = 0 + + for i = 1, #G.GAME.tags do + if G.GAME.tags[i]:apply_to_run({ + type = "new_blind_choice", + }) then + break + end + end + created = true + else + G.GAME.blind:set_blind(G.P_BLINDS[current_card]) + ease_background_colour_blind(G.STATE) + created = true + end + if created then + G.CHOOSE_CARD:remove() + G.GAME.USING_CODE = false + G.GAME.USING_POINTER = false + G.DEBUG_POINTER = false + return true + end + end + if not current_card then -- if card isn't created yet, try playing cards + local words = {} + for i in string.gmatch(string.lower(entered_card), "%S+") do -- not using apply_lower because we actually want the spaces here + table.insert(words, i) + end + + local rank_table = { + { "stone" }, + { "2", "Two", "II" }, + { "3", "Three", "III" }, + { "4", "Four", "IV" }, + { "5", "Five", "V" }, + { "6", "Six", "VI" }, + { "7", "Seven", "VII" }, + { "8", "Eight", "VIII" }, + { "9", "Nine", "IX" }, + { "10", "1O", "Ten", "X", "T" }, + { "J", "Jack" }, + { "Q", "Queen" }, + { "K", "King" }, + { "A", "Ace", "One", "1", "I" }, + { "Abstract", "Abstracted", "TADC" }, + } -- ty variable + local _rank = nil + for m = #words, 1, -1 do -- the legendary TRIPLE LOOP, checking from end since rank is most likely near the end + for i, v in pairs(rank_table) do + for j, k in pairs(v) do + if words[m] == string.lower(k) then + _rank = i + break + end + end + if _rank then + break + end + end + if _rank then + break + end + end + if _rank then -- a playing card is going to get created at this point, but we can find additional descriptors + local suit_table = { + ["Spades"] = { "spades" }, + ["Hearts"] = { "hearts" }, + ["Clubs"] = { "clubs" }, + ["Diamonds"] = { "diamonds" }, + } + for k, v in pairs(SMODS.Suits) do + local index = v.key + local current_name = G.localization.misc.suits_plural[index] + if not suit_table[v.key] then + suit_table[v.key] = { string.lower(current_name) } + end + end + -- i'd rather be pedantic and not forgive stuff like "spade", there's gonna be a lot of checks + -- can change that if need be + local enh_table = { + ["m_lucky"] = { "lucky" }, + ["m_mult"] = { "mult" }, + ["m_bonus"] = { "bonus" }, + ["m_wild"] = { "wild" }, + ["m_steel"] = { "steel" }, + ["m_glass"] = { "glass" }, + ["m_gold"] = { "gold" }, + ["m_stone"] = { "stone" }, + ["m_cry_echo"] = { "echo" }, + ["m_cry_abstract"] = { "abstract" }, + } + for k, v in pairs(G.P_CENTER_POOLS.Enhanced) do + local index = v.key + local current_name = G.localization.descriptions.Enhanced[index].name + current_name = current_name:gsub(" Card$", "") + if not enh_table[v.key] then + enh_table[v.key] = { string.lower(current_name) } + end + end + local ed_table = { + ["e_base"] = { "base" }, + ["e_foil"] = { "foil" }, + ["e_holo"] = { "holo" }, + ["e_polychrome"] = { "polychrome" }, + ["e_negative"] = { "negative" }, + ["e_cry_mosaic"] = { "mosaic" }, + ["e_cry_oversat"] = { "oversat" }, + ["e_cry_glitched"] = { "glitched" }, + ["e_cry_astral"] = { "astral" }, + ["e_cry_blur"] = { "blurred" }, + ["e_cry_gold"] = { "golden" }, + ["e_cry_glass"] = { "fragile" }, + ["e_cry_m"] = { "jolly" }, + ["e_cry_noisy"] = { "noisy" }, + ["e_cry_double_sided"] = { "double-sided", "double_sided", "double" }, -- uhhh sure + } + for k, v in pairs(G.P_CENTER_POOLS.Edition) do + local index = v.key + local current_name = G.localization.descriptions.Edition[index].name + if not ed_table[v.key] then + ed_table[v.key] = { string.lower(current_name) } + end + end + local seal_table = { + ["Red"] = { "red" }, + ["Blue"] = { "blue" }, + ["Purple"] = { "purple" }, + ["Gold"] = { "gold", "golden" }, -- don't worry we're handling seals differently + ["cry_azure"] = { "azure" }, + ["cry_green"] = { "green" }, + } + local sticker_table = { + ["eternal"] = { "eternal" }, + ["perishable"] = { "perishable" }, + ["rental"] = { "rental" }, + ["pinned"] = { "pinned" }, + ["banana"] = { "banana" }, -- no idea why this evades prefixing + ["cry_rigged"] = { "rigged" }, + ["cry_global_sticker"] = { "global" }, + ["cry_flickering"] = { "flickering" }, + ["cry_possessed"] = { "possessed" }, + ["cry_absolute"] = { "absolute" }, + } + local function parsley(_table, _word) + for i, v in pairs(_table) do + for j, k in pairs(v) do + if _word == string.lower(k) then + return i + end + end + end + return "" + end + local function to_rank(rrank) + if rrank <= 10 then + return tostring(rrank) + elseif rrank == 11 then + return "Jack" + elseif rrank == 12 then + return "Queen" + elseif rrank == 13 then + return "King" + elseif rrank == 14 then + return "Ace" + end + end + + -- ok with all that fluff out the way now we can figure out what on earth we're creating + + local _seal_att = false + local _suit = "" + local _enh = "" + local _ed = "" + local _seal = "" + local _stickers = {} + for m = #words, 1, -1 do + -- we have a word. figure out what that word is + -- this is dodgy spaghetti but w/ever + local wword = words[m] + if _suit == "" then + _suit = parsley(suit_table, wword) + end + if _enh == "" then + _enh = parsley(enh_table, wword) + if _enh == "m_gold" and _seal_att == true then + _enh = "" + end + end + if _ed == "" then + _ed = parsley(ed_table, wword) + if _ed == "e_cry_gold" and _seal_att == true then + _ed = "" + end + end + if _seal == "" then + _seal = parsley(seal_table, wword) + if _seal == "Gold" and _seal_att == false then + _seal = "" + end + end + local _st = parsley(sticker_table, wword) + if _st then + _stickers[#_stickers + 1] = _st + end + if wword == "seal" or wword == "sealed" then + _seal_att = true + else + _seal_att = false + end -- from end so the next word should describe the seal + end + + -- now to construct the playing card + -- i'm doing this by applying everything but maybe it's a bit janky? + + G.CHOOSE_CARD:remove() + G.GAME.USING_CODE = false + G.GAME.USING_POINTER = false + G.DEBUG_POINTER = false + + G.E_MANAGER:add_event(Event({ + func = function() + G.playing_card = (G.playing_card and G.playing_card + 1) or 1 + local _card = create_card("Base", G.play, nil, nil, nil, nil, nil, "pointer") + SMODS.change_base( + _card, + _suit ~= "" and _suit + or pseudorandom_element( + { "Spades", "Hearts", "Diamonds", "Clubs" }, + pseudoseed("sigil") + ), + _rank > 1 and to_rank(_rank) or nil + ) + if _enh ~= "" then + _card:set_ability(G.P_CENTERS[_enh]) + end + if _rank == 1 then + _card:set_ability(G.P_CENTERS["m_stone"]) + end + --Abstracted + if + _rank == 15 + or string.lower(_suit) == "abstract" + or string.lower(_suit) == "abstracted" + then + _card:set_ability(G.P_CENTERS["m_cry_abstract"]) + end + if _seal ~= "" then + _card:set_seal(_seal, true, true) + end + if _ed ~= "" then + _card:set_edition(_ed, true, true) + end + for i = 1, #_stickers do + _card.ability[_stickers[i]] = true + if _stickers[i] == "pinned" then + _card.pinned = true + end + end + _card:start_materialize() + G.play:emplace(_card) + table.insert(G.playing_cards, _card) + playing_card_joker_effects({ _card }) + return true + end, + })) + G.E_MANAGER:add_event(Event({ + func = function() + G.deck.config.card_limit = G.deck.config.card_limit + 1 + return true + end, + })) + draw_card(G.play, G.deck, 90, "up", nil) + return true + end + end + end + end, +} + +local aliases = { + ---- Vanilla Cards + -- Vanilla Jokers + j_joker = { + "Joker", + "Jimbo", + }, + j_greedy_joker = { + "Greedy Joker", + "Diamond Joker", + }, + j_lusty_joker = { + "Lusty Joker", + "Horny Joker", + "Heart Joker", + }, + j_wrathful_joker = { + "Wrathful Joker", + "Spade Joker", + }, + j_gluttenous_joker = { + "Gluttonous Joker", + "Fatass Joker", + "Fat Ass Joker", + "Big Back", + "Big Back Joker", + "Club Joker", + }, + j_jolly = { + "Jolly Joker", + "Joseph, J. Joker", + "Pair Mult", + }, + j_zany = { + "Zany Joker", + "Zany", + }, + j_mad = { + "Mad Joker", + "Mad", + }, + j_crazy = { + "Crazy Joker", + "Crazy", + }, + j_droll = { + "Droll Joker", + "Droll", + }, + j_sly = { + "Sly Joker", + "Sly", + }, + j_wily = { + "Wily Joker", + "Wily", + }, + j_clever = { + "Clever Joker", + "Clever", + }, + j_devious = { + "Devious Joker", + "Devious", + }, + j_crafty = { + "Crafty Joker", + "Crafty", + }, + j_half = { + "Half Joker", + "Semi Joker", + }, + j_stencil = { + "Joker Stencil", + "Stencil", + }, + j_four_fingers = { + "Four Fingers", + "4 Fingers", + "Fourfingers", + "4fingers", + }, + j_mime = { + "Mime", + }, + j_credit_card = { + "Credit Card", + "Debit Card", + }, + j_ceremonial = { + "Ceremonial Dagger", + "Dagger", + }, + j_banner = { + "Banner", + }, + j_mystic_summit = { + "Mystic Summit", + }, + j_marble = { + "Marble Joker", + "Lexi", + }, + j_loyalty_card = { + "Loyalty Card", + }, + j_8_ball = { + "8 Ball", + "8-Ball", + "Eight Ball", + "Eightball", + }, + j_misprint = { + "Misprint", + }, + j_dusk = { + "Dusk", + }, + j_raised_fist = { + "Raised Fist", + "1984", + }, + j_chaos = { + "Chaos the Clown", + }, + j_fibonacci = { + "Fibonacci", + "Fibbonaci", + "Fibonnaci", + }, + j_steel_joker = { + "Steel Joker", + }, + j_scary_face = { + "Scary Face", + "Spooky Face", + }, + j_abstract = { + "Abstract Joker", + }, + j_delayed_grat = { + "Delayed Gratification", + "Delayed Grat", + }, + j_hack = { + "Hack", + }, + j_pareidolia = { + "Pareidolia", + "All Face Cards", + "Pariedolia", + }, + j_gros_michel = { + "Gros Michel", + "Banana", + }, + j_even_steven = { + "Even Steven", + "Steven", + }, + j_odd_todd = { + "Odd Todd", + "Todd", + }, + j_scholar = { + "Scholar", + "Dr Spectred", + "Dr. Spectred", + "drspectred", + "Balatro University", + "Balatro University Joker", + "Balatro Uni", + }, + j_business = { + "Business Card", + }, + j_supernova = { + "Supernova", + }, + j_ride_the_bus = { + "Ride the Bus", + "Bus", + }, + j_space = { + "Space Joker", + }, + j_egg = { + "Egg", + "Egg Joker", + }, + j_burglar = { + "Burglar", + }, + j_blackboard = { + "Blackboard", + }, + j_runner = { + "Runner", + }, + j_ice_cream = { + "Ice Cream", + }, + j_dna = { + "DNA", + }, + j_splash = { + "Splash", + "Wet Joker", + }, + j_blue_joker = { + "Blue Joker", + }, + j_sixth_sense = { + "Sixth Sense", + "6th Sense", + }, + j_constellation = { + "Constellation", + }, + j_hiker = { + "Hiker", + }, + j_faceless = { + "Faceless Joker", + }, + j_green_joker = { + "Green Joker", + "Grimbo", + }, + j_superposition = { + "Superposition", + }, + j_todo_list = { + "To Do List", + "Todo List", + "To-Do List", + }, + j_cavendish = { + "Cavendish", + "Glitch", + }, + j_card_sharp = { + "Card Sharp", + }, + j_red_card = { + "Red Card", + }, + j_madness = { + "Madness", + }, + j_square = { + "Square Joker", + }, + j_seance = { + "Seance", + }, + j_riff_raff = { + "Riff-raff", + "Riff Raff", + "RiffRaff", + }, + j_vampire = { + "Vampire", + }, + j_shortcut = { + "Shortcut", + }, + j_hologram = { + "Hologram", + }, + j_vagabond = { + "Vagabond", + }, + j_baron = { + "Baron", + }, + j_cloud_9 = { + "Cloud 9", + "Murphy's Favorite", + "Murphy Favorite", + "Murphys Favorite", + "Murphy Fav", + }, + j_rocket = { + "Rocket", + }, + j_obelisk = { + "Obelisk", + }, + j_midas_mask = { + "Midas Mask", + }, + j_luchador = { + "Luchador", + }, + j_photograph = { + "Photograph", + "Photo", + }, + j_gift = { + "Gift Card", + }, + j_turtle_bean = { + "Turtle Bean", + "Bean", + }, + j_erosion = { + "Erosion", + }, + j_reserved_parking = { + "Reserved Parking", + }, + j_mail = { + "Mail-In Rebate", + "Mail In Rebate", + "Rebate", + "Mail Rebate", + }, + j_to_the_moon = { + "To the Moon", + }, + j_hallucination = { + "Hallucination", + }, + j_fortune_teller = { + "Fortune Teller", + }, + j_juggler = { + "Juggler", + "+1 hand size", + }, + j_drunkard = { + "Drunkard", + "+1 Discard", + }, + j_stone = { + "Stone Joker", + }, + j_golden = { + "Golden Joker", + }, + j_lucky_cat = { + "Lucky Cat", + }, + j_baseball = { + "Baseball Card", + "Baseball Huh?", + }, + j_bull = { + "Bull", + }, + j_diet_cola = { + "Diet Cola", + "Cola", + "Tag Soda", + "Tag Cola", + }, + j_trading = { + "Trading Card", + }, + j_flash = { + "Flash Card", + }, + j_popcorn = { + "Popcorn", + }, + j_trousers = { + "Spare Trousers", + }, + j_ancient = { + "Ancient Joker", + "Anceint Joker", + }, + j_ramen = { + "Ramen", + }, + j_walkie_talkie = { + "Walkie Talkie", + }, + j_selzer = { + "Seltzer", + }, + j_castle = { + "Castle", + }, + j_smiley = { + "Smiley Face", + "Smiley", + }, + j_campfire = { + "Campfire", + }, + j_ticket = { + "Golden Ticket", + "Gold Ticket", + }, + j_mr_bones = { + "Mr. Bones", + "Mr Bones", + }, + j_acrobat = { + "Acrobat", + }, + j_sock_and_buskin = { + "Sock and Buskin", + }, + j_swashbuckler = { + "Swashbuckler", + }, + j_troubadour = { + "Troubadour", + }, + j_certificate = { + "Certificate", + }, + j_smeared = { + "Smeared Joker", + "Smeared", + }, + j_throwback = { + "Throwback", + }, + j_hanging_chad = { + "Hanging Chad", + }, + j_rough_gem = { + "Rough Gem", + }, + j_bloodstone = { + "Bloodstone", + }, + j_arrowhead = { + "Arrowhead", + }, + j_onyx_agate = { + "Onyx Agate", + }, + j_glass = { + "Glass Joker", + }, + j_ring_master = { + "Showman", + }, + j_flower_pot = { + "Flower Pot", + }, + j_blueprint = { + "Blueprint", + "BP", + }, + j_wee = { + "Wee Joker", + "WEEEE", + "Wee", + }, + j_merry_andy = { + "Merry Andy", + }, + j_oops = { + "Oops! All 6s", + "OA6s", + "OA6", + "O A 6s", + "Oops 6s", + "Oops 6", + "Oop 6s", + }, + j_idol = { + "The Idol", + "Idol", + }, + j_seeing_double = { + "Seeing Double", + }, + j_matador = { + "Matador", + }, + j_hit_the_road = { + "Hit the Road", + }, + j_duo = { + "The Duo", + "Duo", + }, + j_trio = { + "The Trio", + "Trio", + }, + j_family = { + "The Family", + "Family", + }, + j_order = { + "The Order", + "Order", + }, + j_tribe = { + "The Tribe", + "Tribe", + }, + j_stuntman = { + "Stuntman", + }, + j_invisible = { + "Invisible Joker", + "Invisible", + }, + j_brainstorm = { + "Brainstorm", + }, + j_satellite = { + "Satellite", + }, + j_shoot_the_moon = { + "Shoot the Moon", + }, + j_drivers_license = { + "Driver's License", + }, + j_cartomancer = { + "Cartomancer", + }, + j_astronomer = { + "Astronomer", + }, + j_burnt = { + "Burnt Joker", + }, + j_bootstraps = { + "Bootstraps", + }, + j_caino = { + "Caino", + }, + j_triboulet = { + "Triboulet", + }, + j_yorick = { + "Yorick", + }, + j_chicot = { + "Chicot", + }, + j_perkeo = { + "Perkeo", + }, + + -- Vanilla Tarots + c_fool = { + "The Fool", + "Fool", + }, + c_high_priestess = { + "The High Priestess", + "High Priestess", + }, + c_empress = { + "The Empress", + "Empress", + "Mult Tarot", + }, + c_emperor = { + "The Emperor", + "Emperor", + }, + c_heirophant = { + "The Hierophant", + "Hierophant", + "The Heirophant", + "Heirophant", + "Bonus Tarot", + }, + c_lovers = { + "The Lovers", + "Lovers", + "Wild Tarot", + }, + c_chariot = { + "The Chariot", + "Chariot", + "Steel Tarot", + }, + c_justice = { + "Justice", + "Glass Tarot", + }, + c_hermit = { + "The Hermit", + "Hermit", + "Doubles Money", + }, + c_wheel_of_fortune = { + "The Wheel Of Fortune", + "Wheel Of Fortune", + "tWoF", + "WoF", + "Gambling", + "Wheel", + }, + c_strength = { + "Strength", + }, + c_hanged_man = { + "The Hanged Man", + "Hanged Man", + "Hang Man", + "Hung Man", + }, + c_death = { + "Death", + "Turn The Left Card Into The Right Card", + }, + c_temperance = { + "Temperance", + "The Temperance", + "Joker Money", + }, + c_devil = { + "The Devil", + "Devil", + "Gold Tarot", + }, + c_tower = { + "The Tower", + "Tower", + "Stone Tarot", + }, + c_star = { + "The Star", + "Star", + "Diamond Tarot", + }, + c_moon = { + "The Moon", + "Moon", + "Club Tarot", + }, + c_sun = { + "The Sun", + "Sun", + "Heart Tarot", + }, + c_judgement = { + "Judgement", + "The Judgement", + "Judgement Day", + "Minos Prime", + }, + c_world = { + "The World", + "World", + "Spade Tarot", + }, + + -- Vanilla Planets + c_mercury = { + "Mercury", + "Merc", + "M planet", + "Mlanet", + "Pair", + "2oak", + }, + c_venus = { + "Venus", + "3 planet", + "3oak", + "Aphrodite", + "Penus", + }, + c_earth = { + "Earth", + "Terra", + "3+2", + "Gaia", + "Hell", + "Here", + "erth", + "erf", + "Full House", + "1987 Sitcom by Jeff Franklin", + "Spawn", + "Spawnpoint", + }, + c_mars = { + "Mars", + "4oak", + "Not 2 Pairs", + "Ares", + "Red Planet", + }, + c_jupiter = { + "Jupiter", + "Flush", + "The big one", + "Zeus", + }, + c_saturn = { + "Saturn", + "Straight", + "Chronos", + "Rings", + }, + c_uranus = { + "Uranus", + "Uranus but in greek", + "2 pair", + "22", + "anus", + "haha get it cuz uranus is like ur-anus and anus means butt so its funny come on guys please laugh", + }, + c_neptune = { + "Neptune", + "Neptunus", + "Poseidon", + "Straight Flush", + "Slush", + "Royal", + }, + c_pluto = { + "Pluto", + "Hades", + "1oak", + "One", + "High Card", + "Not Planet", + "Dwarf", + }, + c_planet_x = { + "Planet X", + "5oak", + "Twitter", + "Five Guys", + }, + c_ceres = { + "Ceres", + "Demeter", + "Flush House", + "Reaper", + }, + c_eris = { + "Eris", + "fish", + "Flush Five", + "F5", + }, + + -- Vanilla Spectrals + c_familiar = { + "Familiar", + "The Familiar", + }, + c_grim = { + "Grim", + "The Grim", + }, + c_incantation = { + "Incantation", + "The Incantation", + "Consumable Stacker", + "Incant", + "Inct", + "Inc", + }, + c_talisman = { + "Talisman", + "The Talisman", + "Bignum mod", + "Omeganum mod", + "Skip Animations", + "Skip Anim", + "Talis", + "Tali", + }, + c_aura = { + "Aura", + "The Aura", + "WoF 2", + }, + c_wraith = { + "Wraith", + "The Wraith", + "Obelisk Spawner 2", + "Wrath", + }, + c_sigil = { + "Sigil", + "The Sigil", + "Suit Equalizer", + }, + c_ouija = { + "Ouija", + "The Ouija", + "Ouija Board", + "Weegee", + }, + c_ectoplasm = { + "Ectoplasm", + "The Ectoplasm", + "White Glop", + "Ghost Matter", + "Ecto", + "Plasm", + "One Negative Popcorn Pretty Please", + }, + c_immolate = { + "Immolate", + "Imolate", + "The Immolate", + "The Imolate", + "Immolation", + "Immolator", + "Oh Boy 20 Dollars", + }, + c_ankh = { + "Ankh", + "Life", + "Egyptian Cross", + }, + c_deja_vu = { + "Deja vu", + "Deja vu", + "Deja", + "vu", + "Again!", + "Deja vu", + "Deja vu", + }, + c_hex = { + "Hex", + "The Hex", + "Vex", + "This Hexes Me", + }, + c_trance = { + "Trance", + "The Trance", + "Transe", + "Trans", + "Trams", + }, + c_medium = { + "Medium", + "The Medium", + "Ourple", + }, + c_cryptid = { + "Cryptid", + "The Cryptid", + "+2", + "The Mod", + "Cry", + }, + c_soul = { + "Soul", + "The Soul", + "Jazz", + "Spirit", + "Legendary", + "White Rock", + "Blank Rune", + }, + c_black_hole = { + "Black Hole", + "The Black Hole", + "Bhole", + "Oprah", + }, + + -- Vanilla Booster Packs + p_arcana_normal_1 = { + "Arcana Pack", + "Arcana Fool", + "Arcana Pack 1", + }, + p_arcana_normal_2 = { + "Arcana", + "Arcana Temperance", + "Arcana Pack 2", + }, + p_arcana_normal_3 = { + "Arcana Hierophant", + "Arcana Pack 3", + }, + p_arcana_normal_4 = { + "Arcana World", + "Arcana Pack 4", + }, + p_arcana_jumbo_1 = { + "Jumbo Arcana", + "Jumbo Arcana Pack", + "Arcana Death", + "Jumbo Arcana 1", + "Jumbo Arcana Pack 1", + }, + p_arcana_jumbo_2 = { + "Arcana Emperor", + "Jumbo Arcana 2", + "Jumbo Arcana Pack 2", + }, + p_arcana_mega_1 = { + "Mega Arcana", + "Mega Arcana Pack", + "Arcana Tower", + "Mega Arcana 1", + "Mega Arcana Pack 1", + }, + p_arcana_mega_2 = { + "Arcana Hermit", + "Mega Arcana 2", + "Mega Arcana Pack 2", + }, + + p_celestial_normal_1 = { + "Celestial Pack", + "Celestial Mercury", + "Celestial Pack 1", + }, + p_celestial_normal_2 = { + "Celestial", + "Celestial Jupiter", + "Celestial Pack 2", + }, + p_celestial_normal_3 = { + "Celestial Earth", + "Celestial Pack 3", + }, + p_celestial_normal_4 = { + "Celestial Uranus", + "Celestial Pack 4", + }, + p_celestial_jumbo_1 = { + "Jumbo Celestial", + "Jumbo Celestial Pack", + "Celestial Mars", + "Jumbo Celestial 1", + "Jumbo Celestial Pack 1", + }, + p_celestial_jumbo_2 = { + "Celestial Pluto", + "Jumbo Celestial 2", + "Jumbo Celestial Pack 2", + }, + p_celestial_mega_1 = { + "Mega Celestial", + "Mega Celestial Pack", + "Celestial Saturn", + "Mega Celestial 1", + "Mega Celestial Pack 1", + }, + p_celestial_mega_2 = { + "Celestial Venus", + "Mega Celestial 2", + "Mega Celestial Pack 2", + }, + p_standard_normal_1 = { + "Standard Pack", + "Standard Pack 1", + }, + p_standard_normal_2 = { + "Standard", + "Standard Pack 2", + }, + p_standard_normal_3 = { + "Standard Pack 3", + }, + p_standard_normal_4 = { + "Standard Pack 4", + }, + p_standard_jumbo_1 = { + "Jumbo Standard", + "Jumbo Standard Pack", + "Jumbo Standard 1", + "Jumbo Standard Pack 1", + }, + p_standard_jumbo_2 = { + "Jumbo Standard 2", + "Jumbo Standard Pack 2", + }, + p_standard_mega_1 = { + "Mega Standard", + "Mega Standard Pack", + "Mega Standard 1", + "Mega Standard Pack 1", + }, + p_standard_mega_2 = { + "Mega Standard 2", + "Mega Standard Pack 2", + }, + p_buffoon_normal_1 = { + "Buffoon Pack", + "Buffoon Hack", + "Buffoon Pack 1", + }, + p_buffoon_normal_2 = { + "Jimbo Pack", + "Buffoon", + "Buffoon Juggler", + "Buffoon Pack 2", + }, + p_buffoon_jumbo_1 = { + "Jumbo Jimbo", + "Jumbo Jimbo Pack", + "Buffoon Banner", + "Jumbo Buffoon", + "Jumbo Buffoon Pack", + }, + p_buffoon_mega_1 = { + "Mega Jimbo", + "Mega Jimbo Pack", + "Buffoon Brainstom", + "Mega Buffoon", + "Mega Buffoon Pack", + }, + p_spectral_normal_1 = { + "Spectral Pack", + "Spectral Grim", + "Spectral Pack 1", + }, + p_spectral_normal_2 = { + "Spectral", + "Spectral Pack 2", + }, + p_spectral_jumbo_1 = { + "Jumbo Spectral", + "Spectral Incantation", + "Jumbo Spectral Pack", + }, + p_spectral_mega_1 = { + "Mega Spectral", + "Spectral Ectoplasm", + "Mega Spectral Pack", + }, + + -- Vanilla Tags + -- everybody forgor + tag_uncommon = { + "Uncommon Tag", + "Tag Uncommon", + }, + tag_rare = { + "Rare Tag", + "Tag Rare", + }, + tag_negative = { + "Negative Tag", + "Tag Negative", + }, + tag_foil = { + "Foil Tag", + "Tag Foil", + }, + tag_holo = { + "Holo Tag", + "Tag Holo", + "Holographic Tag", + "Tag Holographic", + }, + tag_polychrome = { + "Polychrome Tag", + "Tag Polychrome", + }, + tag_investment = { + "Investment Tag", + "Tag Investment", + "Invest Tag", + "Tag Invest", + "Investment", + }, + tag_voucher = { + "Voucher Tag", + "Tag Voucher", + "Vouch Tag", + }, + tag_boss = { + "Boss Tag", + "Tag Boss", + }, + tag_standard = { + "Standard Tag", + "Tag Standard", + }, + tag_charm = { + "Charm Tag", + "Tag Charm", + "Tarot Tag", + "Acrana Tag", + "Arcana Tag", + "Tag Tarot", + "Tag Arcana", + "Charm Pack Tag", + "Tarot Pack Tag", + "Arcana Pack Tag", + "Acrana Pack Tag", + }, + tag_meteor = { + "Meteor Tag", + "Tag Meteor", + "Celestial Tag", + "Tag Celestial", + "Planet Tag", + "Tag Planet", + "Celestial Pack Tag", + "Planet Pack Tag", + }, + tag_buffoon = { + "Buffoon Tag", + "Tag Buffoon", + "Joker Pack Tag", + "Joker Tag", + "Buffoon Pack Tag", + }, + tag_handy = { + "Handy Tag", + "Tag Handy", + }, + tag_garbage = { + "Garbage Tag", + "Tag Garbage", + "Discard Tag", + "Tag Discard", + }, + tag_ethereal = { + "Ethereal Tag", + "Tag Ethereal", + "Spectral Tag", + "Tag Spectral", + }, + tag_coupon = { + "Coupon Tag", + "Tag Coupon", + "Free Tag", + "Shop Tag Free", + "Shop Free Tag", + "Shop Tag", + }, + tag_double = { + "Double Tag", + "Tag Double", + "Extra Tag", + "2 Tag", + }, + tag_juggle = { + "Juggle Tag", + "Tag Juggle", + "Juggler Tag", + "Tag Juggler", + "Hand Size Tag", + "Tag Hand Size", + }, + tag_d_six = { + "D Six Tag", + "Tag D Six", + "D6 Tag", + "Tag D6", + "Reroll Tag", + "Tag Reroll", + "Rerolling Tag", + "Tag Rerolling", + "DSix Tag", + "Tag DSix", + "D6", + "D 6", + "D 6 Tag", + "Tag D 6", + }, + tag_top_up = { + "Top Up Tag", + "Tag Top Up", + "Top Up", + "2 common tag", + }, + tag_skip = { + "Skip Tag", + "Tag Skip", + "Skipping Tag", + "Tag Skipping", + }, + tag_orbital = { + "Orbital Tag", + "Tag Orbital", + "Orbital", + "Planet Tag", + }, + tag_economy = { + "Economy Tag", + "Tag Economy", + "Econ tag", + "Eco tag", + "money tag", + "Tag Money", + "Tag Econ", + "Tag Eco", + }, + -- Vanilla Vouchers + + v_overstock_norm = { + "Overstock", + "Over Stock", + }, + v_overstock_plus = { + "Overstock Plus", + "Over Stock Plus", + "Overstockplus", + "Overstock+", + "Overstock 2", + }, + v_clearance_sale = { + "Clearance Sale", + "Clearancesale", + "Clearance", + }, + v_liquidation = { + "Liquidation", + "Clearance Sale+", + "Clearance Sale Plus", + "Clearance Sale 2", + }, + v_hone = { + "Hone", + }, + v_glow_up = { + "Glow Up", + "Glow-Up", + "Glowup", + "Hone+", + "Hone Plus", + "Hone 2", + }, + v_reroll_surplus = { + "Reroll Surplus", + "Rerollsurplus", + "Reroll Voucher", + }, + v_reroll_glut = { + "Reroll Glut", + "Rerollglut", + "Reroll Surplus+", + "Reroll Surplus Plus", + "Reroll Surplus 2", + }, + v_crystal_ball = { + "Crystal Ball", + "Crystalball", + "Consumable Slot", + "Consumable Voucher", + "Consumable Slot Voucher", + }, + v_omen_globe = { + "Omen Globe", + "Omenglobe", + "Crystal Ball+", + "Crystal Ball Plus", + "Crystal Ball 2", + }, + v_telescope = { + "Telescope", + "Teliscope", + }, + v_observatory = { + "Observatory", + "Telescope+", + "Telescope Plus", + "Telescope 2", + "Perkeo Voucher", + }, + v_grabber = { + "Grabber", + "Hand Voucher", + }, + v_nacho_tong = { + "Nacho Tong", + "Nachotong", + "Grabber+", + "Grabber Plus", + "Grabber 2", + }, + v_wasteful = { + "Wasteful", + "Discard Voucher", + }, + v_recyclomancy = { + "Recyclomancy", + "Wasteful+", + "Wasteful Plus", + "Wasteful 2", + }, + v_tarot_merchant = { + "Tarot Merchant", + "Tarotmerchant", + "Tarot Voucher", + }, + v_tarot_tycoon = { + "Tarot Tycoon", + "Tarot Merchant+", + "Tarot Merchant Plus", + "Tarot Merchant 2", + }, + v_planet_merchant = { + "Planet Merchant", + "Planetmerchant", + "Planet Voucher", + }, + v_planet_tycoon = { + "Planet Tycoon", + "Planet Merchant+", + "Planet Merchant Plus", + "Planet Merchant 2", + }, + v_seed_money = { + "Seed Money", + "Interest Voucher", + "Seedmoney", + }, + v_money_tree = { + "Money Tree", + "Moneytree", + "Seed Money+", + "Seed Money Plus", + "Seed Money 2", + }, + v_blank = { + "Blank", + "Blank Voucher", + "Blank?", + "Does Nothing", + }, + v_antimatter = { + "Antimatter", + "Anti Matter", + "Antematter", + "Blank+", + "Blank Plus", + "Blank 2", + "Joker Slot Voucher", + }, + v_magic_trick = { + "Magic Trick", + "Magictrick", + "Card Voucher", + "Hologram Voucher", + }, + v_illusion = { + "Illusion", + "Magic Trick+", + "Magic Trick Plus", + "Magic Trick 2", + }, + v_hieroglyph = { + "Hieroglyph", + "Heiroglyph", + "Hiroglyph", + }, + v_petroglyph = { + "Petroglyph", + "Hieroglyph+", + "Hieroglyph Plus", + "Hieroglyph 2", + }, + v_directors_cut = { + "Director's Cut", + "Directors Cut", + "Directorscut", + }, + v_retcon = { + "Retcon", + "Boss Reroll", + "Director's Cut+", + "Director's Cut Plus", + "Director's Cut 2", + }, + v_paint_brush = { + "Paint Brush", + "Paintbrush", + "Hand Size Voucher", + }, + v_palette = { + "Palette", + "Pallete", + "Paint Brush+", + "Paint Brush Plus", + "Paint Brush 2", + }, + + ---- Cryptid Cards + -- M jokers + j_cry_m = { + "m", + "lowercase m", + }, + j_cry_mprime = { + "Flesh Panopticon", + "Minos Prime", + "M Prime", + }, + j_cry_M = { + "M", + "Capital M", + }, + j_cry_bubblem = { + "BubbleM", + "Bubble M", + }, + j_cry_foodm = { + "McDonalds", + "McDonald's", + "Food M", + "Fast Food M", + }, + j_cry_mstack = { + "Stack M", + "M Stack", + }, + j_cry_mneon = { + "Neon M", + "mneon", + }, + j_cry_notebook = { + "Notebook", + "The Notebook", + "The Motebook", + "Motebook", + "Noting this down", + "Moting this down", + }, + j_cry_bonk = { + "Bonk", + }, + j_cry_loopy = { + "Loopy", + "Loopy M", + }, + j_cry_scrabble = { + "Scrabble", + "Scrabble Tile", + "Scrabble M", + "Letter M", + }, + j_cry_sacrifice = { + "Sacrifice", + }, + j_cry_reverse = { + "Uno Card", + "Uno Reverse", + "Reverse Card", + "Uno Reverse Card", + "Reverse Uno Card", + }, + j_cry_longboi = { + "Monster", + "longboi", + "long boi", + }, + j_cry_megg = { + "Megg", + "Jolly Egg", + }, + j_cry_macabre = { + "Macabre", + "Macabre Joker", + "M Dagger", + }, + j_cry_smallestm = { + "Tiny", + "Tiny M", + "very small m", + "teeny m", + }, + j_cry_virgo = { + "Virgo", + "Virgin", + }, + j_cry_doodlem = { + "Doodle", + "Doodle M", + "The anniversary is back on!", + }, + j_cry_jollysus = { + "Jolly Joker?", + "jolly sus", + "blue sus", + "sus jolly", + }, + j_cry_biggestm = { + "Huge", + "Big Boned", + "not fat", + "Massive", + "Huge M", + }, + + -- SpOoOky jokers + j_cry_cotton_candy = { + "Cotton Candy", + }, + j_cry_wrapped = { + "Wrapped Candy", + }, + j_cry_chocolate_dice = { + "Chocolate Dice", + "Chocolate Die", + "Choco Dice", + "Choco Die", + }, + j_cry_trick_or_treat = { + "Trick or Treat", + "Trickortreat", + "Trick-or-Treat", + }, + j_cry_candy_basket = { + "Candy Basket", + }, + j_cry_candy_dagger = { + "Candy Dagger", + }, + j_cry_candy_cane = { + "Candy Cane", + }, + j_cry_candy_buttons = { + "Candy Buttons", + }, + j_cry_jawbreaker = { + "Jawbreaker", + }, + j_cry_mellowcreme = { + "Mellowcreme", + "Mellowcream", + }, + j_cry_brittle = { + "Brittle Candy", + }, + j_cry_candy_sticks = { + "Candy Sticks", + }, + j_cry_wonka_bar = { + "Wonka Bar", + "Wonka", + }, + + -- Cursed Jokers + j_cry_blacklist = { + "Blacklist", + }, + j_cry_monopoly_money = { + "Monopoly Money", + "Monopoly", + }, + + -- Code Jokers (not code cards) + j_cry_CodeJoker = { + "Code Joker", + "Codejoker", + }, + j_cry_copypaste = { + "Copy Paste", + "Copy-Paste", + "Copy/Paste", + "Copypaste", + "Copypasta", + }, + j_cry_cut = { + "Cut", + }, + j_cry_blender = { + "Blender", + }, + j_cry_python = { + "Python", + }, + + -- Secret Placeholder 1 + -- Smaller Placeholder + + -- Misc Jokers + j_cry_oil_lamp = { + "Oil Lamp", + "Oillamp", + }, + j_cry_tropical_smoothie = { + "Tropical Smoothie", + "Tropical", + "Smoothie", + }, + -- bigger placeholder + + -- Epic Jokers + j_cry_altgoogol = { + "Nostalgic Googol Play Card", + "NGPC", + "Nostalgic Googol", + "Nostalgic Google Play Card", + }, + -- epic placeholder + + -- Exotic Jokers + -- exotic placeholder + + -- Cryptid Tarots + -- placeholder for the like 5 there is + + -- Cryptid Planets + c_cry_planetlua = { + "Planet.lua", + "Lua Planet", + }, + c_cry_abelt = { + "Asteroid Belt", + "Bulwark", + }, + c_cry_void = { + "Void", + "Clusterfuck", + "Cluster", + }, + c_cry_marsmoons = { + "Mars Moons", + "Phobos", + "Phobos and Deimos", + "Ultimate Pair", + }, + c_cry_universe = { + "Universe", + "The Universe In Its Entirety", + "The Universe In Its Fucking Entirety", + "The Entire Deck", + "The Entire Fucking Deck", + }, + c_cry_nstar = { + "Neutron Star", + "Random Hand", + }, + c_cry_sunplanet = { + "Sol", + "Sun Planet", + "Ascended Hands", + "Ascended Hand", + }, + c_cry_Timantti = { + "Ruutu", + "Diamond Planet", + "High Card Pair Two Pair", + }, + c_cry_Klubi = { + "Risti", + "Club Planet", + "Three of a Kind Straight Flush", + "3oak Straight Flush", + }, + c_cry_Sydan = { + "Hertta", + "Heart Planet", + "Full House Four of a Kind Straight Flush", + "Full House 4oak Straight Flush", + }, + c_cry_Lapio = { + "Pata", + "Spade Planet", + "Five of a Kind Flush House Flush Five", + "5oak Flush House Flush Five", + }, + c_cry_Kaikki = { + "Kaikki", + "Wild Planet", + "Bulwark Clusterfuck Ultimate Pair", + "Bulwark Cluster Ultimate Pair", + }, + + -- Cryptid Spectrals + c_cry_lock = { + "Lock", + }, + c_cry_vacuum = { + "Vacuum", + }, + c_cry_hammerspace = { + "Hammerspace", + "CCD", + }, + c_cry_trade = { + "Trade", + }, + c_cry_summoning = { + "Summoning", + }, + c_cry_replica = { + "Replica", + }, + c_cry_analog = { + "Analog", + }, + c_cry_typhoon = { + "Typhoon", + "Azure Seal", + }, + c_cry_ritual = { + "Ritual", + }, + c_cry_adversary = { + "Adversary", + }, + c_cry_chambered = { + "Chambered", + }, + c_cry_conduit = { + "Conduit", + }, + c_cry_white_hole = { + "White Hole", + }, + c_cry_gateway = { + "Gateway", + "Exotic", + }, + c_cry_source = { + "Source", + "Green Seal", + }, + c_cry_pointer = { + "Pointer", + "Pointer://", + "://Pointer", + "self", + }, + + -- Cryptid Unique Consumeables + -- probably not going to be used ever + + -- Cryptid Code Cards + -- 01010000 01001100 01000001 01000011 01000101 01001000 01001111 01001100 01000100 01000101 01010010 + + -- Secret Placeholder 2 + -- another smaller placeholder + + -- Cryptid Booster Packs + -- placeholder in a placeholder in a placeholder in a holdplacer in a placeholder + + -- Cryptid Tags + tag_cry_astral = { + "Astral Tag", + "Astral", + "Free Astral", + }, + tag_cry_banana = { + "Banana Tag", + }, + tag_cry_bettertop_up = { + "Better Top-Up Tag", + "Better Top-Up", + "Better Top Up Tag", + "Better Top Up", + "Uncommon Top Up", + }, + tag_cry_better_voucher = { + "Tier 3 tag", + "Tier 3 voucher tag", + "Golden Voucher", + "Golden Voucher Tag", + "Better Voucher Tag", + }, + tag_cry_blur = { + "Blurred Tag", + "Blurred", + "Free Blurred", + }, + tag_cry_booster = { + "Booster Tag", + "Double Booster Tag", + "Double Booster", + }, + tag_cry_bundle = { + "Bundle Tag", + "Bundle", + }, + tag_cry_cat = { + "Cat Tag", + "meow", + "mrow", + "mrrp", + "purr", + }, + tag_cry_console = { + "Console Tag", + "Console", + "Code Tag", + }, + tag_cry_double_m = { + "Double M", + "Double M Tag", + "Jolly M", + }, + tag_cry_empowered = { + "Empowered Tag", + "Better Spectral", + "Better Spectral Tag", + }, + tag_cry_epic = { + "Epic Tag", + "Half-price Epic Joker", + "Half price Epic Joker", + "Half price Epic", + "Half-price Epic", + }, + tag_cry_gambler = { + "Gambler Tag", + "Gambling Tag", + "Gambling", + "Gambler's Tag", + "LETS GO GAMBLING!", + }, + tag_cry_glass = { + "Fragile Tag", + "Fragile", + "Glass Tag", + "Free Fragile", + }, + tag_cry_glitched = { + "Glitched Tag", + "Glitched", + "Free Glitched", + }, + tag_cry_gold = { + "Gold Tag", + "Golden Tag", + "Gold", + "Free Golden", + }, + tag_cry_gourmand = { + "Gourmand", + "Gourmand Tag", + "Free Food", + }, + tag_cry_loss = { + "Loss", + "Loss Tag", + "Meme Tag", + "Meme Pack Tag", + }, + tag_cry_m = { + "M Tag", + "Jolly Tag", + "Jolly", + "Free Jolly", + }, + tag_cry_memory = { + "Memory Tag", + "Memory", + }, + tag_cry_mosaic = { + "Mosaic", + "Mosaic Tag", + "Free Mosaic", + }, + tag_cry_oversat = { + "Oversat", + "Free Oversat", + "Oversaturated", + "Free Oversaturated", + "Oversaturated Tag", + }, + tag_cry_quadruple = { + "Quadruple", + "Quadruple Tag", + }, + tag_cry_quintuple = { + "Quintuple", + "Quintuple Tag", + }, + tag_cry_rework = { + "Rework Tag", + }, + tag_cry_schematic = { + "Schematic", + "Schematic Tag", + "Guaranteed Brainstorm", + }, + tag_cry_scope = { + "Scope Tag", + "Scope", + }, + tag_cry_triple = { + "Triple", + "Triple Tag", + }, + + -- Cryptid Vouchers + -- placeholder (T1 T2 T1 T2 pattern) + + -- Cryptid T3 Vouchers + -- super strong placeholder + + --[[ + Format: + = { + "", + "", + ... + "", + }, + ]] + -- TARGET: Add Jokers to Alias List +} + +-- How to use the functions to add cards to the list (all case insensitive) +-- +-- Cryptid.pointeratlasify(cardkey, alias, remove) +-- Adds a specified alias to the pointer alias list +-- cardkey = the card's key; "j_joker", "j_cry_dropshot" (string) +-- alias = the alias you want to refer to the card; "Dropshot", "Default Joker" (string) +-- remove = a check for if you wish to remove the specified alias; true or nil (accepts anything lua treats as true) +-- +-- Cryptid.pointerblistify(cardkey, remove) +-- Blacklists a certain card key from being used in pointer (ignored if debug pointer) +-- cardkey = see above +-- remove = see above +-- +-- Cryptid.pointerblistifytype(valkey, value, remove) +-- Blacklists a certain card data from being used in pointer (ignored if debug pointer) +-- valkey = the value you want to compare against; "rarity", "immutable" (string) +-- value = the value you want to blacklist; "cry_exotic", true (any) +-- remove = see above + +local pointeritems = { + pointer, +} + +return { + name = "Pointer://", + items = pointeritems, + init = function() + function Cryptid.inject_pointer_aliases() + --print("[CRYPTID] Inserting Pointer Aliases") + local alify = Cryptid.pointeraliasify + Cryptid.pointerblistifytype("rarity", "cry_exotic", nil) + for key, aliasesTable in pairs(aliases) do + for _, alias in pairs(aliasesTable) do + alify(key, alias, nil) + end + alify(key, key, nil) + end + for _, group in pairs(G.localization.descriptions) do + if + _ ~= "Back" + and _ ~= "Content Set" + and _ ~= "Edition" + and _ ~= "Enhanced" + and _ ~= "Stake" + and _ ~= "Other" + then + for key, card in pairs(group) do + if G.P_CENTERS[key] then + alify(key, type(card.name) == "table" and card.name[1] or card.name, nil) + if G.P_CENTERS[key].name then + alify(key, G.P_CENTERS[key].name, nil) + end + if G.P_CENTERS[key].original_key then + alify(key, G.P_CENTERS[key].original_key, nil) + end + end + end + end + end + end + end, +} diff --git a/Cryptid/items/sleeve.lua b/Cryptid/items/sleeve.lua index 6928cd8..3b4fe37 100644 --- a/Cryptid/items/sleeve.lua +++ b/Cryptid/items/sleeve.lua @@ -3,7 +3,7 @@ if CardSleeves then key = "very_fair_sleeve", name = "Very Fair Sleeve", atlas = "atlasSleeves", - pos = { x = 0, y = 2 }, + pos = { x = 6, y = 1 }, config = { hands = -2, discards = -2 }, unlocked = true, unlock_condition = { deck = "Very Fair Deck", stake = 1 }, @@ -33,7 +33,7 @@ if CardSleeves then name = "Unlimited Sleeve", atlas = "atlasSleeves", pos = { x = 4, y = 0 }, - config = { cry_highlight_limit = 1e20, hand_size = 1 }, + config = { hand_size = 1 }, unlocked = true, unlock_condition = { deck = "Infinite Deck", stake = 1 }, loc_vars = function(self) @@ -41,7 +41,16 @@ if CardSleeves then end, trigger_effect = function(self, args) end, apply = function(self) - G.GAME.modifiers.cry_highlight_limit = self.config.cry_highlight_limit + G.GAME.infinitedeck = true + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.7, + func = function() + SMODS.change_play_limit(1e6) + SMODS.change_discard_limit(1e6) + return true + end, + })) end, }) @@ -150,7 +159,7 @@ if CardSleeves then name = "Redeemed Sleeve", atlas = "atlasSleeves", pos = { x = 7, y = 0 }, - config = { cry_negative_rate = 20, joker_slot = -2 }, + config = {}, unlocked = true, unlock_condition = { deck = "Redeemed Deck", stake = 1 }, loc_vars = function(self) @@ -164,8 +173,8 @@ if CardSleeves then local glowingsleeve = CardSleeves.Sleeve({ key = "glowing_sleeve", name = "Glowing Sleeve", - atlas = "atlasSleeves", - pos = { x = 0, y = 2 }, + atlas = "glowingSleeve", + pos = { x = 4, y = 2 }, config = { cry_glowing = true }, unlocked = true, unlock_condition = { deck = "Glowing Deck", stake = 1 }, @@ -176,9 +185,7 @@ if CardSleeves then if context.context == "eval" and Cryptid.safe_get(G.GAME, "last_blind", "boss") then for i = 1, #G.jokers.cards do if not Card.no(G.jokers.cards[i], "immutable", true) then - Cryptid.with_deck_effects(G.jokers.cards[i], function(card) - Cryptid.misprintize(card, { min = 1.25, max = 1.25 }, nil, true) - end) + Cryptid.manipulate(G.jokers.cards[i], { value = 1.25 }) end end end @@ -190,7 +197,7 @@ if CardSleeves then name = "Critical Sleeve", atlas = "atlasSleeves", pos = { x = 8, y = 0 }, - config = { cry_crit_rate = 0.25, cry_crit_miss_rate = 0.125 }, + config = { cry_crit_rate = 4, cry_crit_miss_rate = 8 }, unlocked = true, unlock_condition = { deck = "Redeemed Deck", stake = 1 }, loc_vars = function(self) @@ -199,9 +206,21 @@ if CardSleeves then apply = function(self) end, trigger_effect = function(self, args) if args.context == "final_scoring_step" then - local crit_poll = pseudorandom(pseudoseed("cry_critical")) - crit_poll = crit_poll / (G.GAME.probabilities.normal or 1) - if crit_poll < self.config.cry_crit_rate then + local aaa = SMODS.pseudorandom_probability( + self, + "cry_critical", + 1, + self.config.cry_crit_rate, + "Critical Sleeve" + ) + local bbb = SMODS.pseudorandom_probability( + self, + "cry_critical", + 1, + self.config.cry_crit_miss_rate, + "Critical Sleeve" + ) + if aaa then args.mult = args.mult ^ 2 update_hand_text({ delay = 0 }, { mult = args.mult, chips = args.chips }) G.E_MANAGER:add_event(Event({ @@ -218,7 +237,7 @@ if CardSleeves then return true end, })) - elseif crit_poll < self.config.cry_crit_rate + self.config.cry_crit_miss_rate then + elseif bbb then args.mult = args.mult ^ 0.5 update_hand_text({ delay = 0 }, { mult = args.mult, chips = args.chips }) G.E_MANAGER:add_event(Event({ @@ -296,7 +315,7 @@ if CardSleeves then key = "beta_sleeve", name = "Nostalgic Sleeve", atlas = "atlasSleeves", - pos = { x = 0, y = 2 }, + pos = { x = 4, y = 1 }, config = { cry_beta = true }, unlocked = true, unlock_condition = { deck = "Nostalgic Deck", stake = 1 }, @@ -314,7 +333,7 @@ if CardSleeves then key = "bountiful_sleeve", name = "Bountiful Sleeve", atlas = "atlasSleeves", - pos = { x = 0, y = 2 }, + pos = { x = 5, y = 1 }, config = { cry_forced_draw_amount = 5 }, unlocked = true, unlock_condition = { deck = "Bountiful Deck", stake = 1 }, @@ -359,7 +378,7 @@ if CardSleeves then name = "Legendary Sleeve", atlas = "atlasSleeves", pos = { x = 1, y = 1 }, - config = { cry_legendary = true, cry_legendary_rate = 0.2 }, + config = { cry_legendary = true, cry_legendary_rate = 5 }, unlocked = true, unlock_condition = { deck = "Legendary Deck", stake = 1 }, loc_vars = function(self) @@ -369,9 +388,15 @@ if CardSleeves then if args.context == "eval" and G.GAME.last_blind and G.GAME.last_blind.boss then if G.jokers then if #G.jokers.cards < G.jokers.config.card_limit then - local legendary_poll = pseudorandom(pseudoseed("cry_legendary")) - legendary_poll = legendary_poll / (G.GAME.probabilities.normal or 1) - if legendary_poll < self.config.cry_legendary_rate then + if + SMODS.pseudorandom_probability( + self, + "cry_legendary", + 1, + self.config.cry_legendary_rate, + "Legendary Sleeve" + ) + then local card = create_card("Joker", G.jokers, true, 4, nil, nil, nil, "") card:add_to_deck() card:start_materialize() @@ -450,26 +475,1378 @@ if CardSleeves then atlas = "atlasSleeves", pos = { x = 0, y = 1 }, config = { + voucher = {}, cry_antimatter = true, - cry_crit_rate = 0.25, --Critical Deck - cry_legendary_rate = 0.2, --Legendary Deck - -- Enhanced Decks - cry_force_enhancement = "random", - cry_force_edition = "random", - cry_force_seal = "random", - cry_forced_draw_amount = 5, + cry_crit_rate = 4, -- Critical Sleeve, Effect Rate + cry_legendary_rate = 5, -- Legendary Sleeve, Effect Rate + cry_negative_rate = 20, + cry_highlight_limit = 1e20, }, unlocked = true, unlock_condition = { deck = "Antimatter Deck", stake = 1 }, - loc_vars = function(self) - return { vars = {} } + loc_vars = function(self, info_queue, center) + -- Green Sleeve, Debt Effect + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_casl_green", + "wins_by_key", + "stake_gold" + ) or 0 + ) ~= 0 + then + if + self.get_current_deck_key() == "b_green" + or ( + self.get_current_deck_key() == "b_cry_antimatter" + and ( + Cryptid.safe_get(G.PROFILES, G.SETTINGS.profile, "deck_usage", "b_green", "wins", 8) + or 0 + ) + ~= 0 + ) + then + self.config.debt_bonus = 2 + if G.STAGE == G.STAGES.RUN then + -- only calculate if we're in a run, otherwise it's bogus + self.config.added_bankrupt = self.config.debt_bonus + * (G.GAME.round_resets.discards + G.GAME.round_resets.hands) + end + end + end + + -- CCD Sleeve, set config. (I do not know if this is important, I am just implementing everything that the corresponding Sleeve had) + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_cry_ccd_sleeve", + "wins_by_key", + "stake_gold" + ) or 0 + ) ~= 0 + then + self.config.cry_conveyor = true + end + + -- Spooky Sleeve, set config. (Ditto w/ CCD) + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_cry_spooky_sleeve", + "wins_by_key", + "stake_gold" + ) or 0 + ) ~= 0 + then + self.config.cry_spooky = true + end + + return { key = Cryptid.gameset_loc(self, { mainline = "balanced", modest = "balanced" }) } + end, + calculate = function(self, sleeve, context) + if context.create_card and context.card then + local card = context.card + local is_booster_pack = card.ability.set == "Booster" + + -- Ghost Sleeve, Special Options + if + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_casl_ghost", + "wins_by_key", + "stake_gold" + ) or 0 ~= 0 + then + if + self.get_current_deck_key() == "b_ghost" + or ( + self.get_current_deck_key() == "b_cry_antimatter" + and ( + Cryptid.safe_get(G.PROFILES, G.SETTINGS.profile, "deck_usage", "b_ghost", "wins", 8) + or 0 ~= 0 + ) + ) + then + local is_spectral_pack = is_booster_pack and (card.ability.name:find("Spectral")) + if is_spectral_pack then + print("is spectral pack!") + card.ability.extra = card.ability.extra + 2 + end + end + end + + -- Zodiac Sleeve, Special + if + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_casl_zodiac", + "wins_by_key", + "stake_gold" + ) or 0 ~= 0 + then + if + self.get_current_deck_key() == "b_zodiac" + or ( + self.get_current_deck_key() == "b_cry_antimatter" + and ( + Cryptid.safe_get(G.PROFILES, G.SETTINGS.profile, "deck_usage", "b_zodiac", "wins", 8) + or 0 ~= 0 + ) + ) + then + if is_booster_pack then + end + local is_arcana_pack = is_booster_pack and (card.ability.name:find("Arcana")) + if is_arcana_pack then + card.ability.extra = card.ability.extra + 2 + end + + local is_celestial_pack = is_booster_pack and (card.ability.name:find("Celestial")) + if is_celestial_pack then + card.ability.extra = card.ability.extra + 2 + end + end + end + end + + -- Glowing Sleeve + if + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_cry_glowing_sleeve", + "wins_by_key", + "stake_gold" + ) or 0 ~= 0 + then + if context.context == "eval" and Cryptid.safe_get(G.GAME, "last_blind", "boss") then + for i = 1, #G.jokers.cards do + if not Card.no(G.jokers.cards[i], "immutable", true) then + Cryptid.manipulate(G.jokers.cards[i], { value = 1.25 }) + end + end + end + end + + -- Plasma Sleeve, Shop Effect + if context.shop_final_pass or context.reroll_shop then + if + self.get_current_deck_key() == "b_plasma" + or ( + self.get_current_deck_key() == "b_cry_antimatter" + and ( + Cryptid.safe_get(G.PROFILES, G.SETTINGS.profile, "deck_usage", "b_plasma", "wins", 8) + or 0 + ) + ~= 0 + ) + then + -- stop controller/mouse from doing anything + local hold = 0.6 -- how long to take to ease the costs, and how long to hold the player + G.CONTROLLER.locks.shop_reroll = true + if G.CONTROLLER:save_cardarea_focus("shop_jokers") then + G.CONTROLLER.interrupt.focus = true + end + + local cardareas = {} + for _, obj in pairs(G) do + if type(obj) == "table" and obj["is"] and obj:is(CardArea) and obj.config.type == "shop" then + cardareas[#cardareas + 1] = obj + end + end + local total_cost, total_items_for_sale = 0, 0 + for _, cardarea in pairs(cardareas) do + for _, card in pairs(cardarea.cards) do + card:set_cost() + local has_coupon_tag = card.area + and card.ability.couponed + and (card.area == G.shop_jokers or card.area == G.shop_booster) + if has_coupon_tag then + -- tags that set price to 0 (coupon, uncommon, rare, etc) + card.cost = 0 + card.ability.couponed = false + end + total_cost = total_cost + card.cost + total_items_for_sale = total_items_for_sale + 1 + end + end + local avg_cost = math.floor((total_cost - 1) / total_items_for_sale) -- make it always be in favour of the player + for _, cardarea in pairs(cardareas) do + for _, card in pairs(cardarea.cards) do + card.cost = math.max(card.cost, card.base_cost) + local mod = avg_cost - card.cost + -- table, value, mod, floor, timer, not_blockable, delay, ease_type + ease_value(card, "cost", mod, nil, nil, true, hold, "quad") + -- card.cost = avg_cost + -- card:set_cost() + end + end + G.E_MANAGER:add_event(Event({ + func = function() + play_sound("gong", 1.2, 0.2) + play_sound("gong", 1.2 * 1.5, 0.1) + play_sound("tarot1", 1.6, 0.8) + attention_text({ + scale = 1.3, + colour = G.C.GOLD, + text = localize("k_balanced"), + hold = 1.5, + align = "cm", + offset = { x = 0, y = -3.5 }, + major = G.play, + }) + return true + end, + })) + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = hold, + func = function() + -- allow player to buy cards again, ONLY after having eased prices + G.CONTROLLER.interrupt.focus = false + G.CONTROLLER.locks.shop_reroll = false + G.CONTROLLER:recall_cardarea_focus("shop_jokers") + return true + end, + })) + end + end + + -- Green Sleeve, Debt Effect + if sleeve.config.debt_bonus then + if context.end_of_round and not context.individual and not context.repetition then + if not sleeve.config.added_bankrupt then + sleeve.config.added_bankrupt = sleeve.config.debt_bonus + * (G.GAME.round_resets.discards + G.GAME.round_resets.hands) + end + G.GAME.bankrupt_at = G.GAME.bankrupt_at + sleeve.config.added_bankrupt + sleeve.config.added_bankrupt = sleeve.config.debt_bonus + * (G.GAME.round_resets.discards + G.GAME.round_resets.hands) + G.GAME.bankrupt_at = G.GAME.bankrupt_at - sleeve.config.added_bankrupt + end + end + + -- Checkered Sleeve + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_casl_checkered", + "wins_by_key", + "stake_gold" + ) or 0 + ) ~= 0 + then + if + not ( + self.get_current_deck_key() == "b_checkered" + or ( + self.get_current_deck_key() == "b_cry_antimatter" + and ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "deck_usage", + "b_checkered", + "wins", + 8 + ) or 0 + ) + ~= 0 + ) + ) + then + local card = context.card + local force_suits = { ["Clubs"] = "Spades", ["Diamonds"] = "Hearts" } + local is_playing_card = card + and (card.ability.set == "Default" or card.ability.set == "Enhanced") + and card.config.card_key + if (context.create_card or context.modify_playing_card) and card and is_playing_card then + for from_suit, to_suit in pairs(force_suits) do + if card.base.suit == from_suit then + local base = SMODS.Suits[to_suit].card_key + .. "_" + .. SMODS.Ranks[card.base.value].card_key + local initial = G.GAME.blind == nil or context.create_card + card:set_base(G.P_CARDS[base], initial) + end + end + end + end + end + end, + + trigger_effect = function(self, args) + -- Legendary Sleeve, Create Joker On Boss Clear + if args.context == "eval" and Cryptid.safe_get(G.GAME, "last_blind", "boss") then + if G.jokers then + if #G.jokers.cards < G.jokers.config.card_limit then + local legendary_poll = pseudorandom(pseudoseed("cry_legendary")) + legendary_poll = legendary_poll / (G.GAME.probabilities.normal or 1) + if + SMODS.pseudorandom_probability( + self, + "cry_legendary", + 1, + self.config.cry_legendary_rate, + "Antimatter Sleeve" + ) + then + local card = create_card("Joker", G.jokers, true, 4, nil, nil, nil, "") + card:add_to_deck() + card:start_materialize() + G.jokers:emplace(card) + return true + else + card_eval_status_text( + G.jokers, + "jokers", + nil, + nil, + nil, + { message = localize("k_nope_ex"), colour = G.C.RARITY[4] } + ) + end + else + card_eval_status_text( + G.jokers, + "jokers", + nil, + nil, + nil, + { message = localize("k_no_room_ex"), colour = G.C.RARITY[4] } + ) + end + end + end end, - trigger_effect = function(self, args) end, apply = function(self) - Cryptid.antimatter_apply() + local function get_random() -- borrowed from CardSleeves + return pseudorandom("slv", 3, 6) + end + Cryptid.antimattersleeve_apply(self) + + -- Green Sleeve, Debt Effect + if self.config.debt_bonus then + G.E_MANAGER:add_event(Event({ + trigger = "after", + func = function() + self.config.added_bankrupt = self.config.debt_bonus + * (G.GAME.round_resets.discards + G.GAME.round_resets.hands) + G.GAME.bankrupt_at = G.GAME.bankrupt_at - self.config.added_bankrupt + return true + end, + })) + end + + -- Legendary Sleeve, Start Joker + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_cry_legendary_sleeve", + "wins_by_key", + "stake_gold" + ) or 0 + ) ~= 0 + then + G.E_MANAGER:add_event(Event({ + func = function() + if G.jokers then + local card = create_card("Joker", G.jokers, true, 4, nil, nil, nil, "") + card:add_to_deck() + card:start_materialize() + G.jokers:emplace(card) + return true + end + end, + })) + end + + -- Encoded Sleeve + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_cry_encoded_sleeve", + "wins_by_key", + "stake_gold" + ) or 0 + ) ~= 0 + then + G.E_MANAGER:add_event(Event({ + func = function() + if G.jokers then + -- Adding a before spawning becuase jen banned copy_paste + if + G.P_CENTERS["j_cry_CodeJoker"] + and (G.GAME.banned_keys and not G.GAME.banned_keys["j_cry_CodeJoker"]) + then + local card = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_cry_CodeJoker") + card:add_to_deck() + card:start_materialize() + G.jokers:emplace(card) + end + if + G.P_CENTERS["j_cry_copypaste"] + and (G.GAME.banned_keys and not G.GAME.banned_keys["j_cry_copypaste"]) + then + local card = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_cry_copypaste") + card:add_to_deck() + card:start_materialize() + G.jokers:emplace(card) + end + return true + end + end, + })) + end + + -- Wormhole Sleeve, Starting Joker + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_cry_wormhole_sleeve", + "wins_by_key", + "stake_gold" + ) or 0 + ) ~= 0 + then + G.E_MANAGER:add_event(Event({ + func = function() + if G.jokers then + local card = + create_card("Joker", G.jokers, nil, "cry_exotic", nil, nil, nil, "cry_wormholesleeve") + card:add_to_deck() + card:start_materialize() + G.jokers:emplace(card) + return true + end + end, + })) + end + + -- Bountiful Sleeve + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_cry_bountiful_sleeve", + "wins_by_key", + "stake_gold" + ) or 0 + ) ~= 0 + then + G.GAME.modifiers.cry_forced_draw_amount = 5 + end + -- Infinite Sleeve + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_cry_infinite_sleeve", + "wins_by_key", + "stake_gold" + ) or 0 + ) ~= 0 + then + G.GAME.modifiers.cry_highlight_limit = self.config.cry_highlight_limit + end + -- Misprint Sleeve + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_cry_misprint_sleeve", + "wins_by_key", + "stake_gold" + ) or 0 + ) ~= 0 + then + G.GAME.modifiers.cry_misprint_min = 1 + G.GAME.modifiers.cry_misprint_max = (G.GAME.modifiers.cry_misprint_max or 1) * 10 + end + -- CCD Sleeve + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_cry_ccd_sleeve", + "wins_by_key", + "stake_gold" + ) or 0 + ) ~= 0 + then + G.GAME.modifiers.cry_ccd = true + end + -- Spooky Sleeve + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_cry_spooky_sleeve", + "wins_by_key", + "stake_gold" + ) or 0 + ) ~= 0 + then + G.GAME.modifiers.cry_spooky = true + G.E_MANAGER:add_event(Event({ + func = function() + if G.jokers then + local card = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_cry_chocolate_dice") + card:add_to_deck() + card:start_materialize() + card:set_eternal(true) + G.jokers:emplace(card) + return true + end + end, + })) + end + -- Redeemed Sleeve + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_cry_redeemed_sleeve", + "wins_by_key", + "stake_gold" + ) or 0 + ) ~= 0 + then + G.GAME.modifiers.cry_redeemed = true + end + -- Balanced Sleeve + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_cry_misprint_sleeve", + "wins_by_key", + "stake_gold" + ) or 0 + ) ~= 0 + then + G.GAME.modifiers.cry_equilibrium = true + end + -- Beige Sleeve + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_cry_beige_sleeve", + "wins_by_key", + "stake_gold" + ) or 0 + ) ~= 0 + then + if + self.get_current_deck_key() == "b_cry_beige" + or ( + self.get_current_deck_key() == "b_cry_antimatter" + and ( + Cryptid.safe_get(G.PROFILES, G.SETTINGS.profile, "deck_usage", "b_cry_beige", "wins", 8) + or 0 + ) + ~= 0 + ) + then + G.GAME.modifiers.cry_uncommon_value_quad = true + else + G.GAME.modifiers.cry_common_value_quad = true + end + end + -- Wormhole Sleeve, Negative Rate + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_cry_wormhole_sleeve", + "wins_by_key", + "stake_gold" + ) or 0 + ) ~= 0 + then + G.GAME.modifiers.cry_negative_rate = (G.GAME.modifiers.cry_negative_rate or 1) + * self.config.cry_negative_rate + end + -- Abandoned Sleeve + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_casl_abandoned", + "wins_by_key", + "stake_gold" + ) or 0 + ) ~= 0 + then + G.GAME.starting_params.no_faces = true + end + -- Erratic Sleeve + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_casl_erratic", + "wins_by_key", + "stake_gold" + ) or 0 + ) ~= 0 + then + if + self.get_current_deck_key() == "b_erratic" + or ( + self.get_current_deck_key() == "b_cry_antimatter" + and ( + Cryptid.safe_get(G.PROFILES, G.SETTINGS.profile, "deck_usage", "b_erratic", "wins", 8) + or 0 + ) + ~= 0 + ) + then + G.GAME.starting_params.dollars = G.GAME.starting_params.dollars + get_random() + G.GAME.starting_params.discards = G.GAME.starting_params.discards + get_random() + G.GAME.starting_params.hands = G.GAME.starting_params.hands + get_random() + G.GAME.starting_params.joker_slots = G.GAME.starting_params.joker_slots + get_random() + else + G.GAME.starting_params.erratic_suits_and_ranks = true + end + end + -- Red Sleeve + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_casl_red", + "wins_by_key", + "stake_gold" + ) or 0 + ) ~= 0 + then + G.GAME.starting_params.discards = G.GAME.starting_params.discards + 1 + end + -- Blue Sleeve + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_casl_blue", + "wins_by_key", + "stake_gold" + ) or 0 + ) ~= 0 + then + G.GAME.starting_params.hands = G.GAME.starting_params.hands + 1 + end + -- Yellow Sleeve + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_casl_yellow", + "wins_by_key", + "stake_gold" + ) or 0 + ) ~= 0 + then + if + not ( + self.get_current_deck_key() == "b_yellow" + or ( + self.get_current_deck_key() == "b_cry_antimatter" + and ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "deck_usage", + "b_yellow", + "wins", + 8 + ) or 0 + ) + ~= 0 + ) + ) + then + G.GAME.starting_params.dollars = G.GAME.starting_params.dollars + 10 + end + end + -- Green Sleeve + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_casl_green", + "wins_by_key", + "stake_gold" + ) or 0 + ) ~= 0 + then + if + not ( + self.get_current_deck_key() == "b_green" + or ( + self.get_current_deck_key() == "b_cry_antimatter" + and ( + Cryptid.safe_get(G.PROFILES, G.SETTINGS.profile, "deck_usage", "b_green", "wins", 8) + or 0 + ) + ~= 0 + ) + ) + then + G.GAME.modifiers.money_per_hand = (G.GAME.modifiers.money_per_hand or 0) + 2 + G.GAME.modifiers.money_per_discard = (G.GAME.modifiers.money_per_discard or 0) + 1 + end + end + -- Black Sleeve + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_casl_black", + "wins_by_key", + "stake_gold" + ) or 0 + ) ~= 0 + then + G.GAME.starting_params.joker_slots = G.GAME.starting_params.joker_slots + 1 + end + -- Ghost Sleeve, Special Spectral Rate + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_casl_ghost", + "wins_by_key", + "stake_gold" + ) or 0 + ) ~= 0 + then + if + self.get_current_deck_key() == "b_ghost" + or ( + self.get_current_deck_key() == "b_cry_antimatter" + and ( + Cryptid.safe_get(G.PROFILES, G.SETTINGS.profile, "deck_usage", "b_ghost", "wins", 8) + or 0 + ) + ~= 0 + ) + then + G.GAME.spectral_rate = G.GAME.spectral_rate * 2 + end + end + -- Painted Sleeve + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_casl_painted", + "wins_by_key", + "stake_gold" + ) or 0 + ) ~= 0 + then + if + self.get_current_deck_key() == "b_painted" + or ( + self.get_current_deck_key() == "b_cry_antimatter" + and ( + Cryptid.safe_get(G.PROFILES, G.SETTINGS.profile, "deck_usage", "b_painted", "wins", 8) + or 0 + ) + ~= 0 + ) + then + if not G.GAME.modifiers.cry_highlight_limit then + G.GAME.modifiers.cry_highlight_limit = 5 + end + G.GAME.modifiers.cry_highlight_limit = G.GAME.modifiers.cry_highlight_limit + 1 + else + G.GAME.starting_params.hand_size = G.GAME.starting_params.hand_size + 2 + end + end + end, + int = function(self) + function Cryptid.antimattersleeve_trigger_final_scoring(self, context, skip) + -- Critical Sleeve + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_cry_critical_sleeve", + "wins_by_key", + "stake_gold" + ) or 0 + ) + ~= 0 + or skip + then + if context.context == "final_scoring_step" then + if + SMODS.pseudorandom_probability( + self, + "cry_critical", + 1, + self.config.cry_crit_rate, + "Antimatter Sleeve" + ) + then + context.mult = context.mult ^ 2 + update_hand_text({ delay = 0 }, { mult = context.mult, chips = context.chips }) + G.E_MANAGER:add_event(Event({ + func = function() + play_sound("talisman_emult", 1) + attention_text({ + scale = 1.4, + text = localize("cry_critical_hit_ex"), + hold = 4, + align = "cm", + offset = { x = 0, y = -1.7 }, + major = G.play, + }) + return true + end, + })) + delay(0.6) + end + end + end + + -- Plasma Sleeve + if + (self.get_current_deck_key() == "b_plasma" or self.get_current_deck_key() == "b_cry_antimatter") + and ( + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_casl_plasma", + "wins_by_key", + "stake_gold" + ) or 0 + ) + ~= 0 + or skip + ) + then + local tot = context.chips + context.mult + context.chips = math.floor(tot / 2) + context.mult = math.floor(tot / 2) + update_hand_text({ delay = 0 }, { mult = context.mult, chips = context.chips }) + + G.E_MANAGER:add_event(Event({ + func = function() + local text = localize("k_balanced") + play_sound("gong", 0.94, 0.3) + play_sound("gong", 0.94 * 1.5, 0.2) + play_sound("tarot1", 1.5) + ease_colour(G.C.UI_CHIPS, { 0.8, 0.45, 0.85, 1 }) + ease_colour(G.C.UI_MULT, { 0.8, 0.45, 0.85, 1 }) + attention_text({ + scale = 1.4, + text = text, + hold = 2, + align = "cm", + offset = { x = 0, y = -2.7 }, + major = G.play, + }) + G.E_MANAGER:add_event(Event({ + trigger = "after", + blockable = false, + blocking = false, + delay = 4.3, + func = function() + ease_colour(G.C.UI_CHIPS, G.C.BLUE, 2) + ease_colour(G.C.UI_MULT, G.C.RED, 2) + return true + end, + })) + G.E_MANAGER:add_event(Event({ + trigger = "after", + blockable = false, + blocking = false, + no_delete = true, + delay = 6.3, + func = function() + G.C.UI_CHIPS[1], G.C.UI_CHIPS[2], G.C.UI_CHIPS[3], G.C.UI_CHIPS[4] = + G.C.BLUE[1], G.C.BLUE[2], G.C.BLUE[3], G.C.BLUE[4] + G.C.UI_MULT[1], G.C.UI_MULT[2], G.C.UI_MULT[3], G.C.UI_MULT[4] = + G.C.RED[1], G.C.RED[2], G.C.RED[3], G.C.RED[4] + return true + end, + })) + return true + end, + })) + delay(0.6) + end + return context.chips, context.mult + end + function Cryptid.antimattersleeve_trigger(self, context, skip) + -- If Last Blind was a Boss + if context.context == "eval" and Cryptid.safe_get(G.GAME, "last_blind", "boss") then + -- Glowing Sleeve, Mult Values Effect + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_cry_glowing_sleeve", + "wins_by_key", + "stake_gold" + ) or 0 + ) + ~= 0 + or skip + then + for i = 1, #G.jokers.cards do + Cryptid.manipulate(G.jokers.cards[i], { value = 1.25 }) + end + end + + -- Legendary Sleeve, Create New Card Effect + if G.jokers then + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_cry_legendary_sleeve", + "wins_by_key", + "stake_gold" + ) or 0 + ) + ~= 0 + or skip + then + if #G.jokers.cards < G.jokers.config.card_limit then + local legendary_poll = pseudorandom(pseudoseed("cry_legendary")) + legendary_poll = legendary_poll / (G.GAME.probabilities.normal or 1) + if legendary_poll < self.config.cry_legendary_rate then + local card = create_card("Joker", G.jokers, true, 4, nil, nil, nil, "") + card:add_to_deck() + card:start_materialize() + G.jokers:emplace(card) + return true + else + card_eval_status_text( + G.jokers, + "jokers", + nil, + nil, + nil, + { message = localize("k_nope_ex"), colour = G.C.RARITY[4] } + ) + end + else + card_eval_status_text( + G.jokers, + "jokers", + nil, + nil, + nil, + { message = localize("k_no_room_ex"), colour = G.C.RARITY[4] } + ) + end + end + end + + -- Anaglyph Sleeve, Normal + if + ( + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_casl_anaglyph", + "wins_by_key", + "stake_gold" + ) or 0 + ) ~= 0 + ) + and not (self.get_current_deck_key() == "b_anaglyph" or (self.get_current_deck_key() == "b_cry_antimatter" and (Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "deck_usage", + "b_anaglyph", + "wins", + 8 + ) or 0) ~= 0)) + or skip + then + G.E_MANAGER:add_event(Event({ + func = function() + add_tag(Tag("tag_double")) + play_sound("generic1", 0.9 + math.random() * 0.1, 0.8) + play_sound("holo1", 1.2 + math.random() * 0.1, 0.4) + return true + end, + })) + end + end + + -- Anaglyph Sleeve, Special + if context.context == "eval" and not Cryptid.safe_get(G.GAME, "last_blind", "boss") then + if + self.get_current_deck_key() == "b_anaglyph" + or (self.get_current_deck_key() == "b_cry_antimatter" and (Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "deck_usage", + "b_anaglyph", + "wins", + 8 + ) or 0) ~= 0) + or skip + then + G.E_MANAGER:add_event(Event({ + func = function() + add_tag(Tag("tag_double")) + play_sound("generic1", 0.9 + math.random() * 0.1, 0.8) + play_sound("holo1", 1.2 + math.random() * 0.1, 0.4) + return true + end, + })) + end + end + end end, }) + function Cryptid.antimattersleeve_apply(self, skip) + G.GAME.starting_params.hands = G.GAME.starting_params.hands + 1 + -- All Decks with Vouchers (see Cryptid.get_antimatter_vouchers) + local vouchers = Cryptid.get_antimattersleeve_vouchers(self, nil, skip) + if #vouchers > 0 then + for k, v in pairs(vouchers) do + if G.P_CENTERS[v] then + G.GAME.used_vouchers[v] = true + G.GAME.starting_voucher_count = (G.GAME.starting_voucher_count or 0) + 1 + G.E_MANAGER:add_event(Event({ + func = function() + Card.apply_to_run(nil, G.P_CENTERS[v]) + return true + end, + })) + end + end + end + --All Consumables (see Cryptid.get_antimatter_consumables) + local querty = Cryptid.get_antimattersleeve_consumables(self, nil, skip) + if #querty > 0 then + delay(0.4) + G.E_MANAGER:add_event(Event({ + func = function() + for k, v in ipairs(querty) do + if G.P_CENTERS[v] then + local card = create_card("Tarot", G.consumeables, nil, nil, nil, nil, v, "deck") + card:add_to_deck() + G.consumeables:emplace(card) + end + end + return true + end, + })) + end + end + function Cryptid.get_antimattersleeve_vouchers(self, voucher_table, skip) + -- Create a table or use one that is passed into the function + if not voucher_table or type(voucher_table) ~= "table" then + voucher_table = {} + end + -- Add Vouchers into the table by key + local function already_exists(t, voucher) + for _, v in ipairs(t) do + if v == voucher then + return true + end + end + return false + end + local function Add_voucher_to_the_table(t, voucher) + if not already_exists(t, voucher) then + table.insert(t, voucher) + end + end + -- Yellow Sleeve, Vouchers (Special) + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_casl_yellow", + "wins_by_key", + "stake_gold" + ) or 0 ~= 0 + ) or skip + then + if + self.get_current_deck_key() == "b_yellow" + or ( + self.get_current_deck_key() == "b_cry_antimatter" + and ( + Cryptid.safe_get(G.PROFILES, G.SETTINGS.profile, "deck_usage", "b_yellow", "wins", 8) + or 0 ~= 0 + ) + ) + then + Add_voucher_to_the_table(voucher_table, "v_seed_money") + end + end + -- Magic Sleeve, Vouchers + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_casl_magic", + "wins_by_key", + "stake_gold" + ) or 0 ~= 0 + ) or skip + then + if + self.get_current_deck_key() == "b_magic" + or ( + self.get_current_deck_key() == "b_cry_antimatter" + and (Cryptid.safe_get(G.PROFILES, G.SETTINGS.profile, "deck_usage", "b_magic", "wins", 8) or 0 ~= 0) + ) + then + Add_voucher_to_the_table(voucher_table, "v_omen_globe") + else + Add_voucher_to_the_table(voucher_table, "v_crystal_ball") + end + end + + -- Nebula Sleeve, Vouchers + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_casl_nebula", + "wins_by_key", + "stake_gold" + ) or 0 ~= 0 + ) or skip + then + if + self.get_current_deck_key() == "b_nebula" + or ( + self.get_current_deck_key() == "b_cry_antimatter" + and ( + Cryptid.safe_get(G.PROFILES, G.SETTINGS.profile, "deck_usage", "b_nebula", "wins", 8) + or 0 ~= 0 + ) + ) + then + Add_voucher_to_the_table(voucher_table, "v_observatory") + else + Add_voucher_to_the_table(voucher_table, "v_telescope") + end + end + + -- Zodiac Sleeve, Vouchers + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_casl_zodiac", + "wins_by_key", + "stake_gold" + ) or 0 ~= 0 + ) or skip + then + if + not ( + self.get_current_deck_key() == "b_zodiac" + or ( + self.get_current_deck_key() == "b_cry_antimatter" + and ( + Cryptid.safe_get(G.PROFILES, G.SETTINGS.profile, "deck_usage", "b_zodiac", "wins", 8) + or 0 ~= 0 + ) + ) + ) + then + Add_voucher_to_the_table(voucher_table, "v_tarot_merchant") + Add_voucher_to_the_table(voucher_table, "v_planet_merchant") + Add_voucher_to_the_table(voucher_table, "v_overstock_norm") + end + end + + -- Balanced Sleeve, Vouchers + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_cry_equilibrium_sleeve", + "wins_by_key", + "stake_gold" + ) or 0 ~= 0 + ) or skip + then + if + self.get_current_deck_key() == "b_cry_equilibrium" + or ( + self.get_current_deck_key() == "b_cry_antimatter" + and ( + Cryptid.safe_get(G.PROFILES, G.SETTINGS.profile, "deck_usage", "b_cry_equilibrium", "wins", 8) + or 0 ~= 0 + ) + ) + then + -- I thought that overstock multi would be a good way to extend the theme of this deck, without letting the game add duplicate vouchers. ~ Slaaneshi Kitten + Add_voucher_to_the_table(voucher_table, "v_cry_overstock_multi") + else + Add_voucher_to_the_table(voucher_table, "v_overstock_norm") + Add_voucher_to_the_table(voucher_table, "v_overstock_plus") + end + end + + return voucher_table + end + function Cryptid.get_antimattersleeve_consumables(self, consumable_table, skip) + if not consumable_table or type(consumable_table) ~= "table" then + consumable_table = {} + end + + -- Magic Sleeve, Consumables + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_casl_magic", + "wins_by_key", + "stake_gold" + ) or 0 ~= 0 + ) or skip + then + if + not ( + self.get_current_deck_key() == "b_magic" + or ( + self.get_current_deck_key() == "b_cry_antimatter" + and ( + Cryptid.safe_get(G.PROFILES, G.SETTINGS.profile, "deck_usage", "b_magic", "wins", 8) + or 0 ~= 0 + ) + ) + ) + then + table.insert(consumable_table, "c_fool") + table.insert(consumable_table, "c_fool") + end + end + + -- Ghost Sleeve, Consumables + if + ( + Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "sleeve_usage", + "sleeve_casl_ghost", + "wins_by_key", + "stake_gold" + ) or 0 ~= 0 + ) or skip + then + if + not ( + self.get_current_deck_key() == "b_ghost" + or ( + self.get_current_deck_key() == "b_cry_antimatter" + and ( + Cryptid.safe_get(G.PROFILES, G.SETTINGS.profile, "deck_usage", "b_ghost", "wins", 8) + or 0 ~= 0 + ) + ) + ) + then + table.insert(consumable_table, "c_hex") + end + end + return consumable_table + end local sleeveitems = {} if CardSleeves then sleeveitems = { diff --git a/Cryptid/items/spectral.lua b/Cryptid/items/spectral.lua index 73f51d1..cfabb0d 100644 --- a/Cryptid/items/spectral.lua +++ b/Cryptid/items/spectral.lua @@ -1,282 +1,3 @@ -local white_hole = { - cry_credits = { - idea = { - "y_not_tony", - }, - art = { - "5381", - }, - code = { - "Math", - }, - }, - object_type = "Consumable", - dependencies = { - items = { - "set_cry_spectral", - }, - }, - set = "Spectral", - name = "cry-White Hole", - key = "white_hole", - pos = { x = 1, y = 4 }, - cost = 4, - order = 40, - atlas = "atlasnotjokers", - hidden = true, --default soul_rate of 0.3% in spectral packs is used - soul_set = "Planet", - loc_vars = function(self, info_queue, card) - return { key = Card.get_gameset(card) == "modest" and "c_cry_white_hole" or "c_cry_white_hole2" } - end, - can_use = function(self, card) - return true - end, - use = function(self, card, area, copier) - local used_consumable = copier or card - local modest = Card.get_gameset(used_consumable) == "modest" - --Get most played hand type (logic yoinked from Telescope) - local _hand, _tally = nil, -1 - for k, v in ipairs(G.handlist) do - if G.GAME.hands[v].visible and G.GAME.hands[v].played > _tally then - _hand = v - _tally = G.GAME.hands[v].played - end - end - local removed_levels = 0 - for k, v in ipairs(G.handlist) do - if to_big(G.GAME.hands[v].level) > to_big(1) then - local this_removed_levels = G.GAME.hands[v].level - 1 - if - -- Due to how these poker hands are loaded they still techically exist even if Poker Hand Stuff is disabled - -- Because they still exist, While Hole needs to ignore levels from these if disabled (via Black Hole, Planet.lua, etc...) - (v ~= "cry_Bulwark" and v ~= "cry_Clusterfuck" and v ~= "cry_UltPair" and v ~= "cry_WholeDeck") - or Cryptid.enabled("set_cry_poker_hand_stuff") == true - then - if v ~= _hand or not modest then - removed_levels = removed_levels + this_removed_levels - level_up_hand(used_consumable, v, true, -this_removed_levels) - end - end - end - end - update_hand_text({ sound = "button", volume = 0.7, pitch = 0.8, delay = 0.3 }, { - handname = localize(_hand, "poker_hands"), - chips = G.GAME.hands[_hand].chips, - mult = G.GAME.hands[_hand].mult, - level = G.GAME.hands[_hand].level, - }) - if modest then - level_up_hand(used_consumable, _hand, false, 4) - else - level_up_hand(used_consumable, _hand, false, 3 * removed_levels) - end - update_hand_text( - { sound = "button", volume = 0.7, pitch = 1.1, delay = 0 }, - { mult = 0, chips = 0, handname = "", level = "" } - ) - end, - --Incantation compat - can_stack = true, - can_divide = true, - can_bulk_use = true, - bulk_use = function(self, card, area, copier, number) - local used_consumable = copier or card - local modest = Card.get_gameset(used_consumable) == "modest" - --Get most played hand type (logic yoinked from Telescope) - local _hand, _tally = nil, -1 - for k, v in ipairs(G.handlist) do - if G.GAME.hands[v].visible and G.GAME.hands[v].played > _tally then - _hand = v - _tally = G.GAME.hands[v].played - end - end - local removed_levels = 0 - for k, v in ipairs(G.handlist) do - if to_big(G.GAME.hands[v].level) > to_big(1) then - local this_removed_levels = G.GAME.hands[v].level - 1 - removed_levels = removed_levels + this_removed_levels - if v ~= _hand or not modest then - level_up_hand(used_consumable, v, true, -this_removed_levels) - end - end - end - update_hand_text({ sound = "button", volume = 0.7, pitch = 0.8, delay = 0.3 }, { - handname = localize(_hand, "poker_hands"), - chips = G.GAME.hands[_hand].chips, - mult = G.GAME.hands[_hand].mult, - level = G.GAME.hands[_hand].level, - }) - if modest then - level_up_hand(used_consumable, _hand, false, 4 * number) - else - level_up_hand(used_consumable, _hand, false, removed_levels * 3 ^ number) - end - update_hand_text( - { sound = "button", volume = 0.7, pitch = 1.1, delay = 0 }, - { mult = 0, chips = 0, handname = "", level = "" } - ) - end, -} -local vacuum = { - cry_credits = { - idea = { - "Mjiojio", - }, - art = { - "Linus Goof Balls", - }, - code = { - "jenwalter666", - }, - }, - object_type = "Consumable", - dependencies = { - items = { - "set_cry_spectral", - }, - }, - set = "Spectral", - name = "cry-Vacuum", - key = "vacuum", - pos = { x = 3, y = 1 }, - config = { extra = 4 }, - cost = 4, - order = 2, - atlas = "atlasnotjokers", - loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra } } - end, - can_use = function(self, card) - return #G.hand.cards > 0 - end, - use = function(self, card, area, copier) - local used_consumable = copier or card - local earnings = 0 - check_for_unlock({ cry_used_consumable = "c_cry_vacuum" }) - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.4, - func = function() - play_sound("tarot1") - used_consumable:juice_up(0.3, 0.5) - return true - end, - })) - for i = 1, #G.hand.cards do - local percent = 1.15 - (i - 0.999) / (#G.hand.cards - 0.998) * 0.3 - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.15, - func = function() - G.hand.cards[i]:flip() - play_sound("card1", percent) - G.hand.cards[i]:juice_up(0.3, 0.3) - return true - end, - })) - end - delay(0.2) - for i = 1, #G.hand.cards do - local CARD = G.hand.cards[i] - if CARD.config.center ~= G.P_CENTERS.c_base then - earnings = earnings + 1 - end - if CARD.edition then - earnings = earnings + 1 - end - if CARD.seal then - earnings = earnings + 1 - end - local percent = 0.85 + (i - 0.999) / (#G.hand.cards - 0.998) * 0.3 - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.15, - func = function() - CARD:flip() - CARD:set_ability(G.P_CENTERS.c_base, true, nil) - CARD:set_edition(nil, true) - CARD:set_seal(nil, true) - play_sound("tarot2", percent) - CARD:juice_up(0.3, 0.3) - return true - end, - })) - end - ease_dollars(earnings * card.ability.extra) - end, -} -local hammerspace = { - cry_credits = { - idea = { - "jenwalter666", - }, - art = { - "AlexZGreat", - }, - code = { - "jenwalter666", - }, - }, - object_type = "Consumable", - dependencies = { - items = { - "set_cry_spectral", - }, - }, - set = "Spectral", - name = "cry-Hammerspace", - key = "hammerspace", - pos = { x = 4, y = 3 }, - config = {}, - cost = 4, - order = 3, - atlas = "atlasnotjokers", - can_use = function(self, card) - return #G.hand.cards > 0 - end, - use = function(self, card, area, copier) - local used_consumable = copier or card - check_for_unlock({ cry_used_consumable = "c_cry_hammerspace" }) - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.4, - func = function() - play_sound("tarot1") - used_consumable:juice_up(0.3, 0.5) - return true - end, - })) - for i = 1, #G.hand.cards do - local percent = 1.15 - (i - 0.999) / (#G.hand.cards - 0.998) * 0.3 - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.15, - func = function() - G.hand.cards[i]:flip() - play_sound("card1", percent) - G.hand.cards[i]:juice_up(0.3, 0.3) - return true - end, - })) - end - delay(0.2) - for i = 1, #G.hand.cards do - local CARD = G.hand.cards[i] - local percent = 0.85 + (i - 0.999) / (#G.hand.cards - 0.998) * 0.3 - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.15, - func = function() - CARD:flip() - CARD:set_ability(Cryptid.random_consumable("cry_hammerspace", nil, "c_cry_hammerspace", nil, true)) - play_sound("tarot2", percent) - CARD:juice_up(0.3, 0.3) - return true - end, - })) - end - end, -} local lock = { cry_credits = { idea = { @@ -301,7 +22,7 @@ local lock = { pos = { x = 0, y = 1 }, config = {}, cost = 4, - order = 1, + order = 451, atlas = "atlasnotjokers", loc_vars = function(self, info_queue, card) info_queue[#info_queue + 1] = { key = "eternal", set = "Other" } @@ -396,11 +117,183 @@ local lock = { func = function() play_sound("card1", 1.1) target:flip() - target:set_eternal(true) + target.ability.eternal = true return true end, })) end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, +} +local vacuum = { + cry_credits = { + idea = { + "Mjiojio", + }, + art = { + "Linus Goof Balls", + }, + code = { + "jenwalter666", + }, + }, + object_type = "Consumable", + dependencies = { + items = { + "set_cry_spectral", + }, + }, + set = "Spectral", + name = "cry-Vacuum", + key = "vacuum", + pos = { x = 3, y = 1 }, + config = { extra = 4 }, + cost = 4, + order = 452, + atlas = "atlasnotjokers", + loc_vars = function(self, info_queue, center) + return { vars = { center.ability.extra } } + end, + can_use = function(self, card) + return #G.hand.cards > 0 + end, + use = function(self, card, area, copier) + local used_consumable = copier or card + local earnings = 0 + check_for_unlock({ cry_used_consumable = "c_cry_vacuum" }) + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.4, + func = function() + play_sound("tarot1") + used_consumable:juice_up(0.3, 0.5) + return true + end, + })) + for i = 1, #G.hand.cards do + local percent = 1.15 - (i - 0.999) / (#G.hand.cards - 0.998) * 0.3 + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.15, + func = function() + G.hand.cards[i]:flip() + play_sound("card1", percent) + G.hand.cards[i]:juice_up(0.3, 0.3) + return true + end, + })) + end + delay(0.2) + for i = 1, #G.hand.cards do + local CARD = G.hand.cards[i] + if CARD.config.center ~= G.P_CENTERS.c_base then + earnings = earnings + 1 + end + if CARD.edition then + earnings = earnings + 1 + end + if CARD.seal then + earnings = earnings + 1 + end + local percent = 0.85 + (i - 0.999) / (#G.hand.cards - 0.998) * 0.3 + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.15, + func = function() + CARD:flip() + CARD:set_ability(G.P_CENTERS.c_base, true, nil) + CARD:set_edition(nil, true) + CARD:set_seal(nil, true) + play_sound("tarot2", percent) + CARD:juice_up(0.3, 0.3) + return true + end, + })) + end + ease_dollars(earnings * card.ability.extra) + end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, +} +local hammerspace = { + cry_credits = { + idea = { + "jenwalter666", + }, + art = { + "AlexZGreat", + }, + code = { + "jenwalter666", + }, + }, + object_type = "Consumable", + dependencies = { + items = { + "set_cry_spectral", + }, + }, + set = "Spectral", + name = "cry-Hammerspace", + key = "hammerspace", + pos = { x = 4, y = 3 }, + config = {}, + cost = 4, + order = 453, + atlas = "atlasnotjokers", + can_use = function(self, card) + return #G.hand.cards > 0 + end, + use = function(self, card, area, copier) + local used_consumable = copier or card + check_for_unlock({ cry_used_consumable = "c_cry_hammerspace" }) + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.4, + func = function() + play_sound("tarot1") + used_consumable:juice_up(0.3, 0.5) + return true + end, + })) + for i = 1, #G.hand.cards do + local percent = 1.15 - (i - 0.999) / (#G.hand.cards - 0.998) * 0.3 + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.15, + func = function() + G.hand.cards[i]:flip() + play_sound("card1", percent) + G.hand.cards[i]:juice_up(0.3, 0.3) + return true + end, + })) + end + delay(0.2) + for i = 1, #G.hand.cards do + local CARD = G.hand.cards[i] + local percent = 0.85 + (i - 0.999) / (#G.hand.cards - 0.998) * 0.3 + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.15, + func = function() + CARD:flip() + CARD:set_ability(Cryptid.random_consumable("cry_hammerspace", nil, "c_cry_hammerspace", nil, true)) + play_sound("tarot2", percent) + CARD:juice_up(0.3, 0.3) + return true + end, + })) + end + end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, } local trade = { cry_credits = { @@ -426,12 +319,12 @@ local trade = { pos = { x = 2, y = 1 }, config = {}, cost = 4, - order = 4, + order = 454, atlas = "atlasnotjokers", can_use = function(self, card) local usable_count = 0 for _, v in pairs(G.vouchers.cards) do - if not v.ability.eternal then + if not SMODS.is_eternal(v) then usable_count = usable_count + 1 end end @@ -457,7 +350,7 @@ local trade = { end end end - if v.ability.eternal then + if SMODS.is_eternal(v) then can_use = false end if can_use then @@ -465,6 +358,9 @@ local trade = { end end local unredeemed_voucher = pseudorandom_element(usable_vouchers, pseudoseed("cry_trade")) + if not unredeemed_voucher then + return + end --redeem extra voucher code based on Betmma's Vouchers local area if G.STATE == G.STATES.HAND_PLAYED then @@ -535,157 +431,9 @@ local trade = { })) end end, -} -local analog = { - cry_credits = { - idea = { - "y_not_tony", - }, - art = { - "RattlingSnow353", - }, - code = { - "Math", - }, - }, - object_type = "Consumable", - dependencies = { - items = { - "set_cry_spectral", - }, - }, - set = "Spectral", - name = "cry-Analog", - key = "analog", - pos = { x = 3, y = 0 }, - config = { copies = 2, ante = 1 }, - loc_vars = function(self, info_queue, center) - return { vars = { center.ability.copies, center.ability.ante } } - end, - cost = 4, - order = 7, - atlas = "atlasnotjokers", - can_use = function(self, card) - return #G.jokers.cards > 0 - end, - use = function(self, card, area, copier) - check_for_unlock({ cry_used_consumable = "c_cry_analog" }) - local used_consumable = copier or card - local deletable_jokers = {} - for k, v in pairs(G.jokers.cards) do - if not v.ability.eternal then - deletable_jokers[#deletable_jokers + 1] = v - end - end - local chosen_joker = pseudorandom_element(G.jokers.cards, pseudoseed("cry_analog_choice")) - local _first_dissolve = nil - G.E_MANAGER:add_event(Event({ - trigger = "before", - delay = 0.75, - func = function() - for k, v in pairs(deletable_jokers) do - if v ~= chosen_joker then - v:start_dissolve(nil, _first_dissolve) - _first_dissolve = true - end - end - return true - end, - })) - for i = 1, card.ability.copies do - G.E_MANAGER:add_event(Event({ - trigger = "before", - delay = 0.4, - func = function() - local card = copy_card(chosen_joker) - card:start_materialize() - card:add_to_deck() - G.jokers:emplace(card) - return true - end, - })) - end - ease_ante(card.ability.ante) - end, -} -local summoning = { - cry_credits = { - idea = { - "AlexZGreat", - }, - art = { - --Summoning's sprite takes some parts from an unused sprite by Rattlingsnow so i'm crediting both users - "Kailen", - "RattlingSnow353", - }, - code = { - "Jevonn", - }, - }, - object_type = "Consumable", - dependencies = { - items = { - "set_cry_spectral", - }, - }, - set = "Spectral", - name = "cry-Summoning", - key = "summoning", - pos = { x = 3, y = 4 }, - cost = 4, - order = 5, - atlas = "atlasnotjokers", - loc_vars = function(self, info_queue, center) - return { - vars = { - Cryptid.enabled("set_cry_epic") == true and localize("k_cry_epic") or localize("k_rare"), - colours = { G.C.RARITY[Cryptid.enabled("set_cry_epic") == true and "cry_epic" or 3] }, - }, - } - end, - can_use = function(self, card) - return #G.jokers.cards > 0 - and #G.jokers.cards <= G.jokers.config.card_limit - --Prevent use if slots are full and all jokers are eternal (would exceed limit) - and #Cryptid.advanced_find_joker(nil, nil, nil, { "eternal" }, true, "j") < G.jokers.config.card_limit - end, - use = function(self, card, area, copier) - local used_consumable = copier or card - local deletable_jokers = {} - for k, v in pairs(G.jokers.cards) do - if not v.ability.eternal then - deletable_jokers[#deletable_jokers + 1] = v - end - end - local chosen_joker = pseudorandom_element(G.jokers.cards, pseudoseed("cry_summoning")) - local value = Cryptid.enabled("set_cry_epic") == true and "cry_epic" or 0.99 - local _first_dissolve = nil - G.E_MANAGER:add_event(Event({ - trigger = "before", - delay = 0.75, - func = function() - for k, v in pairs(deletable_jokers) do - if v == chosen_joker then - v:start_dissolve(nil, _first_dissolve) - _first_dissolve = true - end - end - return true - end, - })) - G.E_MANAGER:add_event(Event({ - trigger = "after", - delay = 0.4, - func = function() - play_sound("timpani") - local card = create_card("Joker", G.jokers, nil, value, nil, nil, nil, "cry_summoning") - card:add_to_deck() - G.jokers:emplace(card) - card:juice_up(0.3, 0.5) - return true - end, - })) - delay(0.6) + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) end, } local replica = { @@ -712,7 +460,7 @@ local replica = { pos = { x = 1, y = 1 }, config = {}, cost = 4, - order = 6, + order = 455, atlas = "atlasnotjokers", can_use = function(self, card) return #G.hand.cards > 0 @@ -744,7 +492,7 @@ local replica = { })) end for i = 1, #G.hand.cards do - if not G.hand.cards[i].ability.eternal then + if not SMODS.is_eternal(G.hand.cards[i]) then G.E_MANAGER:add_event(Event({ func = function() copy_card(chosen_card, G.hand.cards[i]) @@ -768,6 +516,91 @@ local replica = { end delay(0.5) end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, +} +local analog = { + cry_credits = { + idea = { + "y_not_tony", + }, + art = { + "RattlingSnow353", + }, + code = { + "Math", + }, + }, + object_type = "Consumable", + dependencies = { + items = { + "set_cry_spectral", + }, + }, + set = "Spectral", + name = "cry-Analog", + key = "analog", + pos = { x = 6, y = 2 }, + config = { copies = 2, ante = 1, immutable = { max_copies = 200, max_ante = 1e300 } }, + loc_vars = function(self, info_queue, center) + return { + vars = { + math.min(center.ability.copies, center.ability.immutable.max_copies), + math.min(center.ability.ante, center.ability.immutable.max_ante), + }, + } + end, + cost = 4, + order = 456, + atlas = "atlasnotjokers", + can_use = function(self, card) + return #G.jokers.cards > (G.GAME.modifiers.cry_beta and 1 or 0) + end, + use = function(self, card, area, copier) + check_for_unlock({ cry_used_consumable = "c_cry_analog" }) + local used_consumable = copier or card + local deletable_jokers = {} + for k, v in pairs(G.jokers.cards) do + if not SMODS.is_eternal(v) then + deletable_jokers[#deletable_jokers + 1] = v + end + end + local chosen_joker = pseudorandom_element(G.jokers.cards, pseudoseed("cry_analog_choice")) + local _first_dissolve = nil + G.E_MANAGER:add_event(Event({ + trigger = "before", + delay = 0.75, + func = function() + for k, v in pairs(deletable_jokers) do + if v ~= chosen_joker then + v:start_dissolve(nil, _first_dissolve) + _first_dissolve = true + end + end + return true + end, + })) + for i = 1, to_number(math.min(card.ability.copies, card.ability.immutable.max_copies)) do + G.E_MANAGER:add_event(Event({ + trigger = "before", + delay = 0.4, + func = function() + local card = copy_card(chosen_joker) + card:start_materialize() + card:add_to_deck() + G.jokers:emplace(card) + return true + end, + })) + end + ease_ante(math.min(card.ability.ante, card.ability.immutable.max_ante)) + end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, } local ritual = { cry_credits = { @@ -786,7 +619,7 @@ local ritual = { set = "Spectral", name = "cry-Ritual", key = "ritual", - order = 9, + order = 457, config = { max_highlighted = 1, }, @@ -806,21 +639,20 @@ local ritual = { atlas = "atlasnotjokers", pos = { x = 5, y = 1 }, can_use = function(self, card) - if card.area ~= G.hand then - return G.hand and (#G.hand.highlighted == 1) and G.hand.highlighted[1] and not G.hand.highlighted[1].edition - else - local idx = 1 - if G.hand.highlighted[1] == card then - idx = 2 - end - return (#G.hand.highlighted == 2) and not G.hand.highlighted[idx].edition - end + local cards = Cryptid.get_highlighted_cards({ G.hand }, card, 1, card.ability.max_highlighted, function(card) + return not card.edition and not card.will_be_editioned + end) + return #cards > 0 and #cards <= card.ability.max_highlighted end, use = function(self, card, area, copier) local used_consumable = copier or card - for i = 1, #G.hand.highlighted do - local highlighted = G.hand.highlighted[i] + local cards = Cryptid.get_highlighted_cards({ G.hand }, card, 1, card.ability.max_highlighted, function(card) + return not card.edition and not card.will_be_editioned + end) + for i = 1, #cards do + local highlighted = cards[i] if highlighted ~= card then + highlighted.will_be_editioned = true G.E_MANAGER:add_event(Event({ func = function() play_sound("tarot1") @@ -843,6 +675,7 @@ local ritual = { highlighted:set_edition({ negative = true }) end end + highlighted.will_be_editioned = nil end return true end, @@ -859,6 +692,10 @@ local ritual = { end end end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, } local adversary = { cry_credits = { @@ -878,7 +715,7 @@ local adversary = { pos = { x = 6, y = 1 }, config = {}, cost = 4, - order = 10, + order = 458, atlas = "atlasnotjokers", loc_vars = function(self, info_queue, center) if not center.edition or (center.edition and not center.edition.negative) then @@ -953,6 +790,10 @@ local adversary = { end, })) end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, } local chambered = { cry_credits = { @@ -971,12 +812,13 @@ local chambered = { key = "chambered", pos = { x = 5, y = 0 }, config = { extra = { num_copies = 3 } }, + misprintize_caps = { extra = { num_copies = 100 } }, loc_vars = function(self, info_queue, card) info_queue[#info_queue + 1] = { key = "e_negative_consumable", set = "Edition", config = { extra = 1 } } return { vars = { card.ability.extra.num_copies } } end, cost = 4, - order = 11, + order = 459, atlas = "atlasnotjokers", can_use = function(self, card) local filteredCons = {} @@ -1022,6 +864,10 @@ local chambered = { ) end end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, } local conduit = { cry_credits = { @@ -1041,39 +887,39 @@ local conduit = { pos = { x = 6, y = 0 }, config = {}, cost = 4, - order = 12, + order = 460, atlas = "atlasnotjokers", can_use = function(self, card) local combinedTable = {} + dbl = false + no_dbl = false for _, value in ipairs(G.hand.highlighted) do if value ~= card then + if Card.no(value, "dbl") then + no_dbl = true + elseif value.edition and value.edition.cry_double_sided then + dbl = true + end table.insert(combinedTable, value) end end for _, value in ipairs(G.jokers.highlighted) do if value ~= card then + if Card.no(value, "dbl") then + no_dbl = true + elseif value.edition and value.edition.cry_double_sided then + dbl = true + end table.insert(combinedTable, value) end end - return (#combinedTable == 2) + return (#combinedTable == 2 and not (dbl and no_dbl)) end, use = function(self, card, area, copier) local used_consumable = copier or card - local combinedTable = {} - - for _, value in ipairs(G.hand.highlighted) do - if value ~= card then - table.insert(combinedTable, value) - end - end - - for _, value in ipairs(G.jokers.highlighted) do - if value ~= card then - table.insert(combinedTable, value) - end - end + local combinedTable = Cryptid.get_highlighted_cards({ G.hand, G.jokers }, card, 2, 2) local highlighted_1 = combinedTable[1] local highlighted_2 = combinedTable[2] G.E_MANAGER:add_event(Event({ @@ -1090,8 +936,30 @@ local conduit = { trigger = "after", delay = 0.15, func = function() - highlighted_1:flip() - highlighted_2:flip() + if not highlighted_1.edition or not highlighted_1.edition.cry_double_sided then + highlighted_1:flip() + end + if not highlighted_2.edition or not highlighted_2.edition.cry_double_sided then + highlighted_2:flip() + end + if highlighted_1.children.flip then + highlighted_1.children.flip:remove() + highlighted_1.children.flip = nil + end + + if highlighted_1.children.merge_ds then + highlighted_1.children.merge_ds:remove() + highlighted_1.children.merge_ds = nil + end + if highlighted_2.children.flip then + highlighted_2.children.flip:remove() + highlighted_2.children.flip = nil + end + + if highlighted_2.children.merge_ds then + highlighted_2.children.merge_ds:remove() + highlighted_2.children.merge_ds = nil + end play_sound("card1", percent) highlighted_1:juice_up(0.3, 0.3) highlighted_2:juice_up(0.3, 0.3) @@ -1105,9 +973,13 @@ local conduit = { delay = 0.15, func = function() local one_edition = highlighted_1.edition - highlighted_1:flip() + if not highlighted_1.edition or not highlighted_1.edition.cry_double_sided then + highlighted_1:flip() + end highlighted_1:set_edition(highlighted_2.edition) - highlighted_2:flip() + if not highlighted_2.edition or not highlighted_2.edition.cry_double_sided then + highlighted_2:flip() + end highlighted_2:set_edition(one_edition) play_sound("card1", percent) highlighted_1:juice_up(0.3, 0.3) @@ -1135,20 +1007,373 @@ local conduit = { end, })) end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, } + +local white_hole = { + cry_credits = { + idea = { + "y_not_tony", + }, + art = { + "5381", + }, + code = { + "Math", + }, + }, + object_type = "Consumable", + dependencies = { + items = { + "set_cry_spectral", + }, + }, + set = "Spectral", + name = "cry-White Hole", + key = "white_hole", + pos = { x = 1, y = 4 }, + cost = 4, + order = 200000, + atlas = "atlasnotjokers", + hidden = true, --default soul_rate of 0.3% in spectral packs is used + soul_set = "Planet", + loc_vars = function(self, info_queue, card) + return { key = Card.get_gameset(card) == "modest" and "c_cry_white_hole" or "c_cry_white_hole2" } + end, + can_use = function(self, card) + return true + end, + use = function(self, card, area, copier) + local used_consumable = copier or card + local modest = Card.get_gameset(used_consumable) == "modest" + --Get most played hand type (logic yoinked from Telescope) + local _hand, _tally = nil, -1 + for k, v in ipairs(G.handlist) do + if G.GAME.hands[v].visible and G.GAME.hands[v].played > _tally then + _hand = v + _tally = G.GAME.hands[v].played + end + end + local removed_levels = 0 + for k, v in ipairs(G.handlist) do + if to_big(G.GAME.hands[v].level) > to_big(1) then + local this_removed_levels = G.GAME.hands[v].level - 1 + if + -- Due to how these poker hands are loaded they still techically exist even if Poker Hand Stuff is disabled + -- Because they still exist, While Hole needs to ignore levels from these if disabled (via Black Hole, Planet.lua, etc...) + (v ~= "cry_Bulwark" and v ~= "cry_Clusterfuck" and v ~= "cry_UltPair" and v ~= "cry_WholeDeck") + or Cryptid.enabled("set_cry_poker_hand_stuff") == true + then + if v ~= _hand or not modest then + removed_levels = removed_levels + this_removed_levels + level_up_hand(used_consumable, v, true, -this_removed_levels) + end + end + end + end + update_hand_text({ sound = "button", volume = 0.7, pitch = 0.8, delay = 0.3 }, { + handname = localize(_hand, "poker_hands"), + chips = G.GAME.hands[_hand].chips, + mult = G.GAME.hands[_hand].mult, + level = G.GAME.hands[_hand].level, + }) + if modest then + level_up_hand(used_consumable, _hand, false, 4) + else + level_up_hand(used_consumable, _hand, false, math.min((3 * removed_levels), 1e300)) + end + update_hand_text( + { sound = "button", volume = 0.7, pitch = 1.1, delay = 0 }, + { mult = 0, chips = 0, handname = "", level = "" } + ) + end, + --Incantation compat + can_stack = true, + can_divide = true, + can_bulk_use = true, + bulk_use = function(self, card, area, copier, number) + local used_consumable = copier or card + local modest = Card.get_gameset(used_consumable) == "modest" + --Get most played hand type (logic yoinked from Telescope) + local _hand, _tally = nil, -1 + for k, v in ipairs(G.handlist) do + if G.GAME.hands[v].visible and G.GAME.hands[v].played > _tally then + _hand = v + _tally = G.GAME.hands[v].played + end + end + local removed_levels = 0 + for k, v in ipairs(G.handlist) do + if to_big(G.GAME.hands[v].level) > to_big(1) then + local this_removed_levels = G.GAME.hands[v].level - 1 + removed_levels = removed_levels + this_removed_levels + if v ~= _hand or not modest then + level_up_hand(used_consumable, v, true, -this_removed_levels) + end + end + end + update_hand_text({ sound = "button", volume = 0.7, pitch = 0.8, delay = 0.3 }, { + handname = localize(_hand, "poker_hands"), + chips = G.GAME.hands[_hand].chips, + mult = G.GAME.hands[_hand].mult, + level = G.GAME.hands[_hand].level, + }) + if modest then + level_up_hand(used_consumable, _hand, false, 4 * number) + else + level_up_hand(used_consumable, _hand, false, math.min(((3 ^ number) * removed_levels), 1e300)) + end + update_hand_text( + { sound = "button", volume = 0.7, pitch = 1.1, delay = 0 }, + { mult = 0, chips = 0, handname = "", level = "" } + ) + end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, +} + +local typhoon = { + cry_credits = { + idea = { + "stupid", + }, + art = { + "stupid", + }, + code = { + "stupid", + }, + }, + object_type = "Consumable", + dependencies = { + items = { + "set_cry_spectral", + "cry_azure", + }, + }, + set = "Spectral", + name = "cry-Typhoon", + key = "typhoon", + order = 8, + config = { + -- This will add a tooltip. + mod_conv = "cry_azure_seal", + -- Tooltip args + seal = { planets_amount = 3 }, + max_highlighted = 1, + }, + loc_vars = function(self, info_queue, center) + -- Handle creating a tooltip with set args. + info_queue[#info_queue + 1] = + { set = "Other", key = "cry_azure_seal", specific_vars = { self.config.seal.planets_amount } } + return { vars = { center.ability.max_highlighted } } + end, + cost = 4, + atlas = "atlasnotjokers", + pos = { x = 0, y = 4 }, + use = function(self, card, area, copier) --Good enough + local used_consumable = copier or card + check_for_unlock({ cry_used_consumable = "c_cry_typhoon" }) + local cards = Cryptid.get_highlighted_cards({ G.hand }, card, 1, card.ability.max_highlighted) + for i = 1, #cards do + local highlighted = cards[i] + G.E_MANAGER:add_event(Event({ + func = function() + play_sound("tarot1") + highlighted:juice_up(0.3, 0.5) + return true + end, + })) + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.1, + func = function() + if highlighted then + highlighted:set_seal("cry_azure") + end + return true + end, + })) + delay(0.5) + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.2, + func = function() + G.hand:unhighlight_all() + return true + end, + })) + end + end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, +} + +local meld = { + object_type = "Consumable", + dependencies = { + items = { + "set_cry_spectral", + "e_cry_double_sided", + }, + }, + set = "Spectral", + name = "cry-Meld", + key = "meld", + order = 9, + pos = { x = 4, y = 4 }, + cost = 4, + atlas = "atlasnotjokers", + can_use = function(self, card) + local cards = Cryptid.get_highlighted_cards({ G.jokers, G.hand }, card, 1, 1, function(card) + return not Card.no(card, "dbl") and not card.edition + end) + return #cards == 1 + end, + cry_credits = { + art = { + "George The Rat", + }, + code = { + "Math", + }, + jolly = { + "Jolly Open Winner", + "Axolotolus", + }, + }, + loc_vars = function(self, info_queue) + info_queue[#info_queue + 1] = G.P_CENTERS.e_cry_double_sided + end, + use = function(self, card, area, copier) + local cards = Cryptid.get_highlighted_cards({ G.jokers, G.hand }, card, 1, 1) + if #cards == 1 then + if cards[1].area == G.jokers then + cards[1]:remove_from_deck(true) + cards[1]:set_edition({ cry_double_sided = true }) + cards[1]:add_to_deck(true) + G.jokers:remove_from_highlighted(cards[1]) + else + cards[1]:set_edition({ cry_double_sided = true }) + G.hand:remove_from_highlighted(cards[1]) + end + end + end, + in_pool = function() + return G.GAME.used_vouchers.v_cry_double_slit + end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, +} + +-- Summoning: To Be Moved Into Epic.lua +-- Destroy a random joker and create an epic joker +local summoning = { + cry_credits = { + idea = { + "AlexZGreat", + }, + art = { + "Nova", + }, + code = { + "Jevonn", + }, + }, + object_type = "Consumable", + dependencies = { + items = { + "set_cry_spectral", + }, + }, + set = "Spectral", + name = "cry-Summoning", + key = "summoning", + pos = { x = 3, y = 4 }, + cost = 4, + order = 5, + atlas = "atlasnotjokers", + loc_vars = function(self, info_queue, center) + return { + vars = { + Cryptid.enabled("set_cry_epic") == true and localize("k_cry_epic") or localize("k_rare"), + colours = { G.C.RARITY[Cryptid.enabled("set_cry_epic") == true and "cry_epic" or 3] }, + }, + } + end, + can_use = function(self, card) + return #G.jokers.cards <= G.jokers.config.card_limit + --Prevent use if slots are full and all jokers are eternal (would exceed limit) + and #Cryptid.advanced_find_joker(nil, nil, nil, { "eternal" }, true, "j") < G.jokers.config.card_limit + end, + use = function(self, card, area, copier) + local used_consumable = copier or card + local deletable_jokers = {} + for k, v in pairs(G.jokers.cards) do + if not SMODS.is_eternal(v) then + deletable_jokers[#deletable_jokers + 1] = v + end + end + local chosen_joker = pseudorandom_element(G.jokers.cards, pseudoseed("cry_summoning")) + local value = Cryptid.enabled("set_cry_epic") == true and "cry_epic" or 0.99 + local _first_dissolve = nil + G.E_MANAGER:add_event(Event({ + trigger = "before", + delay = 0.75, + func = function() + for k, v in pairs(deletable_jokers) do + if v == chosen_joker then + v:start_dissolve(nil, _first_dissolve) + _first_dissolve = true + end + end + return true + end, + })) + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.4, + func = function() + play_sound("timpani") + local card = create_card("Joker", G.jokers, nil, value, nil, nil, nil, "cry_summoning") + card:add_to_deck() + G.jokers:emplace(card) + card:juice_up(0.3, 0.5) + return true + end, + })) + delay(0.6) + end, + demicoloncompat = true, + force_use = function(self, card, area) + self:use(card, area) + end, +} + local spectrals = { - white_hole, + lock, vacuum, hammerspace, - lock, trade, - analog, replica, + analog, + ritual, adversary, chambered, conduit, - summoning, - ritual, + meld, + summoning, -- to be moved to epic.lua + typhoon, -- to be moved to misc.lua + white_hole, } return { name = "Spectrals", diff --git a/Cryptid/items/spooky.lua b/Cryptid/items/spooky.lua index e000c51..2d2c51e 100644 --- a/Cryptid/items/spooky.lua +++ b/Cryptid/items/spooky.lua @@ -11,12 +11,15 @@ local cotton_candy = { cost = 10, atlas = "atlasspooky", order = 130, - blueprint_compat = true, eternal_compat = false, perishable_compat = false, + demicoloncompat = true, pools = { ["Food"] = true }, calculate = function(self, card, context) - if context.selling_self and not context.retrigger_joker and not context.blueprint_card then + if + (context.selling_self and not context.retrigger_joker and not context.blueprint_card) + or context.forcetrigger + then for i = 1, #G.jokers.cards do if G.jokers.cards[i] == card then if i > 1 then @@ -42,9 +45,10 @@ local wrapped = { rarity = "cry_candy", cost = 10, atlas = "atlasspooky", + order = 131, eternal_compat = false, perishable_compat = false, - order = 131, + demicoloncompat = true, immutable = true, config = { extra = { rounds = 2 } }, pools = { ["Food"] = true }, @@ -92,11 +96,16 @@ local wrapped = { card:add_to_deck() G.jokers:emplace(card) return { - message = localize("k_extinct_ex"), + message = localize("k_eaten_ex"), colour = G.C.FILTER, } end end + if context.forcetrigger then + local card = create_card("Food", G.jokers, nil, nil, nil, nil, nil, "cry_wrapped") + card:add_to_deck() + G.jokers:emplace(card) + end end, } local choco_dice = { @@ -157,31 +166,29 @@ local choco1 = { object_type = "Event", key = "choco1", loc_vars = function(self, info_queue, center) + local _, aaa = SMODS.get_probability_vars(self, 1, 6, "Chocolate Dice 1") info_queue[#info_queue + 1] = { set = "Other", key = self.key } --todo specific_vars info_queue[#info_queue + 1] = { set = "Other", key = "cry_flickering_desc", specific_vars = { 5 } } - info_queue[#info_queue + 1] = - { set = "Joker", key = "j_cry_ghost", specific_vars = { G.GAME.probabilities.normal or 1, 2, 6 } } + info_queue[#info_queue + 1] = { + set = "Joker", + key = "j_cry_ghost", + specific_vars = { SMODS.get_probability_vars(self, 1, 2, "Chocolate Dice 1"), aaa }, + } end, start = function(self) G.GAME.events[self.key] = true local areas = { "jokers", "deck", "hand", "play", "discard" } for k, v in pairs(areas) do for i = 1, #G[v].cards do - if pseudorandom(pseudoseed("cry_choco_possession")) < G.GAME.probabilities.normal / 3 then + if SMODS.pseudorandom_probability(self, "cry_choco_possession", 1, 3, "Chocolate Dice 1") then SMODS.Stickers.cry_flickering:apply(G[v].cards[i], true) end end end --create a ghost - if not (SMODS.Mods["jen"] or {}).can_load then - local card = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_cry_ghost") - card:add_to_deck() - G.jokers:emplace(card) - else - if G.GAME.dollars ~= 0 then - ease_dollars((-G.GAME.dollars - 1e6), true) - end - end + local card = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_cry_ghost") + card:add_to_deck() + G.jokers:emplace(card) end, } local choco2 = { @@ -233,11 +240,11 @@ local choco3 = { end, finish = function(self) --Reverse all potion effects - if G.GAME.events[self.key].potions[2] then + if G.GAME.events[self.key].potions and G.GAME.events[self.key].potions[2] then G.GAME.starting_params.ante_scaling = G.GAME.starting_params.ante_scaling / (1.15 ^ G.GAME.events[self.key].potions[2]) end - if G.GAME.events[self.key].potions[3] then + if G.GAME.events[self.key].potions and G.GAME.events[self.key].potions[3] then G.GAME.round_resets.hands = G.GAME.round_resets.hands + G.GAME.events[self.key].potions[3] ease_hands_played(G.GAME.events[self.key].potions[3]) G.GAME.round_resets.discards = G.GAME.round_resets.discards + G.GAME.events[self.key].potions[3] @@ -380,7 +387,7 @@ local choco4 = { --lunar abyss and not context.retrigger_joker then for i = 1, #G.play.cards do - if pseudorandom(pseudoseed("cry_choco_lunar")) < G.GAME.probabilities.normal / 4 then + if SMODS.pseudorandom_probability(self, "cry_choco_lunar", 1, 4, "Chocolate Dice 4") then local faces = {} for _, v in ipairs(SMODS.Rank.obj_buffer) do local r = SMODS.Ranks[v] @@ -444,11 +451,14 @@ local choco5 = { --bloodsucker and not context.retrigger_joker then if context.destroying_card:is_suit("Hearts") or context.destroying_card:is_suit("Diamonds") then - if pseudorandom(pseudoseed("cry_choco_blood")) < G.GAME.probabilities.normal / 3 then + if SMODS.pseudorandom_probability(self, "cry_choco_blood", 1, 3, "Chocolate Dice 5") then context.destroying_card.will_shatter = true + local destroying_card = context.destroying_card G.E_MANAGER:add_event(Event({ func = function() - context.destroying_card:start_dissolve() + if destroying_card then + destroying_card:start_dissolve() + end return true end, })) @@ -753,7 +763,7 @@ local flickering = { return { vars = { 5, card.ability.flick_tally or 5 } } end, apply = function(self, card, val) - if not card.ability.eternal or G.GAME.modifiers.cry_sticker_sheet then + if not SMODS.is_eternal(card) or G.GAME.modifiers.cry_sticker_sheet then card.ability[self.key] = val if card.ability[self.key] then card.ability.flick_tally = 5 @@ -824,6 +834,17 @@ local trick_or_treat = { "set_cry_cursed", }, }, + config = { + extra = { + odds = 4, + num_candies = 2, + }, + immutable = { + prob_mod = 3, + max_candies = 40, + }, + }, + key = "trick_or_treat", pos = { x = 2, y = 1 }, rarity = 2, @@ -833,23 +854,51 @@ local trick_or_treat = { blueprint_compat = true, eternal_compat = false, perishable_compat = false, + demicoloncompat = true, calculate = function(self, card, context) if context.selling_self then - if pseudorandom(pseudoseed("cry_trick_or_treat")) < 3 / 4 * G.GAME.probabilities.normal then - for i = 1, 2 do - local card = create_card("Joker", G.jokers, nil, "cry_candy", nil, nil, nil, "cry_trick_candy") - card:add_to_deck() - G.jokers:emplace(card) + if + SMODS.pseudorandom_probability( + card, + "cry_trick_or_treat", + 1, + card and card.ability.extra.odds or self.config.extra.odds + ) + then + local spawn_num = + to_number(math.min(card.ability.immutable.max_candies, card.ability.extra.num_candies)) + + for i = 1, spawn_num do + local new_card = create_card("Joker", G.jokers, nil, "cry_candy", nil, nil, nil, "cry_trick_candy") + new_card:add_to_deck() + G.jokers:emplace(new_card) end else - local card = create_card("Joker", G.jokers, nil, "cry_cursed", nil, nil, nil, "cry_trick_curse") - card:add_to_deck() - G.jokers:emplace(card) + local new_cursed = create_card("Joker", G.jokers, nil, "cry_cursed", nil, nil, nil, "cry_trick_curse") + new_cursed:add_to_deck() + G.jokers:emplace(new_cursed) + end + end + if context.forcetrigger then + local spawn_num = to_number(math.min(card.ability.immutable.max_candies, card.ability.extra.num_candies)) + + for i = 1, spawn_num do + local new_card = create_card("Joker", G.jokers, nil, "cry_candy", nil, nil, nil, "cry_trick_candy") + new_card:add_to_deck() + G.jokers:emplace(new_card) end end end, loc_vars = function(self, info_queue, center) - return { vars = { 3 * G.GAME.probabilities.normal, 4 } } + local num, denom = + SMODS.get_probability_vars(card, 1, card and card.ability.extra.odds or self.config.extra.odds) + return { + vars = { + num, + denom, + number_format(center.ability.extra.num_candies), + }, + } end, } local candy_basket = { @@ -868,32 +917,81 @@ local candy_basket = { blueprint_compat = false, eternal_compat = false, perishable_compat = false, - config = { extra = { candies = 0, candy_mod = 0.5, candy_boss_mod = 2 } }, + demicoloncompat = true, + config = { + extra = { + candies = 0, + candy_mod = 1, + candy_boss_mod = 2, + }, + immutable = { + current_win_count = 0, + wins_needed = 2, + max_spawn = 100, + }, + }, calculate = function(self, card, context) if context.selling_self then - for i = 1, math.min(100, card.ability.extra.candies) do + for i = 1, math.floor(math.min(card.ability.immutable.max_spawn, card.ability.extra.candies)) do local card = create_card("Joker", G.jokers, nil, "cry_candy", nil, nil, nil, "cry_candy_basket") card:add_to_deck() G.jokers:emplace(card) end end if context.end_of_round and not context.individual and not context.repetition then - candy_pre = math.floor(card.ability.extra.candies) - card.ability.extra.candies = card.ability.extra.candies + card.ability.extra.candy_mod + card.ability.immutable.current_win_count = card.ability.immutable.current_win_count + 1 + if G.GAME.blind.boss then - card.ability.extra.candies = card.ability.extra.candies + card.ability.extra.candy_boss_mod + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "candies", + scalar_value = "candy_boss_mod", + operation = function(ref_table, ref_value, initial, change) + ref_table[ref_value] = initial + change * card.ability.extra.candy_boss_mod + end, + no_message = true, + }) end - if math.floor(card.ability.extra.candies) > candy_pre then - card_eval_status_text(card, "extra", nil, nil, nil, { message = localize("k_upgrade_ex") }) + if card.ability.immutable.current_win_count >= card.ability.immutable.wins_needed then + card.ability.immutable.current_win_count = 0 + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "candies", + scalar_value = "candy_mod", + }) + end + end + if context.forcetrigger then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "candies", + scalar_value = "candy_boss_mod", + operation = function(ref_table, ref_value, initial, change) + ref_table[ref_value] = initial + change * card.ability.extra.candy_boss_mod + end, + no_message = true, + }) + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "candies", + scalar_value = "candy_mod", + }) + for i = 1, math.floor(math.min(card.ability.immutable.max_spawn, card.ability.extra.candies)) do + local card = create_card("Joker", G.jokers, nil, "cry_candy", nil, nil, nil, "cry_candy_basket") + card:add_to_deck() + G.jokers:emplace(card) end end end, loc_vars = function(self, info_queue, center) return { vars = { - math.floor(center.ability.extra.candies), - 2 * center.ability.extra.candy_mod, - center.ability.extra.candy_boss_mod, + number_format(math.floor(math.min(center.ability.immutable.max_spawn, center.ability.extra.candies))), + number_format(center.ability.extra.candy_mod), + center.ability.immutable.wins_needed, + number_format( + lenient_bignum(to_big(center.ability.extra.candy_mod) * center.ability.extra.candy_boss_mod) + ), }, } end, @@ -911,22 +1009,24 @@ local blacklist = { cost = 0, atlas = "atlasspooky", order = 136, - config = { extra = { blacklist = {} } }, + config = { extra = { blacklist = 14 } }, blueprint_compat = false, eternal_compat = false, perishable_compat = false, + demicoloncompat = true, no_dbl = true, + immutable = true, calculate = function(self, card, context) if context.joker_main then local blacklist = false for i = 1, #G.play.cards do - if G.play.cards[i]:get_id() == card.ability.extra.blacklist.id then + if G.play.cards[i]:get_id() == card.ability.extra.blacklist then blacklist = true break end end for i = 1, #G.hand.cards do - if G.hand.cards[i]:get_id() == card.ability.extra.blacklist.id then + if G.hand.cards[i]:get_id() == card.ability.extra.blacklist then blacklist = true break end @@ -941,13 +1041,13 @@ local blacklist = { } else for i = 1, #G.discard.cards do - if G.discard.cards[i]:get_id() == card.ability.extra.blacklist.id then + if G.discard.cards[i]:get_id() == card.ability.extra.blacklist then blacklist = true break end end for i = 1, #G.deck.cards do - if G.deck.cards[i]:get_id() == card.ability.extra.blacklist.id then + if G.deck.cards[i]:get_id() == card.ability.extra.blacklist then blacklist = true break end @@ -962,14 +1062,31 @@ local blacklist = { end end end + if context.forcetrigger then + G.E_MANAGER:add_event(Event({ + func = function() + card:start_dissolve() + return true + end, + })) + end end, add_to_deck = function(self, card, from_debuff) card.ability.extra.blacklist = - pseudorandom_element(SMODS.Ranks, pseudoseed("cry_blacklist" .. G.GAME.round_resets.ante)) + pseudorandom_element(SMODS.Ranks, pseudoseed("cry_blacklist" .. G.GAME.round_resets.ante)).id end, loc_vars = function(self, info_queue, center) return { - vars = { localize(center.ability.extra.blacklist and center.ability.extra.blacklist.key or "Ace", "ranks") }, + vars = { + localize( + center.ability.extra.blacklist == 14 and "Ace" + or center.ability.extra.blacklist == 13 and "King" + or center.ability.extra.blacklist == 12 and "Queen" + or center.ability.extra.blacklist == 11 and "Jack" + or number_format(center.ability.extra.blacklist), + "ranks" + ), + }, } end, } @@ -982,7 +1099,13 @@ local ghost = { }, key = "ghost", pos = { x = 3, y = 0 }, - config = { extra = { possess_rate = 2, destroy_rate = 6 } }, + config = { + extra = { + odds = 1, + possess_rate = 2, + destroy_rate = 6, + }, + }, rarity = "cry_cursed", cost = 0, order = 137, @@ -1000,16 +1123,19 @@ local ghost = { and not context.retrigger_joker then if - pseudorandom(pseudoseed("cry_ghost_destroy")) - < cry_prob(card.ability.cry_prob, card.ability.extra.destroy_rate, card.ability.cry_rigged) - / card.ability.extra.destroy_rate + SMODS.pseudorandom_probability( + card, + "cry_ghost_destroy", + 1, + (card and card.ability.extra.odds or self.config.extra.odds) * card.ability.extra.destroy_rate + ) then G.E_MANAGER:add_event(Event({ func = function() card:start_dissolve() for i = 1, #G.jokers.cards do if G.jokers.cards[i].ability.cry_possessed then - if G.jokers.cards[i].ability.eternal then + if SMODS.is_eternal(G.jokers.cards[i]) then G.jokers.cards[i].ability.cry_possessed = nil else G.jokers.cards[i]:start_dissolve() @@ -1023,9 +1149,12 @@ local ghost = { end --todo: let multiple ghosts possess multiple jokers if - pseudorandom(pseudoseed("cry_ghost_possess")) - < cry_prob(card.ability.cry_prob, card.ability.extra.possess_rate, card.ability.cry_rigged) - / card.ability.extra.possess_rate + SMODS.pseudorandom_probability( + card, + "ghostdestroy", + 1, + (card and card.ability.extra.odds or self.config.extra.odds) * card.ability.extra.possess_rate + ) then for i = 1, #G.jokers.cards do G.jokers.cards[i].ability.cry_possessed = nil @@ -1046,11 +1175,22 @@ local ghost = { end, loc_vars = function(self, info_queue, card) info_queue[#info_queue + 1] = { set = "Other", key = "cry_possessed" } + local num, denom = SMODS.get_probability_vars( + card, + 1, + (card and card.ability.extra.odds or self.config.extra.odds) * card.ability.extra.destroy_rate + ) + local num2, denom2 = SMODS.get_probability_vars( + card, + 1, + (card and card.ability.extra.odds or self.config.extra.odds) * card.ability.extra.possess_rate + ) return { vars = { - cry_prob(card.ability.cry_prob, card.ability.extra.destroy_rate, card.ability.cry_rigged), - card.ability.extra.possess_rate, - card.ability.extra.destroy_rate, + num2, + num1, + denom2, + denom1, }, } end, @@ -1069,6 +1209,107 @@ local possessed = { no_sticker_sheet = true, badge_colour = HEX("aaaaaa"), } + +local rotten_egg = { + object_type = "Joker", + dependencies = { + items = { + "set_cry_cursed", + }, + }, + key = "rotten_egg", + pos = { x = 3, y = 3 }, + config = { + extra = { + starting_money = 1, + lose_money = 1, + needed_money = 10, + left_money = 10, + }, + }, + rarity = "cry_cursed", + cost = 0, + order = 136.1, --gross but cryptid doesnt partition orderings and im not shifting everything + atlas = "atlasspooky", + blueprint_compat = false, + eternal_compat = false, + perishable_compat = false, + demicoloncompat = true, + no_dbl = true, + add_to_deck = function(self, card, from_debuff) + G.GAME.cry_rotten_amount = card.ability.extra.starting_money + for k, v in pairs(G.I.CARD) do + if v.set_cost then + v:set_cost() + end + end + end, + remove_from_deck = function() + G.GAME.cry_rotten_amount = nil + for k, v in pairs(G.I.CARD) do + if v.set_cost then + v:set_cost() + end + end + end, + calculate = function(self, card, context) + if + context.end_of_round + and not context.blueprint + and not context.individual + and not context.repetition + and not context.retrigger_joker + then + for i, v in pairs(G.jokers.cards) do + v.sell_cost = v.sell_cost - 1 + end + return { + message = localize("k_downgraded_ex"), + } + end + if + context.selling_card + and context.card.ability.set == "Joker" + and context.card + and context.card.sell_cost ~= 0 + then + card.ability.extra.left_money = card.ability.extra.left_money - context.card.sell_cost + if to_big(card.ability.extra.left_money) <= to_big(0) then + G.E_MANAGER:add_event(Event({ + func = function() + card:start_dissolve() + return true + end, + })) + else + return { + message = number_format(card.ability.extra.needed_money - card.ability.extra.left_money) + .. "/" + .. number_format(card.ability.extra.needed_money), + } + end + end + if context.forcetrigger then + G.E_MANAGER:add_event(Event({ + func = function() + card:start_dissolve() + return true + end, + })) + end + end, + loc_vars = function(self, info_queue, card) + return { + vars = { + number_format(card.ability.extra.starting_money), + number_format(card.ability.extra.lose_money), + number_format(card.ability.extra.needed_money), + number_format(card.ability.extra.left_money), + }, + } + end, +} + local spookydeck = { object_type = "Back", dependencies = { @@ -1154,6 +1395,8 @@ local candy_dagger = { order = 138, atlas = "atlasspooky", blueprint_compat = true, + demicoloncompat = true, + immutable = true, calculate = function(self, card, context) local my_pos = nil for i = 1, #G.jokers.cards do @@ -1167,7 +1410,7 @@ local candy_dagger = { and not (context.blueprint_card or self).getting_sliced and my_pos and G.jokers.cards[my_pos + 1] - and not G.jokers.cards[my_pos + 1].ability.eternal + and not SMODS.is_eternal(G.jokers.cards[my_pos + 1]) and not G.jokers.cards[my_pos + 1].getting_sliced then local sliced_card = G.jokers.cards[my_pos + 1] @@ -1199,6 +1442,35 @@ local candy_dagger = { G.jokers:emplace(card) return nil, true end + if context.forcetrigger and my_pos and G.jokers.cards[my_pos + 1] then + local sliced_card = G.jokers.cards[my_pos + 1] + sliced_card.getting_sliced = true + if sliced_card.config.center.rarity == "cry_exotic" then + check_for_unlock({ type = "what_have_you_done" }) + end + G.GAME.joker_buffer = G.GAME.joker_buffer - 1 + G.E_MANAGER:add_event(Event({ + func = function() + G.GAME.joker_buffer = 0 + card:juice_up(0.8, 0.8) + sliced_card:start_dissolve({ HEX("57ecab") }, nil, 1.6) + play_sound("slice1", 0.96 + math.random() * 0.08) + return true + end, + })) + card_eval_status_text(card, "extra", nil, nil, nil, { + message = localize({ + type = "variable", + key = "a_candy", + vars = { 1 }, + }), + colour = G.C.RARITY["cry_candy"], + no_juice = true, + }) + local card = create_card("Joker", G.jokers, nil, "cry_candy", nil, nil, nil, "cry_candy_dagger") + card:add_to_deck() + G.jokers:emplace(card) + end end, } local candy_cane = { @@ -1216,9 +1488,15 @@ local candy_cane = { order = 139, atlas = "atlasspooky", blueprint_compat = true, + demicoloncompat = true, pools = { ["Food"] = true }, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.rounds, center.ability.extra.dollars } } + return { + vars = { + number_format(center.ability.extra.rounds), + number_format(center.ability.extra.dollars), + }, + } end, calculate = function(self, card, context) if context.individual and context.cardarea == G.play then @@ -1234,7 +1512,7 @@ local candy_cane = { end, })) else - ease_dollars(card.ability.extra.dollars) + ease_dollars(lenient_bignum(card.ability.extra.dollars)) end end if @@ -1244,8 +1522,8 @@ local candy_cane = { and not context.repetition and not context.retrigger_joker then - card.ability.extra.rounds = card.ability.extra.rounds - 1 - if card.ability.extra.rounds > 0 then + card.ability.extra.rounds = lenient_bignum(to_big(card.ability.extra.rounds) - 1) + if to_big(card.ability.extra.rounds) > to_big(0) then return { message = { localize("cry_minus_round") }, colour = G.C.FILTER, @@ -1273,7 +1551,43 @@ local candy_cane = { end, })) return { - message = localize("k_extinct_ex"), + message = localize("k_eaten_ex"), + colour = G.C.FILTER, + } + end + end + if context.forcetrigger then + ease_dollars(lenient_bignum(card.ability.extra.dollars)) + card.ability.extra.rounds = lenient_bignum(to_big(card.ability.extra.rounds) - 1) + if to_big(card.ability.extra.rounds) > to_big(0) then + return { + message = { localize("cry_minus_round") }, + colour = G.C.FILTER, + } + else + G.E_MANAGER:add_event(Event({ + func = function() + play_sound("tarot1") + card.T.r = -0.2 + card:juice_up(0.3, 0.4) + card.states.drag.is = true + card.children.center.pinch.x = true + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.3, + blockable = false, + func = function() + G.jokers:remove_card(card) + card:remove() + card = nil + return true + end, + })) + return true + end, + })) + return { + message = localize("k_eaten_ex"), colour = G.C.FILTER, } end @@ -1298,12 +1612,12 @@ local candy_buttons = { blueprint_compat = true, pools = { ["Food"] = true }, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.rerolls } } + return { vars = { number_format(center.ability.extra.rerolls) } } end, calculate = function(self, card, context) if context.reroll_shop and not context.blueprint then - card.ability.extra.rerolls = card.ability.extra.rerolls - 1 - if card.ability.extra.rerolls <= 0 then + card.ability.extra.rerolls = lenient_bignum(to_big(card.ability.extra.rerolls) - 1) + if to_big(card.ability.extra.rerolls) <= to_big(0) then G.E_MANAGER:add_event(Event({ func = function() play_sound("tarot1") @@ -1326,7 +1640,7 @@ local candy_buttons = { end, })) return { - message = localize("k_extinct_ex"), + message = localize("k_eaten_ex"), colour = G.C.FILTER, } end @@ -1334,7 +1648,10 @@ local candy_buttons = { end end, add_to_deck = function(self, card, from_debuff) + -- The find_joker check in calculate_reroll_cost doesn't work if this is the only copy when added to deck (Too early) + G.GAME.reroll_limit_buffer = 1 calculate_reroll_cost(true) + G.GAME.reroll_limit_buffer = nil end, remove_from_deck = function(self, card, from_debuff) calculate_reroll_cost(true) @@ -1354,6 +1671,7 @@ local jawbreaker = { order = 141, atlas = "atlasspooky", blueprint_compat = false, + demicoloncompat = true, pools = { ["Food"] = true }, calculate = function(self, card, context) if @@ -1367,23 +1685,13 @@ local jawbreaker = { for i = 1, #G.jokers.cards do if G.jokers.cards[i] == card then if i > 1 then - if - not Card.no(G.jokers.cards[i - 1], "immune_to_chemach", true) - and not Card.no(G.jokers.cards[i - 1], "immutable", true) - then - Cryptid.with_deck_effects(G.jokers.cards[i - 1], function(card) - Cryptid.misprintize(card, { min = 2, max = 2 }, nil, true) - end) + if not Card.no(G.jokers.cards[i - 1], "immutable", true) then + Cryptid.manipulate(G.jokers.cards[i - 1], { value = 2 }) end end if i < #G.jokers.cards then - if - not Card.no(G.jokers.cards[i + 1], "immune_to_chemach", true) - and not Card.no(G.jokers.cards[i + 1], "immutable", true) - then - Cryptid.with_deck_effects(G.jokers.cards[i + 1], function(card) - Cryptid.misprintize(card, { min = 2, max = 2 }, nil, true) - end) + if not Card.no(G.jokers.cards[i + 1], "immutable", true) then + Cryptid.manipulate(G.jokers.cards[i + 1], { value = 2 }) end end end @@ -1410,10 +1718,26 @@ local jawbreaker = { end, })) return { - message = localize("k_extinct_ex"), + message = localize("k_eaten_ex"), colour = G.C.FILTER, } end + if context.forcetrigger then + for i = 1, #G.jokers.cards do + if G.jokers.cards[i] == card then + if i > 1 then + if not Card.no(G.jokers.cards[i - 1], "immutable", true) then + Cryptid.manipulate(G.jokers.cards[i - 1], { value = 2 }) + end + end + if i < #G.jokers.cards then + if not Card.no(G.jokers.cards[i + 1], "immutable", true) then + Cryptid.manipulate(G.jokers.cards[i + 1], { value = 2 }) + end + end + end + end + end end, add_to_deck = function(self, card, from_debuff) calculate_reroll_cost(true) @@ -1438,16 +1762,20 @@ local mellowcreme = { config = { extra = { sell_mult = 4 } }, pools = { ["Food"] = true }, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.sell_mult } } + return { vars = { number_format(center.ability.extra.sell_mult) } } end, blueprint_compat = true, + eternal_compat = false, + demicoloncompat = true, calculate = function(self, card, context) - if context.selling_self then + if context.selling_self or context.forcetrigger then for k, v in ipairs(G.consumeables.cards) do if v.set_cost then - v.ability.extra_value = (v.ability.extra_value or 0) - + (math.max(1, math.floor(v.cost / 2)) + (v.ability.extra_value or 0)) - * (card.ability.extra.sell_mult - 1) + v.ability.extra_value = lenient_bignum( + (to_big(v.ability.extra_value) or 0) + + (math.max(1, math.floor(to_big(v.cost) / 2)) + (v.ability.extra_value or 0)) + * (to_big(card.ability.extra.sell_mult) - 1) + ) v:set_cost() end end @@ -1473,7 +1801,7 @@ local brittle = { info_queue[#info_queue + 1] = G.P_CENTERS.m_stone info_queue[#info_queue + 1] = G.P_CENTERS.m_gold info_queue[#info_queue + 1] = G.P_CENTERS.m_steel - return { vars = { center.ability.extra.rounds } } + return { vars = { number_format(center.ability.extra.rounds) } } end, blueprint_compat = true, calculate = function(self, card, context) @@ -1482,10 +1810,11 @@ local brittle = { and context.before and not context.blueprint_card and not context.retrigger_joker + and context.scoring_hand then local _card = context.scoring_hand[#context.scoring_hand] - if not _card.brittled then - card.ability.extra.rounds = card.ability.extra.rounds - 1 + if _card and not _card.brittled then + card.ability.extra.rounds = lenient_bignum(to_big(card.ability.extra.rounds) - 1) local enhancement = pseudorandom_element({ "m_stone", "m_gold", "m_steel" }, pseudoseed("cry_brittle")) _card.brittled = true _card:set_ability(G.P_CENTERS[enhancement], nil, true) @@ -1496,7 +1825,7 @@ local brittle = { return true end, })) - if card.ability.extra.rounds > 0 then + if to_big(card.ability.extra.rounds) > to_big(0) then return nil, true else G.E_MANAGER:add_event(Event({ @@ -1521,7 +1850,7 @@ local brittle = { end, })) return { - message = localize("k_extinct_ex"), + message = localize("k_eaten_ex"), colour = G.C.FILTER, } end @@ -1539,7 +1868,7 @@ local monopoly_money = { key = "monopoly_money", name = "cry-Monopoly", pos = { x = 4, y = 1 }, - config = { extra = { fail_rate = 4 } }, + config = { extra = { odds = 4 } }, order = 144, rarity = "cry_cursed", cost = 0, @@ -1547,6 +1876,7 @@ local monopoly_money = { blueprint_compat = false, eternal_compat = false, perishable_compat = false, + demicoloncompat = true, no_dbl = true, calculate = function(self, card, context) if @@ -1556,9 +1886,12 @@ local monopoly_money = { and not (context.card == card) then if - pseudorandom(pseudoseed("cry_monopoly")) - < cry_prob(card.ability.cry_prob, card.ability.extra.fail_rate, card.ability.cry_rigged) - / card.ability.extra.fail_rate + SMODS.pseudorandom_probability( + card, + "cry_monopoly", + 1, + card and card.ability.extra.odds or self.config.extra.odds + ) then G.E_MANAGER:add_event(Event({ func = function() @@ -1576,18 +1909,28 @@ local monopoly_money = { if context.selling_self and not context.blueprint_card and not context.retrigger_joker then G.E_MANAGER:add_event(Event({ func = function() - ease_dollars(math.floor(-0.5 * G.GAME.dollars)) + ease_dollars(math.floor(0.5 * G.GAME.dollars - G.GAME.dollars)) return true end, })) return nil, true end + if context.forcetrigger then + G.E_MANAGER:add_event(Event({ + func = function() + ease_dollars(math.floor(0.5 * G.GAME.dollars - G.GAME.dollars)) + return true + end, + })) + end end, loc_vars = function(self, info_queue, card) + local num, denom = + SMODS.get_probability_vars(card, 1, card and card.ability.extra.odds or self.config.extra.odds) return { vars = { - cry_prob(card.ability.cry_prob, card.ability.extra.fail_rate, card.ability.cry_rigged), - card.ability.extra.fail_rate, + num, + denom, }, } end, @@ -1603,7 +1946,13 @@ local candy_sticks = { name = "cry-Candy-Sticks", pos = { x = 5, y = 2 }, order = 145, - config = { extra = { boss = {}, hands = 1, clockscore = 0 } }, + config = { + extra = { hands = 1 }, + immutable = { + boss = {}, + clockscore = 0, + }, + }, rarity = "cry_candy", cost = 3, atlas = "atlasspooky", @@ -1612,9 +1961,9 @@ local candy_sticks = { no_dbl = true, calculate = function(self, card, context) if context.setting_blind and not self.getting_sliced and not context.blueprint and context.blind.boss then - card.ability.extra.boss = G.GAME.blind:save() + card.ability.immutable.boss = G.GAME.blind:save() if G.GAME.blind.name == "The Clock" then - card.ability.extra.clockscore = G.GAME.blind.chips + card.ability.immutable.clockscore = G.GAME.blind.chips end G.E_MANAGER:add_event(Event({ func = function() @@ -1632,15 +1981,15 @@ local candy_sticks = { })) end if context.after and G.GAME.blind:get_type() == "Boss" then - card.ability.extra.hands = card.ability.extra.hands - 1 + card.ability.extra.hands = lenient_bignum(to_big(card.ability.extra.hands) - 1) end if ( (context.selling_self and G.GAME.blind and G.GAME.blind:get_type() == "Boss") - or card.ability.extra.hands <= 0 + or to_big(card.ability.extra.hands) <= to_big(0) ) and G.GAME.blind.disabled then - G.GAME.blind:load(card.ability.extra.boss) + G.GAME.blind:load(card.ability.immutable.boss) if not context.selling_self then G.E_MANAGER:add_event(Event({ func = function() @@ -1663,6 +2012,10 @@ local candy_sticks = { return true end, })) + return { + message = localize("k_eaten_ex"), + colour = G.C.FILTER, + } end end if context.end_of_round and G.GAME.blind:get_type() == "Boss" then @@ -1690,7 +2043,7 @@ local candy_sticks = { end end, loc_vars = function(self, info_queue, center) - return { vars = { center.ability.extra.hands } } + return { vars = { number_format(center.ability.extra.hands) } } end, cry_credits = { idea = { @@ -1721,14 +2074,16 @@ local wonka_bar = { rarity = "cry_candy", cost = 10, eternal_compat = false, + demicoloncompat = true, + blueprint_compat = true, atlas = "atlasspooky", loc_vars = function(self, info_queue, center) return { vars = { center.ability.extra } } end, calculate = function(self, card, context) - if context.selling_self and not context.blueprint then - card.ability.extra = math.floor(card.ability.extra) - G.hand.config.highlighted_limit = G.hand.config.highlighted_limit + card.ability.extra + if context.selling_self or context.forcetrigger then + SMODS.change_play_limit(math.floor(card.ability.extra)) + SMODS.change_discard_limit(math.floor(card.ability.extra)) end end, cry_credits = { @@ -1743,6 +2098,94 @@ local wonka_bar = { }, }, } + +-- Buttercup +-- Store items in shop +local buttercup = { + object_type = "Joker", + key = "buttercup", + name = "cry-Buttercup", + pos = { x = 2, y = 3 }, + config = { extra = { slots = 1 } }, + rarity = "cry_candy", + cost = 3, + atlas = "atlasspooky", + blueprint_compat = false, + eternal_compat = false, + demicoloncompat = true, + no_dbl = true, + order = 147, + cry_credits = { + idea = { "Squiddy" }, + art = { "lolxddj" }, + code = { "#Guigui" }, + }, + loc_vars = function(self, info_queue, center) + return { + vars = { center.ability.extra.slots }, + } + end, + add_to_deck = function(self, card, from_debuff) + if card.cry_storage == nil then + local storage_area_config = { + type = "play", + card_w = G.CARD_W, + } + card.cry_storage = CardArea(card.T.x, 2, 1, 1, storage_area_config) + end + if G.GAME.next_shop_cards == nil then + G.GAME.next_shop_cards = {} + end + end, + calculate = function(self, card, context) + if card.cry_storage == nil then + local storage_area_config = { + type = "play", + card_w = G.CARD_W, + } + card.cry_storage = CardArea(card.T.x, 2, 1, 1, storage_area_config) + end + if context.selling_self and not context.blueprint and not context.forcetrigger then + if #card.cry_storage.cards > 0 then + for i, jok in ipairs(card.cry_storage.cards) do + jok.T.w = jok.T.orig.w + jok.T.h = jok.T.orig.h + G.GAME.next_shop_cards[#G.GAME.next_shop_cards + 1] = jok:save() + jok:remove() + end + end + card.cry_storage:remove() + end + if context.forcetrigger and #card.cry_storage.cards > 0 then + for i, jok in ipairs(card.cry_storage.cards) do + -- jok.T.w = jok.T.orig.w + -- jok.T.h = jok.T.orig.h + G.GAME.next_shop_cards[#G.GAME.next_shop_cards + 1] = jok:save() + end + end + end, + init = function() + local start_dissolveref = Card.start_dissolve + function Card:start_dissolve(...) + start_dissolveref(self, card) + if self.config.center.key == "j_cry_buttercup" then + G.E_MANAGER:add_event(Event({ + func = function() + for i, v in pairs((self.cry_storage or {}).cards or {}) do + v.states.visible = false + v:start_dissolve() + end + if self.cry_storage then + self.cry_storage:remove() + end + return true + end, + })) + end + end + end, +} + items = { cotton_candy, wrapped, @@ -1764,8 +2207,9 @@ items = { trick_or_treat, candy_basket, blacklist, + rotten_egg, --ghost, - possessed, + --possessed, spookydeck, candy_dagger, candy_cane, @@ -1776,6 +2220,7 @@ items = { monopoly_money, candy_sticks, wonka_bar, + buttercup, } return { name = "Spooky", diff --git a/Cryptid/items/stake.lua b/Cryptid/items/stake.lua index a92f224..aaf5552 100644 --- a/Cryptid/items/stake.lua +++ b/Cryptid/items/stake.lua @@ -118,7 +118,7 @@ local amber = { atlas = "stake", applied_stakes = { "cry_diamond" }, modifiers = function() - G.GAME.modifiers.cry_booster_packs = 1 + G.GAME.modifiers.extra_boosters = -1 end, shiny = true, order = 17, @@ -352,10 +352,7 @@ return { -- Disallow use of Debuffed Perishable consumables local cuc = Card.can_use_consumeable function Card:can_use_consumeable(any_state, skip_check) - if self.ability.perish_tally == nil then - self.ability.perish_tally = G.GAME.perishable_rounds or 5 - end - if self.ability.perishable and self.ability.perish_tally <= 0 then + if self.debuff then return false end return cuc(self, any_state, skip_check) @@ -366,7 +363,7 @@ return { local temp_hand = {} local hasHand = false for k, v in ipairs(G.hand.cards) do - if not v.ability.eternal then + if not SMODS.is_eternal(v) then temp_hand[#temp_hand + 1] = v hasHand = true end diff --git a/Cryptid/items/tag.lua b/Cryptid/items/tag.lua index 1b361d6..750a617 100644 --- a/Cryptid/items/tag.lua +++ b/Cryptid/items/tag.lua @@ -225,6 +225,9 @@ local empoweredPack = { G.consumeables:emplace(ccard) end, }, + in_pool = function() + return false + end, } local empowered = { cry_credits = { @@ -325,11 +328,11 @@ local gambler = { key = "gambler", loc_vars = function(self, info_queue) info_queue[#info_queue + 1] = { set = "Tag", key = "tag_cry_empowered" } - return { vars = { G.GAME.probabilities.normal or 1, self.config.odds } } + return { vars = { SMODS.get_probability_vars(self, 1, self.config.odds, "Gambler Tag") } } end, apply = function(self, tag, context) if context.type == "new_blind_choice" then - if pseudorandom("cry_gambler_tag") < G.GAME.probabilities.normal / tag.config.odds then + if SMODS.pseudorandom_probability(card, "cry_gambler_tag", 1, tag.config.odds, "Gambler Tag") then local lock = tag.ID G.CONTROLLER.locks[lock] = true tag:yep("+", G.C.SECONDARY_SET.Spectral, function() @@ -1036,22 +1039,14 @@ local banana = { set = "Joker", key = G.P_CENTER_POOLS["Joker"][61].key, }) - info_queue[#info_queue + 1] = { - set = "Joker", - key = "j_cavendish", - specific_vars = { 3, G.GAME.probabilities.normal or 1, 1000 }, - } + info_queue[#info_queue + 1] = G.P_CENTERS.j_cavendish else banana = localize({ type = "name_text", set = "Joker", key = G.P_CENTER_POOLS["Joker"][38].key, }) - info_queue[#info_queue + 1] = { - set = "Joker", - key = "j_gros_michel", - specific_vars = { 15, G.GAME.probabilities.normal or 1, 6 }, - } + info_queue[#info_queue + 1] = G.P_CENTERS.j_gros_michel end return { vars = { banana } } end, @@ -1328,7 +1323,7 @@ local better_voucher = { G.P_CENTERS[voucher_key], { bypass_discovery_center = true, bypass_discovery_ui = true } ) - Cryptid.misprintize(card) + Cryptid.manipulate(card) create_shop_card_ui(card, "Voucher", G.shop_vouchers) card:start_materialize() if G.GAME.modifiers.cry_force_edition and not G.GAME.modifiers.cry_force_random_edition then @@ -1404,7 +1399,7 @@ local booster = { local lock = tag.ID G.CONTROLLER.locks[lock] = true tag:yep("+", G.C.BLUE, function() - G.GAME.boostertag = (G.GAME.boostertag or 0) + 1 + G.GAME.boostertag = G.GAME.boostertag + 1 G.CONTROLLER.locks[lock] = nil return true end) @@ -1413,6 +1408,244 @@ local booster = { end end, } + +local clone = { + cry_credits = { + idea = { + "Squiddy", + }, + art = { + "lord.ruby", + }, + code = { + "lord.ruby", + }, + }, + object_type = "Tag", + dependencies = { + items = { + "set_cry_tag", + }, + }, + name = "cry-Clone Tag", + order = 29, + atlas = "tag_cry", + pos = { x = 6, y = 3 }, + config = { type = "item_bought", cost_fac = 1.5 }, + key = "clone", + loc_vars = function(self, info_queue) + return { vars = { self.config.cost_fac } } + end, + min_ante = 4, + apply = function(self, tag, context) + if context.type == "item_bought" then + local lock = tag.ID + G.CONTROLLER.locks[lock] = true + tag:yep("+", G.C.BLUE, function() + local copy = copy_card(context.card) + copy:add_to_deck() + if context.card.area then + context.card.area:emplace(copy) + else + G.consumeables:emplace(copy) + end + G.E_MANAGER:add_event(Event({ + func = function() + for i, v in pairs(G.I.CARD) do + if v.set_cost then + v:set_cost() + end + end + return true + end, + })) + G.CONTROLLER.locks[lock] = nil + return true + end) + tag.triggered = true + return true + end + end, + init = function() + local buy_ref = G.FUNCS.buy_from_shop + G.FUNCS.buy_from_shop = function(e) + local r = buy_ref(e) + if r ~= false then + for i = 1, #G.GAME.tags do + G.GAME.tags[i]:apply_to_run({ type = "item_bought", card = e.config.ref_table }) + end + end + return r + end + end, +} + +local lens = { + cry_credits = { + idea = { + "Squiddy", + }, + art = { + "lord.ruby", + }, + code = { + "lord.ruby", + }, + }, + object_type = "Tag", + dependencies = { + items = { + "set_cry_tag", + }, + }, + name = "cry-Lens Tag", + order = 30, + atlas = "tag_cry", + pos = { x = 7, y = 3 }, + config = { type = "immediate", negatives = 2 }, + key = "lens", + loc_vars = function(self, info_queue) + info_queue[#info_queue + 1] = G.P_CENTERS.e_negative + return { vars = { self.config.negatives } } + end, + min_ante = 4, + apply = function(self, tag, context) + if context.type == "immediate" then + local c = {} + for i, v in pairs(G.consumeables.cards) do + if not v.edition or not v.edition.negative then + if not v.will_be_editioned then + c[#c + 1] = v + end + end + end + if #c > 0 then + local lock = tag.ID + G.CONTROLLER.locks[lock] = true + local card = pseudorandom_element(c, pseudoseed("cry_lens_tag")) + card.will_be_editioned = true + local card2 = pseudorandom_element(c, pseudoseed("cry_lens_tag")) + if card2 then + card2.will_be_editioned = true + end + tag:yep("+", G.C.BLUE, function() + card:set_edition("e_negative") + G.CONTROLLER.locks[lock] = nil + card.will_be_editioned = nil + if card2 then + card2:set_edition("e_negative") + card2.will_be_editioned = nil + end + return true + end) + else + tag:nope() + end + tag.triggered = true + return true + end + end, +} + +local palette_cleanser = { + cry_credits = { + idea = { + "Squiddy", + }, + art = { + "lord.ruby", + }, + code = { + "lord.ruby", + }, + }, + object_type = "Tag", + dependencies = { + items = { + "set_cry_tag", + }, + }, + name = "cry-Palette Cleanser Tag", + order = 30, + atlas = "tag_cry", + pos = { x = 0, y = 4 }, + config = { type = "immediate" }, + key = "palette_cleanser", + loc_vars = function(self, info_queue) + return { vars = {} } + end, + min_ante = 4, + apply = function(self, tag, context) + if context.type == "immediate" then + local c = {} + for i, v in pairs(G.jokers.cards) do + if v:has_stickers() then + if not v.will_be_cleansed then + c[#c + 1] = v + end + end + end + for i, v in pairs(G.deck.cards) do + if v:has_stickers() then + if not v.will_be_cleansed then + c[#c + 1] = v + end + end + end + for i, v in pairs(G.hand.cards) do + if v:has_stickers() then + if not v.will_be_cleansed then + c[#c + 1] = v + end + end + end + if #c > 0 then + local lock = tag.ID + G.CONTROLLER.locks[lock] = true + local card = pseudorandom_element(c, pseudoseed("cry_palette_cleanser_tag")) + card.will_be_cleansed = true + tag:yep("+", G.C.BLUE, function() + card:remove_random_sticker("cry_palette_cleanser_sticker") + G.CONTROLLER.locks[lock] = nil + card.will_be_cleansed = nil + return true + end) + else + tag:nope() + end + tag.triggered = true + return true + end + end, + in_pool = function() + local c = {} + if G.jokers then + for i, v in pairs(G.jokers.cards) do + if not v:has_stickers() then + if not v.will_be_cleansed then + c[#c + 1] = v + end + end + end + for i, v in pairs(G.deck.cards) do + if not v:has_stickers() then + if not v.will_be_cleansed then + c[#c + 1] = v + end + end + end + for i, v in pairs(G.hand.cards) do + if not v:has_stickers() then + if not v.will_be_cleansed then + c[#c + 1] = v + end + end + end + end + return #c > 0 + end, +} + local tagitems = { cat, empoweredPack, @@ -1436,6 +1669,9 @@ local tagitems = { blur_tag, astral_tag, loss, + clone, + lens, + palette_cleanser, m_tag, double_m_tag, } diff --git a/Cryptid/items/test.lua b/Cryptid/items/test.lua index 2568f7d..44a238a 100644 --- a/Cryptid/items/test.lua +++ b/Cryptid/items/test.lua @@ -129,18 +129,24 @@ local test3 = { }, }, calculate = function(self, card, context) - if context.end_of_round and not context.individual and not context.repetition then - Cryptid.suit_level_up(context.blueprint_card or card, nil, 1, { - "High Card", - "Pair", - "Two Pair", - "Three of a Kind", - "Straight", - "Flush", - "Full House", - "Four of a Kind", - "Straight Flush", - }, true) + if context.using_consumeable then + if context.consumeable.ability.set == "Tarot" then + Cryptid.suit_level_up( + context.blueprint_card or card, + nil, + 1, + Cryptid.table_merge({ "Three of a Kind" }, { "Three of a Kind" }, { "Full House" }, { "Pair" }), + true + ) + else + Cryptid.suit_level_up( + context.blueprint_card or card, + nil, + 1, + Cryptid.table_merge({ "Three of a Kind" }, { "Full House" }, { "Pair" }, { "Three of a Kind" }), + true + ) + end elseif context.pre_discard and not context.hook then local text, loc_disp_text, poker_hands, scoring_hand, disp_text = G.FUNCS.get_poker_hand_info(G.hand.highlighted) diff --git a/Cryptid/items/voucher.lua b/Cryptid/items/voucher.lua index 4387d84..366fc7b 100644 --- a/Cryptid/items/voucher.lua +++ b/Cryptid/items/voucher.lua @@ -5,7 +5,9 @@ local voucher_atlas = { px = 71, py = 95, } -local copies = { --Double tags become Triple Tags and are 2X as common + +-- Normal Vouchers (T1/T2) +local copies = { -- DTag T1; Double tags become Triple Tags and are 2X as common cry_credits = { idea = { "Catman", @@ -27,7 +29,7 @@ local copies = { --Double tags become Triple Tags and are 2X as common }, key = "copies", atlas = "atlasvoucher", - order = 1, + order = 20001, pos = { x = 1, y = 1 }, loc_vars = function(self, info_queue) info_queue[#info_queue + 1] = { set = "Tag", key = "tag_double" } @@ -56,7 +58,7 @@ local copies = { --Double tags become Triple Tags and are 2X as common end end, } -local tag_printer = { --Double tags become Quadruple Tags and are 3X as common +local tag_printer = { --DTag T2; Double tags become Quadruple Tags and are 3X as common cry_credits = { idea = { "Catman", @@ -78,7 +80,7 @@ local tag_printer = { --Double tags become Quadruple Tags and are 3X as common }, }, key = "tag_printer", - order = 2, + order = 20002, atlas = "atlasvoucher", pos = { x = 1, y = 2 }, loc_vars = function(self, info_queue) @@ -88,144 +90,7 @@ local tag_printer = { --Double tags become Quadruple Tags and are 3X as common end, requires = { "v_cry_copies" }, } -local clone_machine = { --Double tags become Quintuple Tags and are 4X as common - cry_credits = { - idea = { - "Catman", - "Mystic Misclick", - }, - art = { - "Linus Goof Balls", - }, - code = { - "Math", - }, - }, - object_type = "Voucher", - dependencies = { - items = { - "set_cry_voucher", - "set_cry_tag", - "set_cry_tier3", - "v_cry_tag_printer", - }, - }, - key = "clone_machine", - atlas = "atlasvoucher", - order = 91, - pos = { x = 1, y = 3 }, - pools = { ["Tier3"] = true }, - loc_vars = function(self, info_queue) - info_queue[#info_queue + 1] = { set = "Tag", key = "tag_double" } - info_queue[#info_queue + 1] = { set = "Tag", key = "tag_cry_quintuple", specific_vars = { 4 } } - return { vars = {} } - end, - requires = { "v_cry_tag_printer" }, -} -local command_prompt = { --Code cards can appear in the shop - cry_credits = { - idea = { - "HexaCryonic", - }, - art = { - "HexaCryonic", - }, - code = { - "Mathguy", - }, - }, - object_type = "Voucher", - dependencies = { - items = { - "set_cry_voucher", - "set_cry_code", - }, - }, - key = "command_prompt", - atlas = "atlasvoucher", - order = 3, - pos = { x = 0, y = 1 }, - loc_vars = function(self, info_queue) - return { vars = {} } - end, - redeem = function(self) - G.E_MANAGER:add_event(Event({ - func = function() - G.GAME.code_rate = (G.GAME.code_rate or 0) + 4 - return true - end, - })) - end, - unredeem = function(self) - G.E_MANAGER:add_event(Event({ - func = function() - G.GAME.code_rate = math.max(0, G.GAME.code_rate - 4) - return true - end, - })) - end, -} -local satellite_uplink = { --Code cards may appear in any of the Celestial Packs - cry_credits = { - idea = { - "HexaCryonic", - }, - art = { - "HexaCryonic", - }, - code = { - "Mathguy", - }, - }, - object_type = "Voucher", - dependencies = { - items = { - "set_cry_voucher", - "set_cry_code", - "v_cry_command_prompt", - }, - }, - key = "satellite_uplink", - atlas = "atlasvoucher", - order = 4, - pos = { x = 0, y = 2 }, - loc_vars = function(self, info_queue) - return { vars = {} } - end, - requires = { "v_cry_command_prompt" }, -} -local quantum_computing = { --Code cards can spawn with Negative addition - cry_credits = { - idea = { - "HexaCryonic", - }, - art = { - "HexaCryonic", - }, - code = { - "Mathguy", - }, - }, - object_type = "Voucher", - dependencies = { - items = { - "set_cry_voucher", - "set_cry_tier3", - "set_cry_code", - "v_cry_satellite_uplink", - }, - }, - key = "quantum_computing", - order = 92, - atlas = "atlasvoucher", - pos = { x = 0, y = 3 }, - pools = { ["Tier3"] = true }, - loc_vars = function(self, info_queue) - return { vars = {} } - end, - requires = { "v_cry_satellite_uplink" }, -} -local pairing = { --Retrigger all M Jokers if played hand is a Pair +local pairing = { -- M T1; Retrigger all M Jokers if played hand is a Pair object_type = "Voucher", dependencies = { items = { @@ -235,7 +100,7 @@ local pairing = { --Retrigger all M Jokers if played hand is a Pair }, key = "pairing", atlas = "atlasvoucher", - order = 5, + order = 20003, pos = { x = 4, y = 5 }, cry_credits = { art = { @@ -257,7 +122,7 @@ local pairing = { --Retrigger all M Jokers if played hand is a Pair return false end, } -local repair_man = { --Retrigger all M Jokers if played hand contains a pair +local repair_man = { -- M T2; Retrigger all M Jokers if played hand contains a pair object_type = "Voucher", dependencies = { items = { @@ -268,7 +133,7 @@ local repair_man = { --Retrigger all M Jokers if played hand contains a pair }, key = "repair_man", atlas = "atlasvoucher", - order = 6, + order = 20004, pos = { x = 5, y = 5 }, requires = { "v_cry_pairing" }, cry_credits = { @@ -291,43 +156,7 @@ local repair_man = { --Retrigger all M Jokers if played hand contains a pair return false end, } -local pairamount_plus = { --Retrigger all M Jokers once for every pair contained in played hand - object_type = "Voucher", - dependencies = { - items = { - "set_cry_voucher", - "set_cry_m", - "set_cry_tier3", - "v_cry_repair_man", - }, - }, - key = "pairamount_plus", - atlas = "atlasvoucher", - order = 93, - pos = { x = 6, y = 5 }, - requires = { "v_cry_repair_man" }, - pools = { ["Tier3"] = true }, - cry_credits = { - art = { - "lolxddj", - }, - code = { - "Math", - }, - jolly = { - "Jolly Open Winner", - "Xaltios", - }, - }, - in_pool = function(self) - local mcheck = Cryptid.get_m_jokers() - if mcheck > 0 then - return true - end - return false - end, -} -local double_vision = { --Double-Sided cards appear 4x more frequently +local double_vision = { -- DSide T1; Double-Sided cards appear 4x more frequently object_type = "Voucher", dependencies = { items = { @@ -336,7 +165,7 @@ local double_vision = { --Double-Sided cards appear 4x more frequently }, }, key = "double_vision", - order = 7, + order = 20005, atlas = "atlasvoucher", pos = { x = 4, y = 3 }, loc_vars = function(self, info_queue) @@ -355,7 +184,7 @@ local double_vision = { --Double-Sided cards appear 4x more frequently }, }, } -local double_slit = { --Meld can appear in the shop and Arcana Packs +local double_slit = { -- DSide T2; Meld can appear in the shop and Arcana Packs object_type = "Voucher", dependencies = { items = { @@ -367,7 +196,7 @@ local double_slit = { --Meld can appear in the shop and Arcana Packs }, key = "double_slit", atlas = "atlasvoucher", - order = 8, + order = 20006, pos = { x = 3, y = 4 }, requires = { "v_cry_double_vision" }, loc_vars = function(self, info_queue) @@ -386,39 +215,159 @@ local double_slit = { --Meld can appear in the shop and Arcana Packs }, }, } -local double_down = { --After every round, X1.5 to all values on the back of Double-Sided Cards +local stickyhand = { -- CSL T1; +1 card selection limit + cry_credits = { + idea = { + "HexaCryonic", + }, + art = { + "HexaCryonic", + }, + code = { + "HexaCryonic", + }, + }, object_type = "Voucher", dependencies = { items = { "set_cry_voucher", - "set_cry_tier3", - "e_cry_double_sided", - "v_cry_double_slit", }, }, - key = "double_down", + key = "stickyhand", + config = { extra = 1 }, atlas = "atlasvoucher", - order = 94, - pos = { x = 4, y = 4 }, - requires = { "v_cry_double_slit" }, - pools = { ["Tier3"] = true }, - loc_vars = function(self, info_queue) - info_queue[#info_queue + 1] = G.P_CENTERS.e_cry_double_sided + order = 20007, + pos = { x = 0, y = 5 }, + loc_vars = function(self, info_queue, card) + return { vars = { (card and card.ability.extra or self.config.extra) } } end, + redeem = function(self, card) + SMODS.change_play_limit(card.ability.extra or self.config.extra) + SMODS.change_discard_limit(card.ability.extra or self.config.extra) + end, + unredeem = function(self, card) + SMODS.change_play_limit(-(card.ability.extra or self.config.extra)) + SMODS.change_discard_limit(-(card.ability.extra or self.config.extra)) + if not G.GAME.before_play_buffer then + G.hand:unhighlight_all() + end + end, +} +local grapplinghook = { -- CSL T2; +2 card selection limit cry_credits = { + idea = { + "HexaCryonic", + }, art = { - "Linus Goof Balls", + "HexaCryonic", }, code = { - "Math", - }, - jolly = { - "Jolly Open Winner", - "Axolotolus", + "HexaCryonic", }, }, + object_type = "Voucher", + dependencies = { + items = { + "set_cry_voucher", + "v_cry_stickyhand", + }, + }, + key = "grapplinghook", + config = { extra = 2 }, + atlas = "atlasvoucher", + order = 20008, + pos = { x = 1, y = 5 }, + requires = { "v_cry_stickyhand" }, + loc_vars = function(self, info_queue, card) + return { vars = { (card and card.ability.extra or self.config.extra) } } + end, + redeem = function(self, card) + SMODS.change_play_limit(card.ability.extra or self.config.extra) + SMODS.change_discard_limit(card.ability.extra or self.config.extra) + end, + unredeem = function(self, card) + SMODS.change_play_limit(-(card.ability.extra or self.config.extra)) + SMODS.change_discard_limit(-(card.ability.extra or self.config.extra)) + if not G.GAME.before_play_buffer then + G.hand:unhighlight_all() + end + end, } -local overstock_multi = { --+1 card slot[s], +1 booster pack slot[s] and +1 voucher slot[s] available in the shop +local command_prompt = { -- Code T1; Code cards can appear in the shop + cry_credits = { + idea = { + "HexaCryonic", + }, + art = { + "HexaCryonic", + }, + code = { + "Mathguy", + }, + }, + object_type = "Voucher", + dependencies = { + items = { + "set_cry_voucher", + "set_cry_code", + }, + }, + key = "command_prompt", + atlas = "atlasvoucher", + order = 20031, + pos = { x = 0, y = 1 }, + loc_vars = function(self, info_queue) + return { vars = {} } + end, + redeem = function(self) + G.E_MANAGER:add_event(Event({ + func = function() + G.GAME.code_rate = (G.GAME.code_rate or 0) + 4 + return true + end, + })) + end, + unredeem = function(self) + G.E_MANAGER:add_event(Event({ + func = function() + G.GAME.code_rate = math.max(0, G.GAME.code_rate - 4) + return true + end, + })) + end, +} +local satellite_uplink = { -- Code T2; Code cards may appear in any of the Celestial Packs + cry_credits = { + idea = { + "HexaCryonic", + }, + art = { + "HexaCryonic", + }, + code = { + "Mathguy", + }, + }, + object_type = "Voucher", + dependencies = { + items = { + "set_cry_voucher", + "set_cry_code", + "v_cry_command_prompt", + }, + }, + key = "satellite_uplink", + atlas = "atlasvoucher", + order = 20032, + pos = { x = 0, y = 2 }, + loc_vars = function(self, info_queue) + return { vars = {} } + end, + requires = { "v_cry_command_prompt" }, +} + +-- Tier 3 Vouchers +local overstock_multi = { -- Overstock T3; +1 card slot, +1 booster pack slot and +1 voucher slot available in the shop cry_credits = { idea = { "Frix", @@ -439,7 +388,7 @@ local overstock_multi = { --+1 card slot[s], +1 booster pack slot[s] and +1 vouc key = "overstock_multi", config = { extra = 1 }, atlas = "atlasvoucher", - order = 75, + order = 32658, pos = { x = 4, y = 1 }, requires = { "v_overstock_plus" }, pools = { ["Tier3"] = true }, @@ -471,7 +420,7 @@ local overstock_multi = { --+1 card slot[s], +1 booster pack slot[s] and +1 vouc SMODS.change_voucher_limit(-mod) end, } -local massproduct = { --All cards and packs in the shop cost $1 +local massproduct = { -- Clearance Sale T3; All cards and packs in the shop cost $1 cry_credits = { idea = { "Frix", @@ -491,7 +440,7 @@ local massproduct = { --All cards and packs in the shop cost $1 }, key = "massproduct", atlas = "atlasvoucher", - order = 76, + order = 32659, pos = { x = 6, y = 4 }, requires = { "v_liquidation" }, pools = { ["Tier3"] = true }, @@ -523,7 +472,7 @@ local massproduct = { --All cards and packs in the shop cost $1 })) end, } -local curate = { --All cards appear with an Edition +local curate = { -- Hone T3; All cards appear with an Edition cry_credits = { idea = { "Frix", @@ -543,7 +492,7 @@ local curate = { --All cards appear with an Edition }, key = "curate", atlas = "atlasvoucher", - order = 77, + order = 32660, pos = { x = 6, y = 1 }, requires = { "v_glow_up" }, pools = { ["Tier3"] = true }, @@ -558,7 +507,7 @@ local curate = { --All cards appear with an Edition end end, } -local rerollexchange = { --All rerolls cost $2 +local rerollexchange = { -- Reroll Surplus T3; All rerolls cost $2 cry_credits = { idea = { "Project666", @@ -578,7 +527,7 @@ local rerollexchange = { --All rerolls cost $2 }, key = "rerollexchange", atlas = "atlasvoucher", - order = 78, + order = 32661, pos = { x = 6, y = 2 }, requires = { "v_reroll_glut" }, pools = { ["Tier3"] = true }, @@ -602,22 +551,35 @@ local rerollexchange = { --All rerolls cost $2 })) end, } ---Order 79 reserved for celestial storage (unimplemented) -local scope = { --Also unimplemented +local CBALLT3PLACEHOLDER = { -- RESERVED FOR CRYSTAL BALL T3 object_type = "Voucher", dependencies = { items = { "set_cry_tier3", }, }, - key = "scope", + key = "CBALLT3PLACEHOLDER", atlas = "atlasvoucher", - order = 80, + order = 32662, + -- pos = { x = 2, y = 0 }, + requires = { "v_omen_globe" }, + pools = { ["Tier3"] = true }, +} +local TSCOPET3PLACEHOLDER = { -- RESERVED FOR TELESCOPE T3 + object_type = "Voucher", + dependencies = { + items = { + "set_cry_tier3", + }, + }, + key = "TSCOPET3PLACEHOLDER", + atlas = "atlasvoucher", + order = 32663, pos = { x = 2, y = 0 }, requires = { "v_observatory" }, pools = { ["Tier3"] = true }, } -local dexterity = { --Permanently gain +2 hand[s] each round +local dexterity = { -- Grabber T3; Permanently gain +2 hands each round cry_credits = { idea = { "Frix", @@ -638,7 +600,7 @@ local dexterity = { --Permanently gain +2 hand[s] each round key = "dexterity", config = { extra = 2 }, atlas = "atlasvoucher", - order = 81, + order = 32664, pos = { x = 6, y = 3 }, requires = { "v_nacho_tong" }, pools = { ["Tier3"] = true }, @@ -654,7 +616,7 @@ local dexterity = { --Permanently gain +2 hand[s] each round ease_hands_played(-1 * (card and card.ability.extra or self.config.extra)) end, } -local threers = { --Permanently gain +2 discard[s] each round +local threers = { -- Wasteful T3; Permanently gain +2 discards each round cry_credits = { idea = { "Frix", @@ -675,7 +637,7 @@ local threers = { --Permanently gain +2 discard[s] each round key = "threers", config = { extra = 2 }, atlas = "atlasvoucher", - order = 82, + order = 32665, pos = { x = 5, y = 0 }, requires = { "v_recyclomancy" }, pools = { ["Tier3"] = true }, @@ -691,7 +653,7 @@ local threers = { --Permanently gain +2 discard[s] each round ease_discard(-1 * (card and card.ability.extra or self.config.extra)) end, } -local tacclimator = { --Tarot cards appear X6 more frequently in the shop All future Tarot cards are free +local tacclimator = { -- Tarot Merchant T3; Tarots are free, spawn rate controllable in run info cry_credits = { idea = { "Frix", @@ -713,7 +675,7 @@ local tacclimator = { --Tarot cards appear X6 more frequently in the shop All key = "tacclimator", config = { extra = 24 / 4, extra_disp = 6 }, atlas = "atlasvoucher", - order = 83, + order = 32666, pos = { x = 1, y = 4 }, requires = { "v_tarot_tycoon" }, pools = { ["Tier3"] = true }, @@ -737,7 +699,7 @@ local tacclimator = { --Tarot cards appear X6 more frequently in the shop All })) end, } -local pacclimator = { --Planet cards appear X6 more frequently in the shop All future Planet cards are free +local pacclimator = { -- Planet Merchant T3; Planets are free, spawn rate controllable in run info cry_credits = { idea = { "Frix", @@ -759,7 +721,7 @@ local pacclimator = { --Planet cards appear X6 more frequently in the shop All key = "pacclimator", config = { extra = 24 / 4, extra_disp = 6 }, atlas = "atlasvoucher", - order = 84, + order = 32667, pos = { x = 0, y = 4 }, requires = { "v_planet_tycoon" }, pools = { ["Tier3"] = true }, @@ -783,7 +745,7 @@ local pacclimator = { --Planet cards appear X6 more frequently in the shop All })) end, } -local moneybean = { --Raise the cap on interest earned in each round to $2.0e299 +local moneybean = { -- Seed Money T3; Raise the cap on interest earned in each round to $2.0e299 cry_credits = { idea = { "Frix", @@ -804,7 +766,7 @@ local moneybean = { --Raise the cap on interest earned in each round to $2.0e299 key = "moneybean", config = { extra = 1e300 }, atlas = "atlasvoucher", - order = 85, + order = 32668, pos = { x = 5, y = 1 }, requires = { "v_money_tree" }, pools = { ["Tier3"] = true }, @@ -832,7 +794,7 @@ local moneybean = { --Raise the cap on interest earned in each round to $2.0e299 })) end, } -local fabric = { --+2 Joker slot[s] +local fabric = { -- Blank Voucher T3; +2 Joker slots cry_credits = { idea = { "Frix", @@ -853,7 +815,7 @@ local fabric = { --+2 Joker slot[s] key = "fabric", config = { extra = 2 }, atlas = "atlasvoucher", - order = 86, + order = 32669, pos = { x = 6, y = 0 }, requires = { "v_antimatter" }, pools = { ["Tier3"] = true }, @@ -898,8 +860,21 @@ local fabric = { --+2 Joker slot[s] end end, } ---Order 87 reserved for Fake-out (unimplemented) -local asteroglyph = { --Set Ante to 0 +local MTRICKT3PLACEHOLDER = { -- RESERVED FOR MAGIC TRICK T3 + object_type = "Voucher", + dependencies = { + items = { + "set_cry_tier3", + }, + }, + key = "TSCOPET3PLACEHOLDER", + atlas = "atlasvoucher", + order = 32670, + pos = { x = 2, y = 0 }, + requires = { "v_observatory" }, + pools = { ["Tier3"] = true }, +} +local asteroglyph = { -- Heiroglyph T3; Set Ante to 0 cry_credits = { idea = { "Frix", @@ -919,7 +894,7 @@ local asteroglyph = { --Set Ante to 0 }, key = "asteroglyph", atlas = "atlasvoucher", - order = 88, + order = 32761, pos = { x = 5, y = 2 }, requires = { "v_petroglyph" }, pools = { ["Tier3"] = true }, @@ -963,8 +938,21 @@ local asteroglyph = { --Set Ante to 0 end end, } ---Order 89 reserved for Ivory Script (unimplemented) -local blankcanvas = { --+2 hand size +local DCUTT3PLACEHOLDER = { -- RESERVED FOR DIRECTOR'S CUT T3 + object_type = "Voucher", + dependencies = { + items = { + "set_cry_tier3", + }, + }, + key = "TSCOPET3PLACEHOLDER", + atlas = "atlasvoucher", + order = 32672, + pos = { x = 2, y = 0 }, + requires = { "v_observatory" }, + pools = { ["Tier3"] = true }, +} +local blankcanvas = { -- Paint Brush T3; +2 hand size cry_credits = { idea = { "Frix", @@ -985,7 +973,7 @@ local blankcanvas = { --+2 hand size key = "blankcanvas", config = { extra = 2 }, atlas = "atlasvoucher", - order = 90, + order = 32763, pos = { x = 2, y = 4 }, requires = { "v_palette" }, pools = { ["Tier3"] = true }, @@ -1011,91 +999,110 @@ local blankcanvas = { --+2 hand size end end, } -local stickyhand = { --+1 card selection limit +local clone_machine = { -- DTag Voucher T3; Double tags become Quintuple Tags and are 4X as common cry_credits = { idea = { - "HexaCryonic", + "Catman", + "Mystic Misclick", }, art = { - "HexaCryonic", + "Linus Goof Balls", }, code = { - "HexaCryonic", + "Math", }, }, object_type = "Voucher", dependencies = { items = { "set_cry_voucher", + "set_cry_tag", + "set_cry_tier3", + "v_cry_tag_printer", }, }, - key = "stickyhand", - config = { extra = 1 }, + key = "clone_machine", atlas = "atlasvoucher", - order = 9, - pos = { x = 0, y = 5 }, - loc_vars = function(self, info_queue, card) - return { vars = { (card and card.ability.extra or self.config.extra) } } - end, - redeem = function(self, card) - G.hand.config.highlighted_limit = G.hand.config.highlighted_limit - + (card and card.ability.extra or self.config.extra) - end, - unredeem = function(self, card) - G.hand.config.highlighted_limit = G.hand.config.highlighted_limit - - (card and card.ability.extra or self.config.extra) - if G.hand.config.highlighted_limit < 5 then - G.hand.config.highlighted_limit = 5 - end - if not G.GAME.before_play_buffer then - G.hand:unhighlight_all() - end + order = 32764, + pos = { x = 1, y = 3 }, + pools = { ["Tier3"] = true }, + loc_vars = function(self, info_queue) + info_queue[#info_queue + 1] = { set = "Tag", key = "tag_double" } + info_queue[#info_queue + 1] = { set = "Tag", key = "tag_cry_quintuple", specific_vars = { 4 } } + return { vars = {} } end, + requires = { "v_cry_tag_printer" }, } -local grapplinghook = { --+1 card selection limit (replace me when "extra functionality" is added later) - cry_credits = { - idea = { - "HexaCryonic", - }, - art = { - "HexaCryonic", - }, - code = { - "HexaCryonic", - }, - }, +local pairamount_plus = { -- M T3; Retrigger all M Jokers once for every pair contained in played hand object_type = "Voucher", dependencies = { items = { "set_cry_voucher", - "v_cry_stickyhand", + "set_cry_m", + "set_cry_tier3", + "v_cry_repair_man", }, }, - key = "grapplinghook", - config = { extra = 2 }, + key = "pairamount_plus", atlas = "atlasvoucher", - order = 10, - pos = { x = 1, y = 5 }, - requires = { "v_cry_stickyhand" }, - loc_vars = function(self, info_queue, card) - return { vars = { (card and card.ability.extra or self.config.extra) } } - end, - redeem = function(self, card) - G.hand.config.highlighted_limit = G.hand.config.highlighted_limit - + (card and card.ability.extra or self.config.extra) - end, - unredeem = function(self, card) - G.hand.config.highlighted_limit = G.hand.config.highlighted_limit - - (card and card.ability.extra or self.config.extra) - if G.hand.config.highlighted_limit < 5 then - G.hand.config.highlighted_limit = 5 - end - if not G.GAME.before_play_buffer then - G.hand:unhighlight_all() + order = 32765, + pos = { x = 6, y = 5 }, + requires = { "v_cry_repair_man" }, + pools = { ["Tier3"] = true }, + cry_credits = { + art = { + "lolxddj", + }, + code = { + "Math", + }, + jolly = { + "Jolly Open Winner", + "Xaltios", + }, + }, + in_pool = function(self) + local mcheck = Cryptid.get_m_jokers() + if mcheck > 0 then + return true end + return false end, } -local hyperspacetether = { --+2 card selection limit + other stuff +local double_down = { -- DSide T3; After every round, X1.5 to all values on the back of Double-Sided Cards + object_type = "Voucher", + dependencies = { + items = { + "set_cry_voucher", + "set_cry_tier3", + "e_cry_double_sided", + "v_cry_double_slit", + }, + }, + key = "double_down", + atlas = "atlasvoucher", + order = 32766, + pos = { x = 4, y = 4 }, + requires = { "v_cry_double_slit" }, + pools = { ["Tier3"] = true }, + loc_vars = function(self, info_queue) + info_queue[#info_queue + 1] = G.P_CENTERS.e_cry_double_sided + end, + cry_credits = { + art = { + "Linus Goof Balls", + }, + code = { + "Math", + "lord-ruby", + }, + jolly = { + "Jolly Open Winner", + "Axolotolus", + }, + }, +} +local hyperspacetether = { -- CSL T3; +2 card selection limit, all* selected cards contribute to asc power cry_credits = { idea = { "HexaCryonic", @@ -1119,27 +1126,58 @@ local hyperspacetether = { --+2 card selection limit + other stuff config = { extra = 2 }, atlas = "atlasvoucher", pos = { x = 2, y = 5 }, - order = 95, + order = 32767, requires = { "v_cry_grapplinghook" }, pools = { ["Tier3"] = true }, loc_vars = function(self, info_queue, card) return { vars = { (card and card.ability.extra or self.config.extra) } } end, redeem = function(self, card) - G.hand.config.highlighted_limit = G.hand.config.highlighted_limit - + (card and card.ability.extra or self.config.extra) + SMODS.change_play_limit(card.ability.extra or self.config.extra) + SMODS.change_discard_limit(card.ability.extra or self.config.extra) end, unredeem = function(self, card) - G.hand.config.highlighted_limit = G.hand.config.highlighted_limit - - (card and card.ability.extra or self.config.extra) - if G.hand.config.highlighted_limit < 5 then - G.hand.config.highlighted_limit = 5 - end + SMODS.change_play_limit(-(card.ability.extra or self.config.extra)) + SMODS.change_discard_limit(-(card.ability.extra or self.config.extra)) if not G.GAME.before_play_buffer then G.hand:unhighlight_all() end end, } +local quantum_computing = { -- Code T3; Code cards spawn with +1 use + cry_credits = { + idea = { + "HexaCryonic", + }, + art = { + "HexaCryonic", + }, + code = { + "Mathguy", + }, + }, + object_type = "Voucher", + dependencies = { + items = { + "set_cry_voucher", + "set_cry_tier3", + "set_cry_code", + "v_cry_satellite_uplink", + }, + }, + key = "quantum_computing", + order = 32768, + atlas = "atlasvoucher", + pos = { x = 0, y = 3 }, + config = { extra = 1 }, + pools = { ["Tier3"] = true }, + loc_vars = function(self, info_queue, card) + return { vars = { (card and card.ability.extra or self.config.extra) } } + end, + requires = { "v_cry_satellite_uplink" }, +} + +-- Triple+ tag tags local triple = { --Copies voucher triple tag cry_credits = { idea = { @@ -1351,36 +1389,44 @@ if SMODS.Mods["Tier3Sub"] then end local voucheritems = { voucher_atlas, + -- Cryptid Normal Vouchers copies, tag_printer, - triple, - quadruple, - quintuple, + pairing, + repair_man, + double_vision, + double_slit, + stickyhand, + grapplinghook, + command_prompt, + satellite_uplink, + -- Vanilla T3s overstock_multi, massproduct, curate, rerollexchange, + -- Crystal Ball T3 Placeholder + -- Telescope T3 Placeholder dexterity, threers, tacclimator, pacclimator, moneybean, fabric, + -- Magic Trick T3 Placeholder asteroglyph, + -- Director's Cut T3 Placeholder blankcanvas, + -- Cryptid T3s clone_machine, - stickyhand, - grapplinghook, - hyperspacetether, - command_prompt, - satellite_uplink, - quantum_computing, - pairing, - repair_man, pairamount_plus, - double_vision, - double_slit, double_down, + hyperspacetether, + quantum_computing, + + triple, + quadruple, + quintuple, } return { name = "Vouchers", diff --git a/Cryptid/lib/ascended.lua b/Cryptid/lib/ascended.lua index 0c757b6..734f1bf 100644 --- a/Cryptid/lib/ascended.lua +++ b/Cryptid/lib/ascended.lua @@ -32,9 +32,15 @@ function G.FUNCS.get_poker_hand_info(_cards) loc_disp_text = localize(disp_text, "poker_hands") end end - + local hidden = false + for i, v in pairs(scoring_hand) do + if v.facing == "back" then + hidden = true + break + end + end if G.SETTINGS.language == "en-us" then - if #scoring_hand > 5 and (text == "Flush Five" or text == "Five of a Kind") then + if #scoring_hand > 5 and (text == "Flush Five" or text == "Five of a Kind" or text == "bunc_Spectrum Five") then local rank_array = {} local county = 0 for i = 1, #scoring_hand do @@ -104,103 +110,192 @@ function G.FUNCS.get_poker_hand_info(_cards) return str_ret end -- text gets stupid small at 100+ anyway - loc_disp_text = (text == "Flush Five" and "Flush " or "") + loc_disp_text = (text == "Flush Five" and "Flush " or text == "bunc_Spectrum Five" and "Spectrum " or "") .. ( (county < 1000 and create_num_chunk(county) or "Thousand") .. (text == "Five of a Kind" and " of a Kind" or "") ) end end - local hand_table = { - ["High Card"] = G.GAME.used_vouchers.v_cry_hyperspacetether and 1 or nil, - ["Pair"] = G.GAME.used_vouchers.v_cry_hyperspacetether and 2 or nil, - ["Two Pair"] = 4, - ["Three of a Kind"] = G.GAME.used_vouchers.v_cry_hyperspacetether and 3 or nil, - ["Straight"] = next(SMODS.find_card("j_four_fingers")) and Cryptid.gameset() ~= "modest" and 4 or 5, - ["Flush"] = next(SMODS.find_card("j_four_fingers")) and Cryptid.gameset() ~= "modest" and 4 or 5, - ["Full House"] = 5, - ["Four of a Kind"] = G.GAME.used_vouchers.v_cry_hyperspacetether and 4 or nil, - ["Straight Flush"] = next(SMODS.find_card("j_four_fingers")) and Cryptid.gameset() ~= "modest" and 4 or 5, --debatable - ["cry_Bulwark"] = 5, - ["Five of a Kind"] = 5, - ["Flush House"] = 5, - ["Flush Five"] = 5, - ["cry_Clusterfuck"] = 8, - ["cry_UltPair"] = 8, - ["cry_WholeDeck"] = 52, - } - -- Change mult and chips colors if hand is ascended - if hand_table[text] and next(scoring_hand) and #scoring_hand > hand_table[text] then - ease_colour(G.C.UI_CHIPS, copy_table(G.C.GOLD), 0.3) - ease_colour(G.C.UI_MULT, copy_table(G.C.GOLD), 0.3) - else - ease_colour(G.C.UI_CHIPS, G.C.BLUE, 0.3) - ease_colour(G.C.UI_MULT, G.C.RED, 0.3) - end - -- this is where all the logic for asc hands is. currently it's very simple but if you want more complex logic, here's the place to do it - if hand_table[text] and Cryptid.enabled("set_cry_poker_hand_stuff") == true then - G.GAME.current_round.current_hand.cry_asc_num = G.GAME.used_vouchers.v_cry_hyperspacetether - and #_cards - hand_table[text] - or #scoring_hand - hand_table[text] + -- Ascension power + local a_power = Cryptid.calculate_ascension_power( + text, + _cards, + scoring_hand, + G.GAME.used_vouchers.v_cry_hyperspacetether, + G.GAME.bonus_asc_power + ) + if a_power > 0 then + G.GAME.current_round.current_hand.cry_asc_num = a_power + -- Change mult and chips colors if hand is ascended + if not hidden then + ease_colour(G.C.UI_CHIPS, copy_table(G.C.GOLD), 0.3) + ease_colour(G.C.UI_MULT, copy_table(G.C.GOLD), 0.3) + G.GAME.current_round.current_hand.cry_asc_num_text = ( + a_power and (type(a_power) == "table" and a_power:gt(to_big(0)) or a_power > 0) + ) + and " (+" .. a_power .. ")" + or "" + else + ease_colour(G.C.UI_CHIPS, G.C.BLUE, 0.3) + ease_colour(G.C.UI_MULT, G.C.RED, 0.3) + G.GAME.current_round.current_hand.cry_asc_num_text = "" + end else G.GAME.current_round.current_hand.cry_asc_num = 0 + ease_colour(G.C.UI_CHIPS, G.C.BLUE, 0.3) + ease_colour(G.C.UI_MULT, G.C.RED, 0.3) + G.GAME.current_round.current_hand.cry_asc_num_text = "" end - - G.GAME.current_round.current_hand.cry_asc_num = math.max(0, G.GAME.current_round.current_hand.cry_asc_num) - if G.GAME.cry_exploit_override then - G.GAME.current_round.current_hand.cry_asc_num = G.GAME.current_round.current_hand.cry_asc_num + 1 - end - - G.GAME.current_round.current_hand.cry_asc_num_text = ( - G.GAME.current_round.current_hand.cry_asc_num - and ( - type(G.GAME.current_round.current_hand.cry_asc_num) == "table" - and G.GAME.current_round.current_hand.cry_asc_num:gt(to_big(0)) - or G.GAME.current_round.current_hand.cry_asc_num > 0 - ) - ) - and " (+" .. G.GAME.current_round.current_hand.cry_asc_num .. ")" - or "" return text, loc_disp_text, poker_hands, scoring_hand, disp_text end function Cryptid.ascend(num) -- edit this function at your leisure - if Cryptid.enabled("set_cry_poker_hand_stuff") ~= true then + if (Cryptid.safe_get(G, "GAME", "current_round", "current_hand", "cry_asc_num") or 0) <= 0 then return num end - if Cryptid.gameset() == "modest" then - -- x(1.1 + 0.05 per sol) base, each card gives + (0.1 + 0.05 per sol) - if not G.GAME.current_round.current_hand.cry_asc_num then - return num - end - if G.GAME.current_round.current_hand.cry_asc_num <= 0 then - return num - end - return math.max( - num, - num - * ( - 1 - + 0.1 - + to_big(0.05 * (G.GAME.sunnumber or 0)) - + to_big( - (0.1 + (0.05 * (G.GAME.sunnumber or 0))) - * to_big(G.GAME.current_round.current_hand.cry_asc_num or 0) - ) - ) - ) + if Cryptid.gameset(G.P_CENTERS.c_cry_sunplanet) == "modest" then + -- Default: Chips and Mult multiplier + 0.25 for every 1 Ascension power + return num * to_big(1 + ((0.25 + G.GAME.sunnumber.modest) * G.GAME.current_round.current_hand.cry_asc_num)) else - return math.max( - num, - num - * to_big( - (1.25 + (0.05 * (G.GAME.sunnumber or 0))) - ^ to_big(G.GAME.current_round.current_hand.cry_asc_num or 0) - ) - ) + -- Default: Chips and Mult multiplier X1.25 for every 1 Ascension power + return num * to_big((1.25 + G.GAME.sunnumber.not_modest) ^ G.GAME.current_round.current_hand.cry_asc_num) end end + function Cryptid.pulse_flame(duration, intensity) -- duration is in seconds, intensity is in idfk honestly, but it increases pretty quickly G.cry_flame_override = G.cry_flame_override or {} G.cry_flame_override["duration"] = duration or 0.01 G.cry_flame_override["intensity"] = intensity or 2 end + +function Cryptid.calculate_ascension_power(hand_name, hand_cards, hand_scoring_cards, tether, bonus) + bonus = bonus or 0 + local starting = 0 + if Cryptid.enabled("set_cry_poker_hand_stuff") ~= true then + return 0 + end + if hand_name then + -- Get Starting Ascension power from Poker Hands + if hand_cards then + local check = Cryptid.hand_ascension_numbers(hand_name, tether) + if check then + starting = (tether and #hand_cards or #hand_scoring_cards) - check + end + end + -- Extra starting calculation for Declare hands + if G.GAME.hands[hand_name] and G.GAME.hands[hand_name].declare_cards then + local total = 0 + for i, v in pairs(G.GAME.hands[hand_name].declare_cards or {}) do + local how_many_fit = 0 + local suit, rank + for i2, v2 in pairs(hand_cards) do + if not v2.marked then + if SMODS.has_no_rank(v2) and v.rank == "rankless" or v2:get_id() == v.rank then + rank = true + end + if v2:is_suit(v.suit) or (v.suit == "suitless" and SMODS.has_no_suit(v2)) or not v.suit then + suit = true + end + if not (suit and rank) then + suit = false + rank = false + end + if suit and rank then + how_many_fit = how_many_fit + 1 + v2.marked = true + end + end + end + if not rank or not suit then + how_many_fit = 0 + end + total = total + how_many_fit + end + for i2, v2 in pairs(hand_cards) do + v2.marked = nil + end + starting = starting + (total - #hand_scoring_cards) + end + end + -- Get Ascension power from Exploit + if G.GAME.cry_exploit_override then + bonus = bonus + 1 + end + -- Get Ascension Power From Sol (Observatory effect) + if G.GAME.used_vouchers.v_observatory and next(find_joker("cry-sunplanet")) then + if #find_joker("cry-sunplanet") == 1 then + bonus = bonus + 1 + else + bonus = bonus + Cryptid.nuke_decimals(Cryptid.funny_log(2, #find_joker("cry-sunplanet") + 1), 2) + end + end + local final = math.max(0, starting + bonus) + -- Round to 1 if final value is less than 1 but greater than 0 + if final > 0 and final < 1 then + final = 1 + end + return final +end +function Cryptid.hand_ascension_numbers(hand_name, tether) + if Cryptid.ascension_numbers[hand_name] and type(Cryptid.ascension_numbers[hand_name]) == "function" then + return Cryptid.ascension_numbers[hand_name](hand_name, tether) + end + if hand_name == "High Card" then + return tether and 1 or nil + elseif hand_name == "Pair" then + return tether and 2 or nil + elseif hand_name == "Two Pair" then + return 4 + elseif hand_name == "Three of a Kind" then + return tether and 3 or nil + elseif hand_name == "Straight" or hand_name == "Flush" or hand_name == "Straight Flush" then + return next(SMODS.find_card("j_four_fingers")) and Cryptid.gameset() ~= "modest" and 4 or 5 + elseif + hand_name == "Full House" + or hand_name == "Five of a Kind" + or hand_name == "Flush House" + or hand_name == "cry_Bulwark" + or hand_name == "Flush Five" + or hand_name == "bunc_Spectrum" + or hand_name == "bunc_Straight Spectrum" + or hand_name == "bunc_Spectrum House" + or hand_name == "bunc_Spectrum Five" + then + return 5 + elseif hand_name == "Four of a Kind" then + return G.GAME.used_vouchers.v_cry_hyperspacetether and 4 or nil + elseif hand_name == "cry_Clusterfuck" or hand_name == "cry_UltPair" then + return 8 + elseif hand_name == "cry_WholeDeck" then + return 52 + elseif hand_name == "cry_Declare0" then + return G.GAME.hands.cry_Declare0 + and G.GAME.hands.cry_Declare0.declare_cards + and #G.GAME.hands.cry_Declare0.declare_cards + elseif hand_name == "cry_Declare1" then + return G.GAME.hands.cry_Declare1 + and G.GAME.hands.cry_Declare1.declare_cards + and #G.GAME.hands.cry_Declare1.declare_cards + elseif hand_name == "cry_Declare2" then + return G.GAME.hands.cry_Declare2 + and G.GAME.hands.cry_Declare2.declare_cards + and #G.GAME.hands.cry_Declare2.declare_cards + elseif + hand_name == "spa_Spectrum" + or hand_name == "spa_Straight_Spectrum" + or hand_name == "spa_Spectrum_House" + or hand_name == "spa_Spectrum_Five" + or hand_name == "spa_Flush_Spectrum" + or hand_name == "spa_Straight_Flush_Spectrum" + or hand_name == "spa_Flush_Spectrum_House" + or hand_name == "spa_Flush_Spectrum_Five" + then + return SpectrumAPI + and SpectrumAPI.configuration.misc.four_fingers_spectrums + and next(SMODS.find_card("j_four_fingers")) + and Cryptid.gameset() ~= "modest" + and 4 + or 5 + end + return nil +end diff --git a/Cryptid/lib/calculate.lua b/Cryptid/lib/calculate.lua index 2a97533..e399719 100644 --- a/Cryptid/lib/calculate.lua +++ b/Cryptid/lib/calculate.lua @@ -3,18 +3,19 @@ -- deal with Rigged and Fragile when scoring a playing card local ec = eval_card function eval_card(card, context) + if not card then + card = { + ability = {}, + can_calculate = function() + return false + end, + } + end if card.will_shatter then return {}, {} end -- Store old probability for later reference - local ggpn = G.GAME.probabilities.normal - if card.ability.cry_rigged then - G.GAME.probabilities.normal = 1e9 - end local ret, post = ec(card, context) - if card.ability.cry_rigged then - G.GAME.probabilities.normal = ggpn - end return ret, post end @@ -39,398 +40,6 @@ function Card:cry_copy_ability() end local cj = Card.calculate_joker -function Card:cry_double_scale_calc(orig_ability, in_context_scaling) - if - self.ability.name ~= "cry-happyhouse" - and self.ability.name ~= "Acrobat" - and self.ability.name ~= "cry-sapling" - and self.ability.name ~= "cry-mstack" - and self.ability.name ~= "cry-notebook" - and self.ability.name ~= "Invisible Joker" - and self.ability.name ~= "cry-Old Invisible Joker" - then - local jkr = self - if jkr.ability and type(jkr.ability) == "table" then - if not G.GAME.cry_double_scale[jkr.sort_id] or not G.GAME.cry_double_scale[jkr.sort_id].ability then - if not G.GAME.cry_double_scale[jkr.sort_id] then - G.GAME.cry_double_scale[jkr.sort_id] = { ability = { double_scale = true } } - end - for k, v in pairs(jkr.ability) do - if type(jkr.ability[k]) ~= "table" then - G.GAME.cry_double_scale[jkr.sort_id].ability[k] = v - else - G.GAME.cry_double_scale[jkr.sort_id].ability[k] = {} - for _k, _v in pairs(jkr.ability[k]) do - G.GAME.cry_double_scale[jkr.sort_id].ability[k][_k] = _v - end - end - end - end - if G.GAME.cry_double_scale[jkr.sort_id] and not G.GAME.cry_double_scale[jkr.sort_id].scaler then - local dbl_info = G.GAME.cry_double_scale[jkr.sort_id] - if jkr.ability.name == "cry-Number Blocks" then - dbl_info.base = { "extra", "money" } - dbl_info.scaler = { "extra", "money_mod" } - dbl_info.scaler_base = jkr.ability.extra.money_mod - dbl_info.offset = 1 - end - if jkr.ability.name == "cry-Exponentia" then - dbl_info.base = { "extra", "Emult" } - dbl_info.scaler = { "extra", "Emult_mod" } - dbl_info.scaler_base = jkr.ability.extra.Emult_mod - dbl_info.offset = 1 - end - if jkr.ability.name == "cry-Redeo" then - dbl_info.base = { "extra", "money_req" } - dbl_info.scaler = { "extra", "money_mod" } - dbl_info.scaler_base = jkr.ability.extra.money_mod - dbl_info.offset = 1 - end - if jkr.ability.name == "cry-Chili Pepper" then - dbl_info.base = { "extra", "Xmult" } - dbl_info.scaler = { "extra", "Xmult_mod" } - dbl_info.scaler_base = jkr.ability.extra.Xmult_mod - dbl_info.offset = 1 - end - if jkr.ability.name == "cry-Scalae" then - dbl_info.base = { "extra", "shadow_scale" } - dbl_info.scaler = { "extra", "shadow_scale_mod" } - dbl_info.scaler_base = jkr.ability.extra.scale_mod - dbl_info.offset = 1 - end - if jkr.ability.name == "cry-mprime" then - dbl_info.base = { "extra", "mult" } - dbl_info.scaler = { "extra", "bonus" } - dbl_info.scaler_base = jkr.ability.extra.bonus - dbl_info.offset = 1 - end - if jkr.ability.name == "Yorick" then - dbl_info.base = { "x_mult" } - dbl_info.scaler = { "extra", "xmult" } --not kidding - dbl_info.scaler_base = 1 - dbl_info.offset = 1 - end - if jkr.ability.name == "Hologram" then - dbl_info.base = { "x_mult" } - dbl_info.scaler = { "extra" } - dbl_info.scaler_base = jkr.ability.extra - dbl_info.offset = 1 - end - if jkr.ability.name == "Gift Card" then - dbl_info.base = { "extra_value" } - dbl_info.scaler = { "extra" } - dbl_info.scaler_base = jkr.ability.extra - dbl_info.offset = 1 - end - if jkr.ability.name == "Throwback" then - dbl_info.base = { "x_mult" } - dbl_info.scaler = { "extra" } - dbl_info.scaler_base = jkr.ability.x_mult or 1 - dbl_info.offset = 1 - end - if jkr.ability.name == "Egg" then - dbl_info.base = { "extra_value" } - dbl_info.scaler = { "extra" } - dbl_info.scaler_base = jkr.ability.extra - dbl_info.offset = 1 - end - local default_modifiers = { - mult = 0, - h_mult = 0, - h_x_mult = 0, - h_dollars = 0, - p_dollars = 0, - t_mult = 0, - t_chips = 0, - x_mult = 1, - h_size = 0, - d_size = 0, - } - for k, v in pairs(jkr.ability) do - --extra_value is ignored because it can be scaled by Gift Card - if - k ~= "extra_value" - and dbl_info.ability[k] ~= v - and is_number(v) - and is_number(dbl_info.ability[k]) - then - dbl_info.base = { k } - local predicted_mod = math.abs(to_number(to_big(v)) - to_number(to_big(dbl_info.ability[k]))) - local best_key = { "" } - local best_coeff = 10 ^ 100 - for l, u in pairs(jkr.ability) do - if not (default_modifiers[l] and default_modifiers[l] == u) then - if l ~= k and is_number(u) then - if - to_number(to_big(predicted_mod / u)) >= 0.999 - and to_number(to_big(predicted_mod / u)) < to_number(to_big(best_coeff)) - then - best_coeff = to_number(to_big(predicted_mod / u)) - best_key = { l } - end - end - if type(jkr.ability[l]) == "table" then - for _l, _u in pairs(jkr.ability[l]) do - if - is_number(_u) - and to_number(to_big(predicted_mod / _u)) >= 0.999 - and to_number(to_big(predicted_mod / _u)) - < to_number(to_big(best_coeff)) - then - best_coeff = to_number(to_big(predicted_mod / _u)) - best_key = { l, _l } - end - end - end - end - end - dbl_info.scaler = best_key - end - if - type(jkr.ability[k]) == "table" - and type(dbl_info.ability) == "table" - and type(dbl_info.ability[k]) == "table" - then - for _k, _v in pairs(jkr.ability[k]) do - if - dbl_info.ability[k][_k] ~= _v - and is_number(_v) - and is_number(dbl_info.ability[k][_k]) - then - dbl_info.base = { k, _k } - local predicted_mod = math.abs(_v - dbl_info.ability[k][_k]) - local best_key = { "" } - local best_coeff = 10 ^ 100 - for l, u in pairs(jkr.ability) do - if is_number(u) and to_number(to_big(predicted_mod / u)) >= 0.999 then - if to_number(to_big(predicted_mod / u)) < to_number(to_big(best_coeff)) then - best_coeff = to_number(to_big(predicted_mod / u)) - best_key = { l } - end - end - if type(jkr.ability[l]) == "table" then - for _l, _u in pairs(jkr.ability[l]) do - if - (l ~= k or _l ~= _k) - and is_number(_u) - and to_number(to_big(predicted_mod / _u)) >= 0.999 - then - if - to_number(to_big(predicted_mod / _u)) - < to_number(to_big(best_coeff)) - then - best_coeff = to_number(to_big(predicted_mod / _u)) - best_key = { l, _l } - end - end - end - end - end - dbl_info.scaler = best_key - end - end - end - end - if dbl_info.scaler then - dbl_info.scaler_base = #dbl_info.scaler == 2 - and orig_ability[dbl_info.scaler[1]][dbl_info.scaler[2]] - or orig_ability[dbl_info.scaler[1]] - dbl_info.offset = 1 - end - end - end - end - local orig_scale_base = nil - local orig_scale_scale = nil - if G.GAME.cry_double_scale[self.sort_id] and G.GAME.cry_double_scale[self.sort_id].scaler then - local jkr = self - local dbl_info = G.GAME.cry_double_scale[self.sort_id] - if #dbl_info.base == 2 then - if - not ( - type(jkr.ability) ~= "table" - or not orig_ability[dbl_info.base[1]] - or type(orig_ability[dbl_info.base[1]]) ~= "table" - or not orig_ability[dbl_info.base[1]][dbl_info.base[2]] - ) - then - orig_scale_base = orig_ability[dbl_info.base[1]][dbl_info.base[2]] - end - else - if jkr.ability[dbl_info.base[1]] then - orig_scale_base = orig_ability[dbl_info.base[1]] - end - end - if #dbl_info.scaler == 2 then - if - not ( - not orig_ability[dbl_info.scaler[1]] - or type(orig_ability[dbl_info.scaler[1]]) == "number" - or not orig_ability[dbl_info.scaler[1]][dbl_info.scaler[2]] - ) - then - orig_scale_scale = orig_ability[dbl_info.scaler[1]][dbl_info.scaler[2]] - end - else - if orig_ability[dbl_info.scaler[1]] then - orig_scale_scale = orig_ability[dbl_info.scaler[1]] - end - end - end - - if orig_scale_base and orig_scale_scale then - local new_scale_base = nil - local true_base = nil - local jkr = self - local dbl_info = G.GAME.cry_double_scale[self.sort_id] - if #dbl_info.base == 2 then - if - not ( - type(jkr.ability) ~= "table" - or not jkr.ability[dbl_info.base[1]] - or type(jkr.ability[dbl_info.base[1]]) ~= "table" - or not jkr.ability[dbl_info.base[1]][dbl_info.base[2]] - ) - then - new_scale_base = jkr.ability[dbl_info.base[1]][dbl_info.base[2]] - end - else - if jkr.ability[dbl_info.base[1]] then - new_scale_base = jkr.ability[dbl_info.base[1]] - end - end - true_base = dbl_info.scaler_base - if - new_scale_base and ((to_big(math.abs(new_scale_base - orig_scale_base)) > to_big(0)) or in_context_scaling) - then - for i = 1, #G.jokers.cards do - local obj = G.jokers.cards[i].config.center - if obj.cry_scale_mod and type(obj.cry_scale_mod) == "function" then - local ggpn = G.GAME.probabilities.normal - if G.jokers.cards[i].ability.cry_rigged then - G.GAME.probabilities.normal = 1e9 - end - local o = obj:cry_scale_mod( - G.jokers.cards[i], - jkr, - orig_scale_scale, - true_base, - orig_scale_base, - new_scale_base - ) - if G.jokers.cards[i].ability.cry_rigged then - G.GAME.probabilities.normal = ggpn - end - if o then - if #dbl_info.scaler == 2 then - if - not ( - not jkr.ability[dbl_info.scaler[1]] - or not jkr.ability[dbl_info.scaler[1]][dbl_info.scaler[2]] - ) - then - jkr.ability[dbl_info.scaler[1]][dbl_info.scaler[2]] = o - orig_scale_scale = o - end - else - if jkr.ability[dbl_info.scaler[1]] then - jkr.ability[dbl_info.scaler[1]] = o - orig_scale_scale = o - end - end - card_eval_status_text( - G.jokers.cards[i], - "extra", - nil, - nil, - nil, - { message = localize("k_upgrade_ex") } - ) - end - local reps = {} - for i2 = 1, #G.jokers.cards do - local _card = G.jokers.cards[i2] - local ggpn = G.GAME.probabilities.normal - if _card.ability.cry_rigged then - G.GAME.probabilities.normal = 1e9 - end - local check = - cj(G.jokers.cards[i2], { retrigger_joker_check = true, other_card = G.jokers.cards[i] }) - if _card.ability.cry_rigged then - G.GAME.probabilities.normal = ggpn - end - if type(check) == "table" then - reps[i2] = check and check.repetitions and check or 0 - else - reps[i2] = 0 - end - if - G.jokers.cards[i2] == G.jokers.cards[i] - and G.jokers.cards[i].edition - and G.jokers.cards[i].edition.retriggers - then - local old_repetitions = reps[i] ~= 0 and reps[i].repetitions or 0 - local check = false --G.jokers.cards[i]:calculate_retriggers() - if check and check.repetitions then - check.repetitions = check.repetitions + old_repetitions - reps[i] = check - end - end - end - for i0, j in ipairs(reps) do - if (type(j) == "table") and j.repetitions and (j.repetitions > 0) then - for r = 1, j.repetitions do - card_eval_status_text(j.card, "jokers", nil, nil, nil, j) - local ggpn = G.GAME.probabilities.normal - if G.jokers.cards[i].ability.cry_rigged then - G.GAME.probabilities.normal = 1e9 - end - local o = obj:cry_scale_mod( - G.jokers.cards[i], - jkr, - orig_scale_scale, - true_base, - orig_scale_base, - new_scale_base - ) - if G.jokers.cards[i].ability.cry_rigged then - G.GAME.probabilities.normal = ggpn - end - if o then - if #dbl_info.scaler == 2 then - if - not ( - not jkr.ability[dbl_info.scaler[1]] - or not jkr.ability[dbl_info.scaler[1]][dbl_info.scaler[2]] - ) - then - jkr.ability[dbl_info.scaler[1]][dbl_info.scaler[2]] = o - orig_scale_scale = o - end - else - if jkr.ability[dbl_info.scaler[1]] then - jkr.ability[dbl_info.scaler[1]] = o - orig_scale_scale = o - end - end - card_eval_status_text( - G.jokers.cards[i], - "extra", - nil, - nil, - nil, - { message = localize("k_upgrade_ex") } - ) - end - end - end - end - end - end - end - end -end - local smcc = SMODS.calculate_context function SMODS.calculate_context(context, return_table) for k, v in pairs(SMODS.Events) do @@ -497,27 +106,27 @@ function Card:calculate_joker(context) and self.edition and self.edition.cry_double_sided then - self:init_dbl_side() - active_side = self.dbl_side - if context.callback then - local m = context.callback - context.callback = function(card, a, b) - m(self, a, b) + local dummy = self:get_other_side_dummy() + if dummy then + active_side = dummy + if context.callback then + local m = context.callback + context.callback = function(card, a, b) + m(self, a, b) + end + context.dbl_side = true end - context.dbl_side = true + else + return end end - if active_side.will_shatter then + if not active_side or active_side.will_shatter then return end - local ggpn = G.GAME.probabilities.normal if not G.GAME.cry_double_scale then G.GAME.cry_double_scale = { double_scale = true } --doesn't really matter what's in here as long as there's something end - if active_side.ability.cry_rigged then - G.GAME.probabilities.normal = 1e9 - end - local orig_ability = active_side:cry_copy_ability() + local orig_ability = copy_table(active_side.ability) local in_context_scaling = false local callback = context.callback if active_side.ability.cry_possessed then @@ -594,327 +203,5 @@ function Card:calculate_joker(context) in_context_scaling = true end end - if active_side.ability.cry_rigged then - G.GAME.probabilities.normal = ggpn - end - if - (next(find_joker("cry-Scalae")) or next(find_joker("cry-Double Scale"))) - or (active_side.ability.name == "cry-Exponentia" or "cry-Compound Interest") - then - active_side:cry_double_scale_calc(orig_ability, in_context_scaling) - end return ret, trig end - -function Cryptid.exponentia_scale_mod(self, orig_scale_scale, orig_scale_base, new_scale_base) - local jkr = self - local dbl_info = G.GAME.cry_double_scale[jkr.sort_id] - if jkr.ability and type(jkr.ability) == "table" then - if not G.GAME.cry_double_scale[jkr.sort_id] or not G.GAME.cry_double_scale[jkr.sort_id].ability then - if not G.GAME.cry_double_scale[jkr.sort_id] then - G.GAME.cry_double_scale[jkr.sort_id] = { ability = { double_scale = true } } - end - for k, v in pairs(jkr.ability) do - if type(jkr.ability[k]) ~= "table" then - G.GAME.cry_double_scale[jkr.sort_id].ability[k] = v - else - G.GAME.cry_double_scale[jkr.sort_id].ability[k] = {} - for _k, _v in pairs(jkr.ability[k]) do - G.GAME.cry_double_scale[jkr.sort_id].ability[k][_k] = _v - end - end - end - end - if not dbl_info then - dbl_info = {} - end - if G.GAME.cry_double_scale[jkr.sort_id] and not G.GAME.cry_double_scale[jkr.sort_id].scaler then - dbl_info.base = { "extra", "Emult" } - dbl_info.scaler = { "extra", "Emult_mod" } - dbl_info.scaler_base = jkr.ability.extra.Emult_mod - dbl_info.offset = 1 - end - end - local true_base = dbl_info.scaler_base - if true_base then - for i = 1, #G.jokers.cards do - local obj = G.jokers.cards[i].config.center - if obj.cry_scale_mod and type(obj.cry_scale_mod) == "function" then - local ggpn = G.GAME.probabilities.normal - if G.jokers.cards[i].ability.cry_rigged then - G.GAME.probabilities.normal = 1e9 - end - local o = obj:cry_scale_mod( - G.jokers.cards[i], - jkr, - orig_scale_scale, - true_base, - orig_scale_base, - new_scale_base - ) - if G.jokers.cards[i].ability.cry_rigged then - G.GAME.probabilities.normal = ggpn - end - if o then - if #dbl_info.scaler == 2 then - if - not ( - not jkr.ability[dbl_info.scaler[1]] - or not jkr.ability[dbl_info.scaler[1]][dbl_info.scaler[2]] - ) - then - jkr.ability[dbl_info.scaler[1]][dbl_info.scaler[2]] = o - orig_scale_scale = o - end - else - if jkr.ability[dbl_info.scaler[1]] then - jkr.ability[dbl_info.scaler[1]] = o - orig_scale_scale = o - end - end - card_eval_status_text( - G.jokers.cards[i], - "extra", - nil, - nil, - nil, - { message = localize("k_upgrade_ex") } - ) - end - local reps = {} - for i2 = 1, #G.jokers.cards do - local _card = G.jokers.cards[i2] - local ggpn = G.GAME.probabilities.normal - if _card.ability.cry_rigged then - G.GAME.probabilities.normal = 1e9 - end - local check = - cj(G.jokers.cards[i2], { retrigger_joker_check = true, other_card = G.jokers.cards[i] }) - if _card.ability.cry_rigged then - G.GAME.probabilities.normal = ggpn - end - if type(check) == "table" then - reps[i2] = check and check.repetitions and check or 0 - else - reps[i2] = 0 - end - if - G.jokers.cards[i2] == G.jokers.cards[i] - and G.jokers.cards[i].edition - and G.jokers.cards[i].edition.retriggers - then - local old_repetitions = reps[i] ~= 0 and reps[i].repetitions or 0 - local check = false --G.jokers.cards[i]:calculate_retriggers() - if check and check.repetitions then - check.repetitions = check.repetitions + old_repetitions - reps[i] = check - end - end - end - for i0, j in ipairs(reps) do - if (type(j) == "table") and j.repetitions and (j.repetitions > 0) then - for r = 1, j.repetitions do - card_eval_status_text(j.card, "jokers", nil, nil, nil, j) - local ggpn = G.GAME.probabilities.normal - if G.jokers.cards[i].ability.cry_rigged then - G.GAME.probabilities.normal = 1e9 - end - local o = obj:cry_scale_mod( - G.jokers.cards[i], - jkr, - orig_scale_scale, - true_base, - orig_scale_base, - new_scale_base - ) - if G.jokers.cards[i].ability.cry_rigged then - G.GAME.probabilities.normal = ggpn - end - if o then - if #dbl_info.scaler == 2 then - if - not ( - not jkr.ability[dbl_info.scaler[1]] - or not jkr.ability[dbl_info.scaler[1]][dbl_info.scaler[2]] - ) - then - jkr.ability[dbl_info.scaler[1]][dbl_info.scaler[2]] = o - orig_scale_scale = o - end - else - if jkr.ability[dbl_info.scaler[1]] then - jkr.ability[dbl_info.scaler[1]] = o - orig_scale_scale = o - end - end - card_eval_status_text( - G.jokers.cards[i], - "extra", - nil, - nil, - nil, - { message = localize("k_upgrade_ex") } - ) - end - end - end - end - end - end - end -end - -function Cryptid.compound_interest_scale_mod(self, orig_scale_scale, orig_scale_base, new_scale_base) - local jkr = self - local dbl_info = G.GAME.cry_double_scale[jkr.sort_id] - if jkr.ability and type(jkr.ability) == "table" then - if not G.GAME.cry_double_scale[jkr.sort_id] or not G.GAME.cry_double_scale[jkr.sort_id].ability then - if not G.GAME.cry_double_scale[jkr.sort_id] then - G.GAME.cry_double_scale[jkr.sort_id] = { ability = { double_scale = true } } - end - for k, v in pairs(jkr.ability) do - if type(jkr.ability[k]) ~= "table" then - G.GAME.cry_double_scale[jkr.sort_id].ability[k] = v - else - G.GAME.cry_double_scale[jkr.sort_id].ability[k] = {} - for _k, _v in pairs(jkr.ability[k]) do - G.GAME.cry_double_scale[jkr.sort_id].ability[k][_k] = _v - end - end - end - end - if G.GAME.cry_double_scale[jkr.sort_id] and not G.GAME.cry_double_scale[jkr.sort_id].scaler then - dbl_info.base = { "extra", "percent" } - dbl_info.scaler = { "extra", "percent_mod" } - dbl_info.scaler_base = jkr.ability.extra.percent_mod - dbl_info.offset = 1 - end - end - local true_base = dbl_info.scaler_base - if true_base then - for i = 1, #G.jokers.cards do - local obj = G.jokers.cards[i].config.center - if obj.cry_scale_mod and type(obj.cry_scale_mod) == "function" then - local ggpn = G.GAME.probabilities.normal - if G.jokers.cards[i].ability.cry_rigged then - G.GAME.probabilities.normal = 1e9 - end - local o = obj:cry_scale_mod( - G.jokers.cards[i], - jkr, - orig_scale_scale, - true_base, - orig_scale_base, - new_scale_base - ) - if G.jokers.cards[i].ability.cry_rigged then - G.GAME.probabilities.normal = ggpn - end - if o then - if #dbl_info.scaler == 2 then - if - not ( - not jkr.ability[dbl_info.scaler[1]] - or not jkr.ability[dbl_info.scaler[1]][dbl_info.scaler[2]] - ) - then - jkr.ability[dbl_info.scaler[1]][dbl_info.scaler[2]] = o - orig_scale_scale = o - end - else - if jkr.ability[dbl_info.scaler[1]] then - jkr.ability[dbl_info.scaler[1]] = o - orig_scale_scale = o - end - end - card_eval_status_text( - G.jokers.cards[i], - "extra", - nil, - nil, - nil, - { message = localize("k_upgrade_ex") } - ) - end - local reps = {} - for i2 = 1, #G.jokers.cards do - local _card = G.jokers.cards[i2] - local ggpn = G.GAME.probabilities.normal - if _card.ability.cry_rigged then - G.GAME.probabilities.normal = 1e9 - end - local check = - cj(G.jokers.cards[i2], { retrigger_joker_check = true, other_card = G.jokers.cards[i] }) - if _card.ability.cry_rigged then - G.GAME.probabilities.normal = ggpn - end - if type(check) == "table" then - reps[i2] = check and check.repetitions and check or 0 - else - reps[i2] = 0 - end - if - G.jokers.cards[i2] == G.jokers.cards[i] - and G.jokers.cards[i].edition - and G.jokers.cards[i].edition.retriggers - then - local old_repetitions = reps[i] ~= 0 and reps[i].repetitions or 0 - local check = false --G.jokers.cards[i]:calculate_retriggers() - if check and check.repetitions then - check.repetitions = check.repetitions + old_repetitions - reps[i] = check - end - end - end - for i0, j in ipairs(reps) do - if (type(j) == "table") and j.repetitions and (j.repetitions > 0) then - for r = 1, j.repetitions do - card_eval_status_text(j.card, "jokers", nil, nil, nil, j) - local ggpn = G.GAME.probabilities.normal - if G.jokers.cards[i].ability.cry_rigged then - G.GAME.probabilities.normal = 1e9 - end - local o = obj:cry_scale_mod( - G.jokers.cards[i], - jkr, - orig_scale_scale, - true_base, - orig_scale_base, - new_scale_base - ) - if G.jokers.cards[i].ability.cry_rigged then - G.GAME.probabilities.normal = ggpn - end - if o then - if #dbl_info.scaler == 2 then - if - not ( - not jkr.ability[dbl_info.scaler[1]] - or not jkr.ability[dbl_info.scaler[1]][dbl_info.scaler[2]] - ) - then - jkr.ability[dbl_info.scaler[1]][dbl_info.scaler[2]] = o - orig_scale_scale = o - end - else - if jkr.ability[dbl_info.scaler[1]] then - jkr.ability[dbl_info.scaler[1]] = o - orig_scale_scale = o - end - end - card_eval_status_text( - G.jokers.cards[i], - "extra", - nil, - nil, - nil, - { message = localize("k_upgrade_ex") } - ) - end - end - end - end - end - end - end -end diff --git a/Cryptid/lib/content.lua b/Cryptid/lib/content.lua index e24ee09..b691479 100644 --- a/Cryptid/lib/content.lua +++ b/Cryptid/lib/content.lua @@ -15,11 +15,11 @@ SMODS.PokerHand({ l_chips = 50, l_mult = 1, example = { - { "S_A", true, "m_stone" }, - { "S_A", true, "m_stone" }, - { "S_A", true, "m_stone" }, - { "S_A", true, "m_stone" }, - { "S_A", true, "m_stone" }, + { "S_A", true, enhancement = "m_stone" }, + { "S_A", true, enhancement = "m_stone" }, + { "S_A", true, enhancement = "m_stone" }, + { "S_A", true, enhancement = "m_stone" }, + { "S_A", true, enhancement = "m_stone" }, }, atlas = "poker_hands", pos = { x = 0, y = 0 }, @@ -267,6 +267,68 @@ SMODS.PokerHand({ return end, }) + +SMODS.PokerHand({ + key = "None", + visible = false, + chips = 0, + mult = 0, + l_chips = 5, + l_mult = 0.5, + example = {}, + atlas = "poker_hands", + pos = { x = 0, y = 0 }, + evaluate = function(parts, hand) + if Cryptid.enabled("set_cry_poker_hand_stuff") ~= true or Cryptid.enabled("c_cry_nibiru") ~= true then --or Cryptid.enabled("c_cry_asteroidbelt") ~= true then + return {} + end + return { hand and #hand == 0 and G.GAME.hands["cry_None"].visible and {} or nil } + end, +}) + +SMODS.PokerHand({ + key = "Declare0", + visible = false, + chips = 0, + mult = 0, + l_chips = 0, + l_mult = 0, + example = {}, + atlas = "poker_hands", + pos = { x = 0, y = 0 }, + above_hand = "cry_UltPair", + order_offset = 1000, + evaluate = function(parts, hand) end, +}) +SMODS.PokerHand({ + key = "Declare1", + visible = false, + chips = 0, + mult = 0, + l_chips = 0, + l_mult = 0, + example = {}, + atlas = "poker_hands", + pos = { x = 0, y = 0 }, + above_hand = "cry_UltPair", + order_offset = 1001, + evaluate = function(parts, hand) end, +}) +SMODS.PokerHand({ + key = "Declare2", + visible = false, + chips = 0, + mult = 0, + l_chips = 0, + l_mult = 0, + example = {}, + atlas = "poker_hands", + pos = { x = 0, y = 0 }, + above_hand = "cry_UltPair", + order_offset = 1002, + evaluate = function(parts, hand) end, +}) + SMODS.Rarity({ key = "exotic", loc_txt = {}, @@ -312,6 +374,7 @@ SMODS.ConsumableType({ default = "c_cry_potion", can_stack = false, can_divide = false, + no_collection = true, }) -- Pool used by Food Jokers SMODS.ObjectType({ @@ -399,6 +462,14 @@ SMODS.Atlas({ Sprite(0, 0, G.CARD_W, G.CARD_H, G[self.atlas_table][self.key_noloc or self.key], { x = 5, y = 0 }) end, }) +SMODS.Sound({ + key = "forcetrigger", + path = "forcetrigger.ogg", +}) +SMODS.Sound({ + key = "demitrigger", + path = "demitrigger.ogg", +}) SMODS.Sound({ key = "meow1", path = "meow1.ogg", @@ -492,9 +563,17 @@ SMODS.Sound({ key = "music_big", path = "music_big.ogg", select_music_track = function() - return Cryptid_config.Cryptid + if G.GAME.cry_music_big then + return G.GAME.cry_music_big + end + if + Cryptid_config.Cryptid and Cryptid_config.Cryptid.big_music and to_big(G.GAME.round_scores["hand"].amt) > to_big(10) ^ 1000000 + then + G.GAME.cry_music_big = true + return true + end end, }) SMODS.Sound({ @@ -661,7 +740,7 @@ SMODS.UndiscoveredSprite({ key = "Code", atlas = "atlasnotjokers", path = "atlasnotjokers.png", - pos = { x = 9, y = 5 }, + pos = { x = 12, y = 6 }, px = 71, py = 95, }) @@ -681,6 +760,15 @@ SMODS.Atlas({ py = 34, frames = 21, }) +--splitting these up because like more than 20 on one atlas is a crime +SMODS.Atlas({ + key = "blinds_two", + atlas_table = "ANIMATION_ATLAS", + path = "bl_cry_two.png", + px = 34, + py = 34, + frames = 21, +}) SMODS.Atlas({ key = "nostalgia", atlas_table = "ANIMATION_ATLAS", @@ -702,3 +790,77 @@ SMODS.Atlas({ px = 73, py = 95, }) +SMODS.Atlas({ + key = "glowingSleeve", + path = "sleeve_cry_glowing.png", + px = 73, + py = 95, +}) +-- Scoring Calculation for The Tax +SMODS.Scoring_Calculation({ + key = "tax", + func = function(self, chips, mult, flames) + return math.floor(math.min(0.4 * G.GAME.blind.chips, chips * mult) + 0.5) + end, + replace_ui = function(self) + local aaa = 40 + local bbb = localize({ type = "variable", key = "tax_hand", vars = { aaa } })[1] + -- rebuild the ui to change colours and add text and stuff + -- SMODS made some stuff for this so that's kinda convienient ig + return { + n = G.UIT.R, + config = { minh = 1.2, align = "cm" }, + nodes = { + { + n = G.UIT.C, + config = { align = "cm" }, + nodes = { + { + n = G.UIT.R, + config = { align = "cm", minh = 1, padding = 0.1 }, + nodes = { + -- Chips box + { + n = G.UIT.C, + config = { align = "cm", id = "hand_chips_container" }, + nodes = { + SMODS.GUI.score_container({ + type = "chips", + text = "chip_text", + align = "cr", + colour = G.C.CRY_TAX_CHIPS, + }), + }, + }, + -- Operator thingy (Stays the same) + SMODS.GUI.operator(0.4), + -- Mult box + { + n = G.UIT.C, + config = { align = "cm", id = "hand_mult_container" }, + nodes = { + SMODS.GUI.score_container({ + type = "mult", + colour = G.C.CRY_TAX_MULT, + }), + }, + }, + }, + }, + -- Text + { + n = G.UIT.R, + config = { align = "cm" }, + nodes = { + { + n = G.UIT.T, + config = { text = bbb, scale = 0.25, colour = G.C.IMPORTANT }, + }, + }, + }, + }, + }, + }, + } + end, +}) diff --git a/Cryptid/lib/cross-mod.lua b/Cryptid/lib/cross-mod.lua index 5dc2e56..917c4fe 100644 --- a/Cryptid/lib/cross-mod.lua +++ b/Cryptid/lib/cross-mod.lua @@ -13,26 +13,28 @@ SMODS.Joker:take_ownership("green_joker", { and not context.blueprint and context.other_card == context.full_hand[#context.full_hand] then - local prev_mult = card.ability.mult - card.ability.mult = math.max(0, card.ability.mult - card.ability.extra) - if card.ability.mult ~= prev_mult then - return { - message = localize({ - type = "variable", - key = "a_mult_minus", - vars = { card.ability.extra }, - }), - colour = G.C.RED, - card = card, - } + if card.ability.mult ~= 0 then + SMODS.scale_card(card, { + ref_table = card.ability, + ref_value = "mult", + scalar_table = card.ability, + scalar_value = "extra", + operation = function(ref_table, ref_value, initial, change) + ref_table[ref_value] = math.max(0, initial - change) + end, + message_key = "a_mult_minus", + message_colour = G.C.RED, + }) end end if context.cardarea == G.jokers and context.before and not context.blueprint then - card.ability.mult = card.ability.mult + card.ability.extra - return { - card = card, - message = localize({ type = "variable", key = "a_mult", vars = { card.ability.extra } }), - } + SMODS.scale_card(card, { + ref_table = card.ability, + ref_value = "mult", + scalar_value = "extra", + message_key = "a_mult", + message_colour = G.C.RED, + }) end if context.joker_main then return { @@ -44,41 +46,6 @@ SMODS.Joker:take_ownership("green_joker", { loc_txt = {}, }, true) ---Top Gear from The World End with Jimbo has several conflicts with Cryptid items ---Namely, It overrides the edition that edition jokers spawn with, and doesn't work correctly with edition decks ---I'm taking ownership of this, overiding it, and making an implementaion that is compatible with Cryptid - ---Unrelated but kind of related side note: this prevents top gear from showing up in collection, not sure what's up with that ---Is it due to how TWEWJ is Coded? Is it an issue with Steamodded itself? Might be worth looking into, just sayin - -if (SMODS.Mods["TWEWY"] or {}).can_load then - SMODS.Joker:take_ownership("twewy_topGear", { - name = "Cry-topGear", - --Stop Top Gear's Old code from working by overriding these - add_to_deck = function(self, card, from_debuff) end, - remove_from_deck = function(self, card, from_debuff) end, - rarity = 3, - loc_txt = { - name = "Top Gear", - text = { - "All {C:blue}Common{C:attention} Jokers{}", - "are {C:dark_edition}Polychrome{}", - }, - }, - }) -end - ---Make Ortalab's Locked jokers not show up on Deck of Equilibrium and Antimatter Deck -if (SMODS.Mods["ortalab"] or {}).can_load then - for i = 1, 150 do - print(i) - SMODS.Joker:take_ownership("ortalab_temp_" .. i, { - name = "Cry-skibidi", - no_doe = true, - }) - end -end - --Requires Malverk Mod if (SMODS.Mods["malverk"] or {}).can_load then AltTexture({ @@ -117,9 +84,11 @@ if (SMODS.Mods["AntePreview"] or {}).can_load then big = get_new_boss() end local predictions = predict_hook() - if next(SMODS.find_card("j_cry_kittyprinter")) then - predictions.Small.tag = "tag_cry_cat" - predictions.Big.tag = "tag_cry_cat" + local s = Cryptid.get_next_tag("Small") + local b = Cryptid.get_next_tag("Big") + if s or b then + predictions.Small.tag = s or predictions.Small.tag + predictions.Big.tag = b or predictions.Big.tag end if G.GAME.modifiers.cry_no_tags then for _, pred in pairs(predictions) do @@ -140,3 +109,63 @@ if (SMODS.Mods["AntePreview"] or {}).can_load then return predictions end end + +--Designed to run if ran with is_suit overriding mods of higher priority (UnStable comes to first mind) +function Card:is_suit_force_enhancement(suit, bypass_debuff, flush_calc) + --Force suit to be suit X if specified in enhancement, only if not vampired + if Cryptid.cry_enhancement_has_specific_suit(self) and not self.vampired then + return suit == Cryptid.cry_enhancement_get_specific_suit(self) + end + local ref = self:is_suit(suit, bypass_debuff, flush_calc) + return ref +end + +-- === Cross mod access for Cryptid === -- +-- IcyEthics: Adding this section to collect functions that are intended to help other mods +-- interact with Cryptid's functionality in some way + +-- ://CLASS API +-- This function allows another mod to set up a name and alias that's accessible by the ://CLASS Code Card +-- It's also set up more generically so that other mods can access the same information +Cryptid.enhancement_alias_list = {} + +---@param list table +function Cryptid.load_enhancement_aliases(list) + for _enhancementkey, _listofaliases in pairs(list) do + Cryptid.enhancement_alias_list[_enhancementkey] = _listofaliases + end +end + +-- Acclimator Voucher API functions +-- This should allow other mods to set up their own tier 3 vouchers in the style of +-- the Tarot Acclimator voucher by setting up the voucher and just initializing +-- a call to this function in their initialization + +Cryptid.voucher_acclimator_data = {} + +---@param voucher_key string +---@param localization_key string +---@param ref_value string +---@param colour any +function Cryptid.setup_voucher_rate_adjuster(voucher_key, localization_key, ref_value, colour) + -- Necessary values: + -- Voucher key + -- localize key + -- ref value + -- colour + + if not voucher_key or not localization_key or not ref_value or not colour then + print("Cryptid.setup_voucher_rate_adjuster was improperly called") + end + + Cryptid.voucher_acclimator_data[#Cryptid.voucher_acclimator_data + 1] = { + voucher_key = voucher_key, + localization_key = localization_key, + ref_value = ref_value, + colour = colour, + } + print(Cryptid.voucher_acclimator_data[#Cryptid.voucher_acclimator_data]) +end + +Cryptid.setup_voucher_rate_adjuster("v_cry_tacclimator", "b_tarot_rate", "tarot", G.C.SECONDARY_SET.Tarot) +Cryptid.setup_voucher_rate_adjuster("v_cry_pacclimator", "b_planet_rate", "planet", G.C.SECONDARY_SET.Planet) diff --git a/Cryptid/lib/forcetrigger.lua b/Cryptid/lib/forcetrigger.lua new file mode 100644 index 0000000..622df8a --- /dev/null +++ b/Cryptid/lib/forcetrigger.lua @@ -0,0 +1,1332 @@ +-- everything demicolon needs (not really as simple anymore) +function Cryptid.demicolonGetTriggerable(card) + local n = { false, false } + if not card then + return n + end + if + Card.no(card, "demicoloncompat", true) + or Card.no(card, "demicolon_compat", true) + or Cryptid.forcetriggerVanillaCheck(card) + then + n[1] = true + else + n[1] = false + end + if card.ability.consumeable and Cryptid.forcetriggerConsumableCheck(card) then + n[1] = true + end + return n +end + +function Cryptid.forcetrigger(card, context) + if not card then + return {} + end + local results = {} + local check = Cryptid.forcetriggerVanillaCheck(card) + if not Talisman.config_file.disable_anims then + G.E_MANAGER:add_event(Event({ + trigger = "before", + func = function() + play_sound("cry_forcetrigger", 1, 0.6) + return true + end, + })) + end + if not check and card.ability.set == "Joker" then + local demicontext = Cryptid.deep_copy(context) + demicontext.forcetrigger = true + results = eval_card(card, demicontext) + demicontext = nil + elseif check and card.ability.set == "Joker" then + results = {} + results.jokers = {} + -- page 1 + if card.ability.name == "Joker" then + results = { jokers = { mult_mod = card.ability.mult, card = card } } + end + if card.ability.name == "Greedy Joker" then + results = { jokers = { mult_mod = card.ability.extra.s_mult, card = card } } + end + if card.ability.name == "Lusty Joker" then + results = { jokers = { mult_mod = card.ability.extra.s_mult, card = card } } + end + if card.ability.name == "Wrathful Joker" then + results = { jokers = { mult_mod = card.ability.extra.s_mult, card = card } } + end + if card.ability.name == "Gluttonous Joker" then + results = { jokers = { mult_mod = card.ability.extra.s_mult, card = card } } + end + if card.ability.name == "Jolly Joker" then + results = { jokers = { mult_mod = card.ability.t_mult, card = card } } + end + if card.ability.name == "Zany Joker" then + results = { jokers = { mult_mod = card.ability.t_mult, card = card } } + end + if card.ability.name == "Mad Joker" then + results = { jokers = { mult_mod = card.ability.t_mult, card = card } } + end + if card.ability.name == "Crazy Joker" then + results = { jokers = { mult_mod = card.ability.t_mult, card = card } } + end + if card.ability.name == "Droll Joker" then + results = { jokers = { mult_mod = card.ability.t_mult, card = card } } + end + if card.ability.name == "Sly Joker" then + results = { jokers = { chips = card.ability.t_chips, card = card } } + end + if card.ability.name == "Wily Joker" then + results = { jokers = { chips = card.ability.t_chips, card = card } } + end + if card.ability.name == "Clever Joker" then + results = { jokers = { chips = card.ability.t_chips, card = card } } + end + if card.ability.name == "Devious Joker" then + results = { jokers = { chips = card.ability.t_chips, card = card } } + end + if card.ability.name == "Crafty Joker" then + results = { jokers = { chips = card.ability.t_chips, card = card } } + end + -- page 2 + if card.ability.name == "Half Joker" then + results = { jokers = { mult_mod = card.ability.extra.mult, card = card } } + end + if card.ability.name == "Joker Stencil" then + results = { jokers = { Xmult_mod = card.ability.x_mult, card = card } } + end + -- if card.ability.name == "Four Fingers" then results = { jokers = { }, } end + -- if card.ability.name == "Mime" then results = { jokers = { }, } end + -- if card.ability.name == "Credit Card" then results = { jokers = { }, } end + if card.ability.name == "Ceremonial Dagger" then + local my_pos = nil + for i = 1, #G.jokers.cards do + if G.jokers.cards[i] == card then + my_pos = i + break + end + end + if + my_pos + and G.jokers.cards[my_pos + 1] + and not card.getting_sliced + and not SMODS.is_eternal(G.jokers.cards[my_pos + 1]) + and not G.jokers.cards[my_pos + 1].getting_sliced + then + local sliced_card = G.jokers.cards[my_pos + 1] + sliced_card.getting_sliced = true + G.GAME.joker_buffer = G.GAME.joker_buffer - 1 + G.E_MANAGER:add_event(Event({ + func = function() + G.GAME.joker_buffer = 0 + card:juice_up(0.8, 0.8) + sliced_card:start_dissolve({ HEX("57ecab") }, nil, 1.6) + play_sound("slice1", 0.96 + math.random() * 0.08) + return true + end, + })) + SMODS.scale_card(card, { + ref_table = card.ability, + ref_value = "mult", + scalar_table = { cost = sliced_card.sell_cost * 2 }, + scalar_value = "cost", + no_message = true, + }) + end + results = { jokers = { mult_mod = card.ability.mult, card = card } } + end + if card.ability.name == "Banner" then + results = { jokers = { chips = card.ability.extra, card = card } } + end + if card.ability.name == "Mystic Summit" then + results = { jokers = { mult_mod = card.ability.extra.mult, card = card } } + end + if card.ability.name == "Marble Joker" then + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.4, + func = function() + local front = pseudorandom_element(G.P_CARDS, pseudoseed("marb_fr")) + G.playing_card = (G.playing_card and G.playing_card + 1) or 1 + local card = Card( + G.play.T.x + G.play.T.w / 2, + G.play.T.y, + G.CARD_W, + G.CARD_H, + front, + G.P_CENTERS.m_stone, + { playing_card = G.playing_card } + ) + card:start_materialize({ G.C.SECONDARY_SET.Enhanced }) + G.deck:emplace(card) + table.insert(G.playing_cards, card) + return true + end, + })) + end + if card.ability.name == "Loyalty Card" then + results = { jokers = { Xmult_mod = card.ability.extra.Xmult, card = card } } + end + if card.ability.name == "8 Ball" then + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.4, + func = function() + local card = create_card("Tarot", G.consumeables, nil, nil, nil, nil, nil, "8ba") + card:add_to_deck() + G.consumeables:emplace(card) + G.GAME.consumeable_buffer = 0 + return true + end, + })) + end + if card.ability.name == "Misprint" then + results = { jokers = { mult_mod = card.ability.extra.max, card = card } } + end + -- if card.ability.name == "Dusk" then results = { jokers = { }, } end + if card.ability.name == "Raised Fist" then + results = { jokers = { mult_mod = 22, card = card } } + end + -- if card.ability.name == "Chaos the Clown" then results = { jokers = { }, } end + -- page 3 + if card.ability.name == "Fibonacci" then + results = { jokers = { mult_mod = card.ability.extra, card = card } } + end + if card.ability.name == "Steel Joker" then + results = { jokers = { Xmult_mod = (card.ability.extra + 1), card = card } } + end + if card.ability.name == "Scary Face" then + results = { jokers = { chips = card.ability.extra, card = card } } + end + if card.ability.name == "Abstract Joker" then + results = { jokers = { mult_mod = card.ability.extra, card = card } } + end + if card.ability.name == "Delayed Gratification" then + ease_dollars(card.ability.extra) + end + -- if card.ability.name == "Hack" then results = { jokers = { }, } end + -- if card.ability.name == "Pareidolia" then results = { jokers = { }, } end + if card.ability.name == "Gros Michel" then + G.E_MANAGER:add_event(Event({ + func = function() + play_sound("tarot1") + card.T.r = -0.2 + card:juice_up(0.3, 0.4) + card.states.drag.is = true + card.children.center.pinch.x = true + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.3, + blockable = false, + func = function() + G.jokers:remove_card(card) + card:remove() + card = nil + return true + end, + })) + return true + end, + })) + G.GAME.pool_flags.gros_michel_extinct = true + results = { jokers = { mult_mod = card.ability.extra.mult, card = card } } + end + if card.ability.name == "Even Steven" then + results = { jokers = { mult_mod = card.ability.extra, card = card } } + end + if card.ability.name == "Odd Todd" then + results = { jokers = { chips = card.ability.extra, card = card } } + end + if card.ability.name == "Scholar" then + results = { jokers = { chips = card.ability.extra.chips, mult_mod = card.ability.extra.mult, card = card } } + end + if card.ability.name == "Business Card" then + ease_dollars(2) + end + if card.ability.name == "Supernova" then + local hand = context.other_context and context.other_context.scoring_name or context.scoring_name + if hand then + results = { jokers = { mult_mod = G.GAME.hands[hand].played, card = card } } + end + end + if card.ability.name == "Ride The Bus" then + SMODS.scale_card(card, { + ref_table = card.ability, + ref_value = "mult", + scalar_value = "extra", + no_message = true, + }) + results = { jokers = { mult_mod = card.ability.mult, card = card } } + end + if card.ability.name == "Space Joker" then + if #G.hand.highlighted > 0 then + local text, disp_text = G.FUNCS.get_poker_hand_info(G.hand.highlighted) + update_hand_text({ sound = "button", volume = 0.7, pitch = 0.8, delay = 0.3 }, { + handname = localize(text, "poker_hands"), + chips = G.GAME.hands[text].chips, + mult = G.GAME.hands[text].mult, + level = G.GAME.hands[text].level, + }) + level_up_hand(card, text, nil, 1) + update_hand_text( + { sound = "button", volume = 0.7, pitch = 1.1, delay = 0 }, + { mult = 0, chips = 0, handname = "", level = "" } + ) + elseif context.scoring_name then + level_up_hand(card, context.scoring_name) + end + end + -- page 4 + if card.ability.name == "Egg" then + SMODS.scale_card(card, { + ref_table = card.ability, + ref_value = "extra_value", + scalar_value = "extra", + no_message = true, + }) + card:set_cost() + end + if card.ability.name == "Burglar" then + G.E_MANAGER:add_event(Event({ + func = function() + ease_discard(-G.GAME.current_round.discards_left, nil, true) + ease_hands_played(card.ability.extra) + return true + end, + })) + end + if card.ability.name == "Blackboard" then + results = { jokers = { Xmult_mod = card.ability.extra, card = card } } + end + if card.ability.name == "Runner" then + SMODS.scale_card(card, { + ref_table = card.ability, + ref_value = "chips", + scalar_value = "chip_mod", + no_message = true, + }) + results = { jokers = { chips = card.ability.extra.chips, card = card } } + end + if card.ability.name == "Ice Cream" then + SMODS.scale_card(card, { + ref_table = card.ability, + ref_value = "chips", + scalar_value = "chip_mod", + operation = "-", + no_message = true, + }) + results = { jokers = { chips = card.ability.extra.chips, card = card } } + if card.ability.extra.chips - card.ability.extra.chip_mod <= 0 then + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.4, + func = function() + play_sound("tarot1") + card.T.r = -0.2 + card:juice_up(0.3, 0.4) + card.states.drag.is = true + card.children.center.pinch.x = true + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.3, + blockable = false, + func = function() + G.jokers:remove_card(card) + card:remove() + card = nil + return true + end, + })) + return true + end, + })) + end + end + if card.ability.name == "DNA" and context.full_hand then + G.playing_card = (G.playing_card and G.playing_card + 1) or 1 + local _card = copy_card(context.full_hand[1], nil, nil, G.playing_card) + _card:add_to_deck() + G.deck.config.card_limit = G.deck.config.card_limit + 1 + table.insert(G.playing_cards, _card) + G.hand:emplace(_card) + _card.states.visible = nil + + G.E_MANAGER:add_event(Event({ + func = function() + _card:start_materialize() + return true + end, + })) + end + -- if card.ability.name == "Splash" then results = { jokers = { }, } end + if card.ability.name == "Blue Joker" then + results = { jokers = { chips = card.ability.extra, card = card } } + end + if card.ability.name == "Sixth Sense" then + G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1 + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.4, + func = function() + local card = create_card("Spectral", G.consumeables, nil, nil, nil, nil, nil, "sixth") + card:add_to_deck() + G.consumeables:emplace(card) + G.GAME.consumeable_buffer = 0 + return true + end, + })) + end + if card.ability.name == "Constellation" then + SMODS.scale_card(card, { + ref_table = card.ability, + ref_value = "x_mult", + scalar_value = "extra", + no_message = true, + }) + results = { jokers = { Xmult_mod = card.ability.x_mult, card = card } } + end + -- if card.ability.name == "Hiker" then results = { jokers = { }, } end + if card.ability.name == "Faceless Joker" then + ease_dollars(card.ability.extra.dollars) + end + if card.ability.name == "Green Joker" then + results = { jokers = { mult_mod = card.ability.mult, card = card } } + end + if card.ability.name == "Superposition" then + G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1 + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.4, + func = function() + local card = create_card("Tarot", G.consumeables, nil, nil, nil, nil, nil, "sup") + card:add_to_deck() + G.consumeables:emplace(card) + G.GAME.consumeable_buffer = 0 + return true + end, + })) + end + if card.ability.name == "To Do List" then + ease_dollars(card.ability.extra.dollars) + end + -- page 5 + if card.ability.name == "Cavendish" then + results = { jokers = { Xmult_mod = card.ability.extra.Xmult, card = card } } + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.4, + func = function() + play_sound("tarot1") + card.T.r = -0.2 + card:juice_up(0.3, 0.4) + card.states.drag.is = true + card.children.center.pinch.x = true + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.3, + blockable = false, + func = function() + G.jokers:remove_card(card) + card:remove() + card = nil + return true + end, + })) + return true + end, + })) + end + if card.ability.name == "Card Sharp" then + results = { jokers = { Xmult_mod = card.ability.extra.Xmult, card = card } } + end + if card.ability.name == "Red Card" then + SMODS.scale_card(card, { + ref_table = card.ability, + ref_value = "mult", + scalar_value = "extra", + no_message = true, + }) + results = { jokers = { mult_mod = card.ability.mult, card = card } } + end + if card.ability.name == "Madness" then + local destructable_jokers = {} + for i = 1, #G.jokers.cards do + if + G.jokers.cards[i] ~= card + and not SMODS.is_eternal(G.jokers.cards[i]) + and not G.jokers.cards[i].getting_sliced + then + destructable_jokers[#destructable_jokers + 1] = G.jokers.cards[i] + end + end + local joker_to_destroy = #destructable_jokers > 0 + and pseudorandom_element(destructable_jokers, pseudoseed("madness")) + or nil + + if joker_to_destroy and not card.getting_sliced then + joker_to_destroy.getting_sliced = true + G.E_MANAGER:add_event(Event({ + func = function() + card:juice_up(0.8, 0.8) + joker_to_destroy:start_dissolve({ G.C.RED }, nil, 1.6) + return true + end, + })) + end + SMODS.scale_card(card, { + ref_table = card.ability, + ref_value = "x_mult", + scalar_value = "extra", + no_message = true, + }) + results = { jokers = { Xmult_mod = card.ability.x_mult, card = card } } + end + if card.ability.name == "Square Joker" then + card.ability.extra.chips = card.ability.extra.chips + card.ability.extra.chip_mod + results = { jokers = { chips = card.ability.extra.chips, card = card } } + end + if card.ability.name == "Seance" then + G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1 + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.4, + func = function() + local card = create_card("Spectral", G.consumeables, nil, nil, nil, nil, nil, "sea") + card:add_to_deck() + G.consumeables:emplace(card) + G.GAME.consumeable_buffer = 0 + return true + end, + })) + end + if card.ability.name == "Riff-raff" then + local jokers_to_create = math.min(2, G.jokers.config.card_limit - (#G.jokers.cards + G.GAME.joker_buffer)) + G.GAME.joker_buffer = G.GAME.joker_buffer + jokers_to_create + G.E_MANAGER:add_event(Event({ + func = function() + for i = 1, jokers_to_create do + local card = create_card("Joker", G.jokers, nil, 0, nil, nil, nil, "rif") + card:add_to_deck() + G.jokers:emplace(card) + card:start_materialize() + G.GAME.joker_buffer = 0 + end + return true + end, + })) + end + if card.ability.name == "Vampire" then + if context.scoring_hand and #context.scoring_hand > 0 then + for k, v in ipairs(context.scoring_hand) do + if v.config.center ~= G.P_CENTERS.c_base and not v.debuff and not v.vampired then + enhanced[#enhanced + 1] = v + v.vampired = true + v:set_ability(G.P_CENTERS.c_base, nil, true) + end + v.vampired = nil + end + elseif G and G.hand and #G.hand.highlighted > 0 then + for k, v in ipairs(G.hand.highlighted) do + if v.config.center ~= G.P_CENTERS.c_base and not v.debuff and not v.vampired then + enhanced[#enhanced + 1] = v + v.vampired = true + v:set_ability(G.P_CENTERS.c_base, nil, true) + end + v.vampired = nil + end + end + SMODS.scale_card(card, { + ref_table = card.ability, + ref_value = "x_mult", + scalar_value = "extra", + no_message = true, + }) + results = { jokers = { Xmult_mod = card.ability.x_mult, card = card } } + end + -- if card.ability.name == "Shortcut" then results = { jokers = { } } end + if card.ability.name == "Hologram" then + SMODS.scale_card(card, { + ref_table = card.ability, + ref_value = "x_mult", + scalar_value = "extra", + no_message = true, + }) + results = { jokers = { Xmult_mod = card.ability.x_mult, card = card } } + end + if card.ability.name == "Vagabond" then + G.GAME.consumeable_buffer = G.GAME.consumeable_buffer + 1 + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.4, + func = function() + local card = create_card("Tarot", G.consumeables, nil, nil, nil, nil, nil, "vag") + card:add_to_deck() + G.consumeables:emplace(card) + G.GAME.consumeable_buffer = 0 + return true + end, + })) + end + if card.ability.name == "Baron" then + results = { jokers = { Xmult_mod = card.ability.extra, card = card } } + end + if card.ability.name == "Cloud 9" then + if card.ability.nine_tally then + ease_dollars(card.ability.extra * card.ability.nine_tally) + else + ease_dollars(card.ability.extra) + end + end + if card.ability.name == "Rocket" then + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "dollars", + scalar_value = "increase", + no_message = true, + }) + ease_dollars(card.ability.extra.dollars) + end + if card.ability.name == "Obelisk" then -- Sobelisk + SMODS.scale_card(card, { + ref_table = card.ability, + ref_value = "x_mult", + scalar_value = "extra", + no_message = true, + }) + results = { jokers = { Xmult_mod = card.ability.x_mult, card = card } } + end + -- page 6 + if card.ability.name == "Midas Mask" then + if context.scoring_hand then + for k, v in ipairs(context.scoring_hand) do + if v:is_face() then + v:set_ability(G.P_CENTERS.m_gold, nil, true) + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.4, + func = function() + v:juice_up() + return true + end, + })) + end + end + elseif G and G.hand and #G.hand.highlighted > 0 then + for k, v in ipairs(G.hand.highlighted) do + if v:is_face() then + v:set_ability(G.P_CENTERS.m_gold, nil, true) + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.4, + func = function() + v:juice_up() + return true + end, + })) + end + end + end + end + if card.ability.name == "Luchador" then + if G.GAME.blind and ((not G.GAME.blind.disabled) and (G.GAME.blind:get_type() == "Boss")) then + G.GAME.blind:disable() + end + end + if card.ability.name == "Photograph" then + results = { jokers = { Xmult_mod = card.ability.extra, card = card } } + end + if card.ability.name == "Gift Card" then + for k, v in ipairs(G.jokers.cards) do + if v.set_cost then + v.ability.extra_value = (v.ability.extra_value or 0) + card.ability.extra + v:set_cost() + end + end + for k, v in ipairs(G.consumeables.cards) do + if v.set_cost then + v.ability.extra_value = (v.ability.extra_value or 0) + card.ability.extra + v:set_cost() + end + end + end + if card.ability.name == "Turtle Bean" then + G.hand:change_size(-card.ability.extra.h_size) + SMODS.scale_card(card, { + ref_table = card.ability.extra, + ref_value = "h_size", + scalar_value = "h_mod", + operation = "-", + no_message = true, + }) + G.hand:change_size(card.ability.extra.h_size) + end + if card.ability.name == "Erosion" then + results = { + jokers = { mult_mod = card.ability.extra * (G.GAME.starting_deck_size - #G.playing_cards), card = card }, + } + end + if card.ability.name == "Reserved Parking" then + ease_dollars(card.ability.extra.dollars) + end + if card.ability.name == "Mail-In Rebate" then + ease_dollars(card.ability.extra) + end + -- if card.ability.name == "To the Moon" then results = { jokers = { } } end + if card.ability.name == "Hallucination" then + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.4, + func = function() + local card = create_card("Tarot", G.consumeables, nil, nil, nil, nil, nil, "hal") + card:add_to_deck() + G.consumeables:emplace(card) + G.GAME.consumeable_buffer = 0 + return true + end, + })) + end + if card.ability.name == "Fortune Teller" then + results = { jokers = { mult_mod = G.GAME.consumeable_usage_total.tarot or 1, card = card } } + end + if card.ability.name == "Juggler" then + G.hand:change_size(card.ability.h_size) + end + if card.ability.name == "Drunkard" then + ease_discard(card.ability.d_size) + end + if card.ability.name == "Stone Joker" then + results = { jokers = { chips = card.ability.extra * card.ability.stone_tally, card = card } } + end + if card.ability.name == "Golden Joker" then + ease_dollars(card.ability.extra) + end + -- page 7 + if card.ability.name == "Lucky Cat" then + card.ability.x_mult = card.ability.x_mult + card.ability.extra + results = { jokers = { Xmult_mod = card.ability.x_mult, card = card } } + end + if card.ability.name == "Baseball Card" then + results = { jokers = { Xmult_mod = card.ability.extra, card = card } } + end + if card.ability.name == "Bull" then + results = { + jokers = { + chips = card.ability.extra * math.max(0, (G.GAME.dollars + (G.GAME.dollar_buffer or 0))), + card = card, + }, + } + end + if card.ability.name == "Diet Cola" then + G.E_MANAGER:add_event(Event({ + func = function() + add_tag(Tag("tag_double")) + play_sound("generic1", 0.9 + math.random() * 0.1, 0.8) + play_sound("holo1", 1.2 + math.random() * 0.1, 0.4) + return true + end, + })) + end + if card.ability.name == "Trading Card" then + ease_dollars(card.ability.extra) + end + if card.ability.name == "Flash Card" then + SMODS.scale_card(card, { + ref_table = card.ability, + ref_value = "mult", + scalar_value = "extra", + no_message = true, + }) + results = { jokers = { mult_mod = card.ability.mult, card = card } } + end + if card.ability.name == "Popcorn" then + SMODS.scale_card(card, { + ref_table = card.ability, + ref_value = "mult", + scalar_value = "extra", + operation = "-", + no_message = true, + }) + results = { jokers = { mult_mod = card.ability.mult, card = card } } + end + if card.ability.name == "Spare Trousers" then + SMODS.scale_card(card, { + ref_table = card.ability, + ref_value = "mult", + scalar_value = "extra", + no_message = true, + }) + results = { jokers = { mult_mod = card.ability.mult, card = card } } + end + if card.ability.name == "Ancient Joker" then + results = { jokers = { Xmult_mod = card.ability.extra, card = card } } + end + if card.ability.name == "Ramen" then + SMODS.scale_card(card, { + ref_table = card.ability, + ref_value = "x_mult", + scalar_value = "extra", + operation = "-", + no_message = true, + }) + results = { jokers = { Xmult_mod = card.ability.x_mult, card = card } } + end + if card.ability.name == "Walkie Talkie" then + results = { jokers = { mult_mod = card.ability.extra.mult, chips = card.ability.extra.chips, card = card } } + end + -- if card.ability.name == "Seltzer" then results = { jokers = { } } end + if card.ability.name == "Castle" then + SMODS.scale_card(card, { + ref_table = card.ability, + ref_value = "chips", + scalar_value = "chip_mod", + no_message = true, + }) + results = { jokers = { chips = card.ability.extra.chips, card = card } } + end + if card.ability.name == "Smiley Face" then + results = { jokers = { mult_mod = card.ability.extra, card = card } } + end + if card.ability.name == "Campfire" then + SMODS.scale_card(card, { + ref_table = card.ability, + ref_value = "x_mult", + scalar_value = "extra", + no_message = true, + }) + results = { jokers = { Xmult_mod = card.ability.x_mult, card = card } } + end + -- page 8 + if card.ability.name == "Golden Ticket" then + ease_dollars(card.ability.extra) + end + -- if card.ability.name == "Mr Bones" then results = { jokers = { } } end + if card.ability.name == "Acrobat" then + results = { jokers = { Xmult_mod = card.ability.extra, card = card } } + end + -- if card.ability.name == "Sock and Buskin" then results = { jokers = { } } end + if card.ability.name == "Swashbuckler" then + results = { jokers = { mult_mod = card.ability.mult, card = card } } + end + if card.ability.name == "Troubadour" then + G.hand:change_size(card.ability.extra.h_size) + G.GAME.round_resets.hands = G.GAME.round_resets.hands + card.ability.extra.h_plays + end + if card.ability.name == "Certificate" then + local _card = create_playing_card({ + front = pseudorandom_element(G.P_CARDS, pseudoseed("cert_fr")), + center = G.P_CENTERS.c_base, + }, G.discard, true, nil, { G.C.SECONDARY_SET.Enhanced }, true) + _card:set_seal(SMODS.poll_seal({ guaranteed = true, type_key = "certsl" })) + G.E_MANAGER:add_event(Event({ + func = function() + G.hand:emplace(_card) + _card:start_materialize() + G.GAME.blind:debuff_card(_card) + G.hand:sort() + return true + end, + })) + end + -- if card.ability.name == "Smeared Joker" then results = { jokers = { } } end + if card.ability.name == "Throwback" then + results = { jokers = { Xmult_mod = card.ability.x_mult, card = card } } + end + -- if card.ability.name == "Hanging Chad" then results = { jokers = { } } end + if card.ability.name == "Rough Gem" then + ease_dollars(card.ability.extra) + end + if card.ability.name == "Bloodstone" then + results = { jokers = { Xmult_mod = card.ability.extra.Xmult, card = card } } + end + if card.ability.name == "Arrowhead" then + results = { jokers = { chips = card.ability.extra, card = card } } + end + if card.ability.name == "Onyx Agate" then + results = { jokers = { mult_mod = card.ability.extra, card = card } } + end + if card.ability.name == "Glass Joker" then + SMODS.scale_card(card, { + ref_table = card.ability, + ref_value = "x_mult", + scalar_value = "extra", + no_message = true, + }) + results = { jokers = { Xmult_mod = card.ability.x_mult, card = card } } + end + -- page 9 + -- if card.ability.name == "Showman" then results = { jokers = { } } end + if card.ability.name == "Flower Pot" then + results = { jokers = { Xmult_mod = card.ability.extra, card = card } } + end + -- if card.ability.name == "Blueprint" then results = { jokers = { } } end + if card.ability.name == "Wee Joker" then + SMODS.scale_card(card, { + ref_table = card.ability, + ref_value = "chips", + scalar_value = "chip_mod", + no_message = true, + }) + results = { jokers = { chips = card.ability.extra.chips, card = card } } + end + if card.ability.name == "Merry Andy" then + ease_discard(card.ability.d_size) + G.hand:change_size(card.ability.h_size) + end + -- if card.ability.name == "Oops! All 6s" then results = { jokers = { } } end + if card.ability.name == "The Idol" then + results = { jokers = { Xmult_mod = card.ability.extra, card = card } } + end + if card.ability.name == "Seeing Double" then + results = { jokers = { Xmult_mod = card.ability.extra, card = card } } + end + if card.ability.name == "Matador" then + ease_dollars(card.ability.extra) + end + if card.ability.name == "Hit The Road" then + SMODS.scale_card(card, { + ref_table = card.ability, + ref_value = "x_mult", + scalar_value = "extra", + no_message = true, + }) + results = { jokers = { Xmult_mod = card.ability.x_mult, card = card } } + end + if card.ability.name == "The Duo" then + results = { jokers = { Xmult_mod = card.ability.x_mult, card = card } } + end + if card.ability.name == "The Trio" then + results = { jokers = { Xmult_mod = card.ability.x_mult, card = card } } + end + if card.ability.name == "The Family" then + results = { jokers = { Xmult_mod = card.ability.x_mult, card = card } } + end + if card.ability.name == "The Order" then + results = { jokers = { Xmult_mod = card.ability.x_mult, card = card } } + end + if card.ability.name == "The Tribe" then + results = { jokers = { Xmult_mod = card.ability.x_mult, card = card } } + end + -- page 10 + if card.ability.name == "Stuntman" then + G.hand:change_size(-card.ability.extra.h_size) + results = { jokers = { chips = card.ability.extra.chip_mod, card = card } } + end + if card.ability.name == "Invisible Joker" then + card.ability.invis_rounds = card.ability.invis_rounds + 1 + local jokers = {} + for i = 1, #G.jokers.cards do + if G.jokers.cards[i] ~= card then + jokers[#jokers + 1] = G.jokers.cards[i] + end + end + if #jokers > 0 then + G.E_MANAGER:add_event(Event({ + func = function() + local chosen_joker = pseudorandom_element(jokers, pseudoseed("invisible")) + local card = copy_card( + chosen_joker, + nil, + nil, + nil, + chosen_joker.edition and chosen_joker.edition.negative + ) + if card.ability.invis_rounds then + card.ability.invis_rounds = 0 + end + card:add_to_deck() + G.jokers:emplace(card) + return true + end, + })) + end + end + -- if card.ability.name == "Brainstorm" then results = { jokers = { } } end + if card.ability.name == "Satellite" then + local planets_used = 0 + for k, v in pairs(G.GAME.consumeable_usage) do + if v.set == "Planet" then + planets_used = planets_used + 1 + end + end + ease_dollars(card.ability.extra * planets_used or 1) + end + if card.ability.name == "Shoot The Moon" then + results = { jokers = { mult_mod = 13, card = card } } + end + if card.ability.name == "Driver's License" then + results = { jokers = { Xmult_mod = card.ability.extra, card = card } } + end + if card.ability.name == "Cartomancer" then + G.E_MANAGER:add_event(Event({ + func = function() + local card = create_card("Tarot", G.consumeables, nil, nil, nil, nil, nil, "car") + card:add_to_deck() + G.consumeables:emplace(card) + G.GAME.consumeable_buffer = 0 + return true + end, + })) + end + -- if card.ability.name == "Astronomer" then results = { jokers = { } } end + if card.ability.name == "Burnt Joker" then + if #G.hand.highlighted > 0 then + local text, disp_text = G.FUNCS.get_poker_hand_info(G.hand.highlighted) + update_hand_text({ sound = "button", volume = 0.7, pitch = 0.8, delay = 0.3 }, { + handname = localize(text, "poker_hands"), + chips = G.GAME.hands[text].chips, + mult = G.GAME.hands[text].mult, + level = G.GAME.hands[text].level, + }) + level_up_hand(card, text, nil, 1) + update_hand_text( + { sound = "button", volume = 0.7, pitch = 1.1, delay = 0 }, + { mult = 0, chips = 0, handname = "", level = "" } + ) + elseif context.scoring_name then + level_up_hand(card, context.scoring_name) + end + end + if card.ability.name == "Bootstraps" then + results = { + jokers = { + mult_mod = card.ability.mult + * math.floor((G.GAME.dollars + (G.GAME.dollar_buffer or 0)) / card.ability.extra.dollars), + card = card, + }, + } + end + if card.ability.name == "Caino" then + SMODS.scale_card(card, { + ref_table = card.ability, + ref_value = "x_mult", + scalar_value = "extra", + no_message = true, + }) + results = { jokers = { Xmult_mod = card.ability.caino_xmult, card = card } } + end + if card.ability.name == "Triboulet" then + results = { jokers = { Xmult_mod = card.ability.extra, card = card } } + end + if card.ability.name == "Yorick" then + SMODS.scale_card(card, { + ref_table = card.ability, + ref_value = "x_mult", + scalar_value = "extra", + no_message = true, + }) + results = { jokers = { Xmult_mod = card.ability.x_mult, card = card } } + end + if card.ability.name == "Chicot" then + if G.GAME.blind and G.GAME.blind:get_type() == "Boss" then + G.GAME.blind:disable() + end + end + if card.ability.name == "Perkeo" then + local eligibleJokers = {} + for i = 1, #G.consumeables.cards do + if G.consumeables.cards[i].ability.consumeable then + eligibleJokers[#eligibleJokers + 1] = G.consumeables.cards[i] + end + end + if #eligibleJokers > 0 then + G.E_MANAGER:add_event(Event({ + func = function() + local card = copy_card(pseudorandom_element(eligibleJokers, pseudoseed("perkeo")), nil) + card:set_edition({ negative = true }, true) + card:add_to_deck() + G.consumeables:emplace(card) + return true + end, + })) + end + end + if card.ability.name == "Perkeo (Incantation)" then + if G.consumeables.cards[1] then + G.E_MANAGER:add_event(Event({ + func = function() + local total, checked, center = 0, 0, nil + for i = 1, #G.consumeables.cards do + total = total + (G.consumeables.cards[i]:getQty()) + end + local poll = pseudorandom(pseudoseed("perkeo")) * total + for i = 1, #G.consumeables.cards do + checked = checked + (G.consumeables.cards[i]:getQty()) + if checked >= poll then + center = G.consumeables.cards[i] + break + end + end + local _card = copy_card(center, nil) + _card:set_edition({ negative = true }, true) + _card:add_to_deck() + G.consumeables:emplace(_card) + return true + end, + })) + end + end + elseif card.ability.consumeable and Cryptid.forcetriggerConsumableCheck(card) then + G.cry_force_use = true + if + (card.ability.consumeable.max_highlighted or card.ability.name == "Aura") + and not card.config.center.force_use + --and not card.config.center.force_use + then --Cards that require cards in hand to be selected + local _cards = {} + local targets = {} + + --Get all cards that we can target + for k, v in ipairs(G.hand.cards) do + if + not ((card.ability.name == "Aura") and (v.edition or v.will_be_editioned)) + and not v.will_be_destroyed + then + _cards[#_cards + 1] = v + end + end + + local highlight_count = to_number(math.min(#_cards, card.ability.consumeable.max_highlighted or 1)) + + if highlight_count > 0 then + --Choose random targets for consumable + for i = 1, highlight_count do + local selected_card, card_key = pseudorandom_element(_cards, pseudoseed("forcehighlight")) + if card.ability.name == "Aura" then + selected_card.will_be_editioned = true + end + if card.ability.name == "The Hanged Man" then + selected_card.will_be_destroyed = true + end + targets[#targets + 1] = table.remove(_cards, card_key) + + --Dodgy way of doing this + --Basically we need to highlight the cards temporarily to ensure events are created correctly + G.hand:add_to_highlighted(selected_card, true) + end + + G.E_MANAGER:add_event(Event({ + func = function() + for _, v in ipairs(targets) do + G.hand:add_to_highlighted(v, true) + v.will_be_editioned = nil + v.will_be_destroyed = nil + play_sound("card1", 1) + end + return true + end, + })) + + card:use_consumeable() + + G.E_MANAGER:add_event(Event({ + func = function() + G.hand:unhighlight_all() + return true + end, + })) + + --Unhighlight once events are created + G.hand:unhighlight_all() + end + else + -- Copy rigged code to guarantee WoF and Planet.lua + + local ggpn = G.GAME.probabilities.normal + G.GAME.probabilities.normal = 1e9 + + if not card.config.center.force_use then + card:use_consumeable() + else + card.config.center:force_use(card, card.area) + end + + G.GAME.probabilities.normal = ggpn + end + G.cry_force_use = nil + end + return results +end + +function Cryptid.forcetriggerVanillaCheck(card) + if not card then + return false + end + local compatvanilla = { + "Joker", + "Greedy Joker", + "Lusty Joker", + "Wrathful Joker", + "Gluttonous Joker", + "Jolly Joker", + "Zany Joker", + "Mad Joker", + "Crazy Joker", + "Droll Joker", + "Sly Joker", + "Wily Joker", + "Clever Joker", + "Devious Joker", + "Crafty Joker", + "Half Joker", + "Joker Stencil", + -- "Four Fingers", + -- "Mime", + -- "Credit Card", + "Ceremonial Dagger", + "Banner", + "Mystic Summit", + "Marble Joker", + "Loyalty Card", + "8 Ball", + "Misprint", + -- "Dusk", + "Raised Fist", + -- "Chaos the Clown", + "Fibonacci", + "Steel Joker", + "Scary Face", + "Abstract Joker", + "Delayed Gratification", + -- "Hack", + -- "Pareidolia", + "Gros Michel", + "Even Steven", + "Odd Todd", + "Scholar", + "Business Card", + "Supernova", + "Ride the Bus", + "Space Joker", + "Egg", + "Burglar", + "Blackboard", + "Runner", + "Ice Cream", + "DNA", + -- "Splash", + "Blue Joker", + "Sixth Sense", + "Constellation", + "Hiker", + "Faceless Joker", + "Green Joker", + "Superposition", + "To Do List", + "Cavendish", + "Card Sharp", + "Red Card", + "Madness", + "Square Joker", + "Seance", + "Riff-Raff", + "Vampire", + -- "Shortcut", + "Hologram", + "Vagabond", + "Baron", + "Cloud 9", + "Rocket", + "Obelisk", + "Midas Mask", + "Luchador", + "Photograph", + "Gift Card", + "Turtle Bean", + "Erosion", + "Reserved Parking", + "Mail-In Rebate", + -- "To the Moon", + "Hallucination", + "Fortune Teller", + "Juggler", + "Drunkard", + "Stone Joker", + "Golden Joker", + "Lucky Cat", + "Baseball Card", + "Bull", + "Diet Cola", + "Trading Card", + "Flash Card", + "Popcorn", + "Spare Trousers", + "Ancient Joker", + "Ramen", + "Walkie Talkie", + -- "Seltzer", + "Castle", + "Smiley Face", + "Campfire", + "Golden Ticket", + -- "Mr. Bones", + "Acrobat", + -- "Sock and Buskin", + "Swashbuckler", + "Troubadour", + "Certificate", + -- "Smeared Joker", + "Throwback", + -- "Hanging Chad", + "Rough Gem", + "Bloodstone", + "Arrowhead", + "Onyx Agate", + "Glass Joker", + -- "Showman", + "Flower Pot", + -- "Blueprint", + "Wee Joker", + "Merry Andy", + -- "Oops! All 6s", + "The Idol", + "Seeing Double", + "Matador", + "Hit the Road", + "The Duo", + "The Trio", + "The Family", + "The Order", + "The Tribe", + "Stuntman", + "Invisible Joker", + -- "Brainstorm", + "Satellite", + "Shoot the Moon", + "Driver's License", + "Cartomancer", + -- "Astronomer", + "Burnt Joker", + "Bootstraps", + "Caino", + "Triboulet", + "Yorick", + "Chicot", + "Perkeo", + "Perkeo (Incantation)", + } + for i = 1, #compatvanilla do + if card.ability.name == compatvanilla[i] then + return true + end + end + return false +end + +function Cryptid.forcetriggerConsumableCheck(card) + if not card then + return false + end + local banned = { + "cry-Exploit", + --"cry-Merge", + "cry-Divide", + "cry-Delete", + "cry-Pointer", + } + for i = 1, #banned do + if card.ability.name == banned[i] then + return false + end + end + return card.config.center.demicoloncompat or not card.config.center.original_mod +end diff --git a/Cryptid/lib/gameset.lua b/Cryptid/lib/gameset.lua index 8b02f75..6ec4009 100644 --- a/Cryptid/lib/gameset.lua +++ b/Cryptid/lib/gameset.lua @@ -31,10 +31,6 @@ function Game:update(dt) end G.FUNCS.cry_intro_controller = function() - if Jen then - G.PROFILES[G.SETTINGS.profile].cry_intro_complete = true - G.PROFILES[G.SETTINGS.profile].cry_gameset = "madness" - end G.PROFILES[G.SETTINGS.profile].cry_intro_progress = G.PROFILES[G.SETTINGS.profile].cry_intro_progress or { state = "start", @@ -188,7 +184,7 @@ G.FUNCS.cry_intro_part = function(_part) --TODO: localize G.modestBtn = create_UIBox_character_button_with_sprite({ sprite = modestSprite, - button = "Modest", + button = localize("cry_gameset_modest"), id = "modest", func = "cry_modest", colour = G.C.GREEN, @@ -196,7 +192,7 @@ G.FUNCS.cry_intro_part = function(_part) }) G.mainlineBtn = create_UIBox_character_button_with_sprite({ sprite = mainlineSprite, - button = "Mainline", + button = localize("cry_gameset_mainline"), id = "mainline", func = "cry_mainline", colour = G.C.RED, @@ -204,7 +200,7 @@ G.FUNCS.cry_intro_part = function(_part) }) G.madnessBtn = create_UIBox_character_button_with_sprite({ sprite = madnessSprite, - button = "Madness", + button = localize("cry_gameset_madness"), id = "madness", func = "cry_madness", colour = G.C.CRY_EXOTIC, @@ -547,9 +543,6 @@ end -- designed to work on any object type function Cryptid.gameset(card, center) - if Jen then - return "madness" - end if not center then if not card then return G.PROFILES[G.SETTINGS.profile].cry_gameset or "mainline" @@ -569,7 +562,9 @@ function Cryptid.gameset(card, center) if center.tag and center.tag.key then --dumb fix for tags center = center.tag else - print("Could not find key for center: " .. tprint(center)) + if false then + print("Could not find key for center: " .. tprint(center)) + end return G.PROFILES[G.SETTINGS.profile].cry_gameset or "mainline" end end @@ -602,6 +597,11 @@ function Card:set_ability(center, y, z) if not center then return end + -- Addition by IcyEthics to make compatible with strings used on set_ability. Copied directly from the smods set_ability implementation + if type(center) == "string" then + assert(G.P_CENTERS[center], ('Could not find center "%s"'):format(center)) + center = G.P_CENTERS[center] + end if not center.config then center.config = {} --crashproofing end @@ -633,15 +633,19 @@ function Card:set_ability(center, y, z) end end ---open gameset config UI when clicking on a card in the Cryptid collection ---disable this functionality for Jen's Almanac -if not Jen then +-- open gameset config UI when clicking on a card in the Cryptid collection +-- can be disabled in config +if Cryptid_config.gameset_toggle then local ccl = Card.click function Card:click() ccl(self) if G.your_collection then for k, v in pairs(G.your_collection) do - if self.area == v and G.ACTIVE_MOD_UI and G.ACTIVE_MOD_UI.id == "Cryptid" then + if + self.area == v + and G.ACTIVE_MOD_UI + and (Cryptid.mod_gameset_whitelist[G.ACTIVE_MOD_UI.id] or G.ACTIVE_MOD_UI.id == "Cryptid") + then if not self.config.center or self.config.center and self.config.center.set == "Default" then --make a fake center local old_force_gameset = self.config.center and self.config.center.force_gameset @@ -1115,15 +1119,29 @@ function Cryptid.update_obj_registry(m, force_enable) end if m.obj_table then for k, v in pairs(m.obj_table) do - if v.mod and v.mod.id == "Cryptid" then + if v.mod and (v.mod.id == "Cryptid" or Cryptid.mod_gameset_whitelist[v.mod.id]) then local en = force_enable or Cryptid.enabled(k) if en == true then if v.cry_disabled then v:enable() + if v.key == "set_cry_poker_hand_stuff" then + G.PROFILES[G.SETTINGS.profile].cry_none = Cryptid.safe_get( + G.PROFILES, + G.SETTINGS.profile, + "cry_none2" + ) or nil + G.PROFILES[G.SETTINGS.profile].cry_none2 = nil + end end else if not v.cry_disabled then v:_disable(en) + if v.key == "set_cry_poker_hand_stuff" and G.PROFILES[G.SETTINGS.profile].cry_none then + --Remove the none flag if poker hands are disabled because leaving it on can leave to softlocks + G.PROFILES[G.SETTINGS.profile].cry_none2 = + Cryptid.safe_get(G.PROFILES, G.SETTINGS.profile, "cry_none") + G.PROFILES[G.SETTINGS.profile].cry_none = nil + end end end end @@ -1141,7 +1159,7 @@ function Cryptid.index_items(func, m) end if m.obj_table then for k, v in pairs(m.obj_table) do - if v.mod and v.mod.id == "Cryptid" then + if v.mod and (v.mod.id == "Cryptid" or Cryptid.mod_gameset_whitelist[v.mod.id]) then func(v) end end @@ -1186,6 +1204,12 @@ SMODS.ContentSet({ key = "m", atlas = "atlasepic", pos = { x = 3, y = 1 }, --m + cry_order = -23, +}) +SMODS.ContentSet({ + key = "meme", + atlas = "atlastwo", + pos = { x = 2, y = 4 }, --Happy House cry_order = -22, }) SMODS.ContentSet({ @@ -1218,7 +1242,7 @@ SMODS.ContentSet({ key = "deck", atlas = "atlasdeck", pos = { x = 4, y = 5 }, --Critical Deck - cry_order = -23, + cry_order = -24, }) SMODS.ContentSet({ key = "spooky", @@ -1243,7 +1267,7 @@ SMODS.ContentSet({ key = "misc", atlas = "cry_misc", pos = { x = 2, y = 0 }, --Echo Card - cry_order = -22, + cry_order = -21, }) SMODS.ContentSet({ key = "misc_joker", @@ -1329,7 +1353,7 @@ function create_UIBox_your_collection_content_sets() local joker_pool = {} for k, v in pairs(SMODS.ContentSet.obj_table) do - if v.set == "Content Set" then + if v.set == "Content Set" and v.original_mod.id == G.ACTIVE_MOD_UI.id then table.insert(joker_pool, v) end end @@ -1424,7 +1448,7 @@ function create_UIBox_your_collection_current_set() end Cryptid.index_items(is_in_set) table.sort(joker_pool, function(a, b) - return a.cry_order < b.cry_order + return (a.cry_order or a.order or pseudorandom(a.key)) < (b.cry_order or b.order or pseudorandom(b.key)) end) local joker_options = {} for i = 1, math.ceil(#joker_pool / (5 * #G.your_collection)) do @@ -1493,12 +1517,12 @@ G.FUNCS.your_collection_content_set_page = function(args) end local joker_pool = {} for k, v in pairs(SMODS.ContentSet.obj_table) do - if v.set == "Content Set" then + if v.set == "Content Set" and v.original_mod.id == G.ACTIVE_MOD_UI.id then table.insert(joker_pool, v) end end table.sort(joker_pool, function(a, b) - return a.cry_order < b.cry_order + return (a.cry_order or a.order or pseudorandom(a.key)) < (b.cry_order or b.order or pseudorandom(b.key)) end) for i = 1, 5 do for j = 1, #G.your_collection do @@ -1541,7 +1565,7 @@ G.FUNCS.your_collection_current_set_page = function(args) end Cryptid.index_items(is_in_set) table.sort(joker_pool, function(a, b) - return a.cry_order < b.cry_order + return (a.cry_order or a.order or pseudorandom(a.key)) < (b.cry_order or b.order or pseudorandom(b.key)) end) for i = 1, 5 do for j = 1, #G.your_collection do @@ -1612,19 +1636,19 @@ end -- Hooks for all collection types local smcp = SMODS.collection_pool SMODS.collection_pool = function(m) - if G.ACTIVE_MOD_UI and G.ACTIVE_MOD_UI.id == "Cryptid" then + if G.ACTIVE_MOD_UI and (Cryptid.mod_gameset_whitelist[G.ACTIVE_MOD_UI.id] or G.ACTIVE_MOD_UI.id == "Cryptid") then -- use SMODS pools instead of vanilla pools, so disabled cards appear if m[1] and m[1].set and m[1].set == "Seal" then m = {} for k, v in pairs(SMODS.Seal.obj_table) do - if v.mod and v.mod.id == "Cryptid" then + if v.mod and (Cryptid.mod_gameset_whitelist[v.mod.id] or v.mod.id == "Cryptid") then table.insert(m, v) end end elseif m[1] and m[1].set and m[1].set == "Sticker" then m = {} for k, v in pairs(SMODS.Sticker.obj_table) do - if v.mod and v.mod.id == "Cryptid" then + if v.mod and (Cryptid.mod_gameset_whitelist[v.mod.id] or v.mod.id == "Cryptid") then table.insert(m, v) end end @@ -1632,19 +1656,19 @@ SMODS.collection_pool = function(m) local set = m[1].set m = {} for k, v in pairs(SMODS.Center.obj_table) do - if v.set == set and v.mod and v.mod.id == "Cryptid" then + if v.set == set and v.mod and (Cryptid.mod_gameset_whitelist[v.mod.id] or v.mod.id == "Cryptid") then table.insert(m, v) end end end -- Fix blind issues for k, v in pairs(m) do - if v.set == "Blind" and v.mod and v.mod.id == "Cryptid" then + if v.set == "Blind" and v.mod and (Cryptid.mod_gameset_whitelist[v.mod.id] or v.mod.id == "Cryptid") then v.config = {} end end table.sort(m, function(a, b) - return a.cry_order < b.cry_order + return (a.cry_order or a.order or pseudorandom(a.key)) < (b.cry_order or b.order or pseudorandom(b.key)) end) end return smcp(m) @@ -1654,7 +1678,7 @@ end local mct = modsCollectionTally function modsCollectionTally(pool, set) local t = mct(pool, set) - if G.ACTIVE_MOD_UI and G.ACTIVE_MOD_UI.id == "Cryptid" then + if G.ACTIVE_MOD_UI and (Cryptid.mod_gameset_whitelist[G.ACTIVE_MOD_UI.id] or G.ACTIVE_MOD_UI.id == "Cryptid") then local obj_tally = { tally = 0, of = 0 } --infer pool local _set = set or Cryptid.safe_get(pool, 1, "set") @@ -1709,10 +1733,10 @@ end -- Make non-center collections show all cards as centers local uibk = create_UIBox_your_collection_decks function create_UIBox_your_collection_decks() - if G.ACTIVE_MOD_UI and G.ACTIVE_MOD_UI.id == "Cryptid" then + if G.ACTIVE_MOD_UI and (Cryptid.mod_gameset_whitelist[G.ACTIVE_MOD_UI.id] or G.ACTIVE_MOD_UI.id == "Cryptid") then local generic_collection_pool = {} for k, v in pairs(SMODS.Center.obj_table) do - if v.set == "Back" and v.mod and v.mod.id == "Cryptid" then + if v.set == "Back" and v.mod and (v.mod.id == "Cryptid" or Cryptid.mod_gameset_whitelist[v.mod.id]) then table.insert(generic_collection_pool, v) end end @@ -1740,10 +1764,10 @@ end local uitag = create_UIBox_your_collection_tags function create_UIBox_your_collection_tags() - if G.ACTIVE_MOD_UI and G.ACTIVE_MOD_UI.id == "Cryptid" then + if G.ACTIVE_MOD_UI and (Cryptid.mod_gameset_whitelist[G.ACTIVE_MOD_UI.id] or G.ACTIVE_MOD_UI.id == "Cryptid") then local generic_collection_pool = {} for k, v in pairs(SMODS.Tag.obj_table) do - if v.set == "Tag" and v.mod and v.mod.id == "Cryptid" then + if v.set == "Tag" and v.mod and (v.mod.id == "Cryptid" or Cryptid.mod_gameset_whitelist[v.mod.id]) then table.insert(generic_collection_pool, v) end end @@ -1763,10 +1787,10 @@ end local uibl = create_UIBox_your_collection_blinds function create_UIBox_your_collection_blinds() - if G.ACTIVE_MOD_UI and G.ACTIVE_MOD_UI.id == "Cryptid" then + if G.ACTIVE_MOD_UI and (Cryptid.mod_gameset_whitelist[G.ACTIVE_MOD_UI.id] or G.ACTIVE_MOD_UI.id == "Cryptid") then local generic_collection_pool = {} for k, v in pairs(SMODS.Blind.obj_table) do - if v.set == "Blind" and v.mod and v.mod.id == "Cryptid" then + if v.set == "Blind" and v.mod and (v.mod.id == "Cryptid" or Cryptid.mod_gameset_whitelist[v.mod.id]) then table.insert(generic_collection_pool, v) end end @@ -1786,7 +1810,7 @@ end local uisl = create_UIBox_your_collection_seals function create_UIBox_your_collection_seals() - if G.ACTIVE_MOD_UI and G.ACTIVE_MOD_UI.id == "Cryptid" then + if G.ACTIVE_MOD_UI and (Cryptid.mod_gameset_whitelist[G.ACTIVE_MOD_UI.id] or G.ACTIVE_MOD_UI.id == "Cryptid") then return SMODS.card_collection_UIBox(G.P_CENTER_POOLS.Seal, { 5, 5 }, { snap_back = true, infotip = localize("ml_edition_seal_enhancement_explanation"), @@ -1808,7 +1832,7 @@ end local uist = create_UIBox_your_collection_stickers function create_UIBox_your_collection_stickers() - if G.ACTIVE_MOD_UI and G.ACTIVE_MOD_UI.id == "Cryptid" then + if G.ACTIVE_MOD_UI and (Cryptid.mod_gameset_whitelist[G.ACTIVE_MOD_UI.id] or G.ACTIVE_MOD_UI.id == "Cryptid") then return SMODS.card_collection_UIBox(SMODS.Stickers, { 5, 5 }, { snap_back = true, hide_single_page = true, diff --git a/Cryptid/lib/misc.lua b/Cryptid/lib/misc.lua index d6d93da..33050e6 100644 --- a/Cryptid/lib/misc.lua +++ b/Cryptid/lib/misc.lua @@ -187,6 +187,9 @@ function Cryptid.pluralize(str, vars) if type(num) == "string" then num = (Big and to_number(to_big(num))) or num end + if not num then + num = 1 + end local plural = _table[1] -- default local checks = { [1] = "=" } -- checks 1 by default local checks1mod = false -- tracks if 1 was modified @@ -217,6 +220,9 @@ function Cryptid.pluralize(str, vars) table.sort(keys, function(a, b) return a < b end) + if not (tonumber(num) or is_number(num)) then + num = 1 + end for _, k in ipairs(keys) do if fch(checks[k], "=") then if to_big(math.abs(num - k)) < to_big(0.001) then @@ -293,9 +299,11 @@ function Cryptid.with_deck_effects(card, func) if not card.added_to_deck then return func(card) else + card.from_quantum = true card:remove_from_deck(true) local ret = func(card) card:add_to_deck(true) + card.from_quantum = nil return ret end end @@ -468,7 +476,7 @@ function Cryptid.bonus_voucher_mod(mod) { bypass_discovery_center = true, bypass_discovery_ui = true } ) card.shop_cry_bonusvoucher = #curr_bonus - Cryptid.misprintize(card) + Cryptid.manipulate(card) if G.GAME.events.ev_cry_choco2 then card.misprint_cost_fac = (card.misprint_cost_fac or 1) * 2 card:set_cost() @@ -502,6 +510,9 @@ end local sppref = set_profile_progress function set_profile_progress() sppref() + if not Cryptid.shinytagdata then + Cryptid.shinytagdata = {} + end if not Cryptid.shinytagdata.init then for k, v in pairs(G.P_TAGS) do if Cryptid.shinytagdata[k] == nil then @@ -512,54 +523,46 @@ function set_profile_progress() end end -Cryptid.big_num_whitelist = { - j_ride_the_bus = true, - j_egg = true, - j_runner = true, - j_ice_cream = true, - j_constellation = true, - j_green_joker = true, - j_red_card = true, - j_madness = true, - j_square = true, - j_vampire = true, - j_hologram = true, - j_obelisk = true, - j_turtle_bean = true, - j_lucky_cat = true, - j_flash = true, - j_popcorn = true, - j_trousers = true, - j_ramen = true, - j_castle = true, - j_campfire = true, - j_throwback = true, - j_glass = true, - j_wee = true, - j_hit_the_road = true, - j_caino = true, - j_yorick = true, - -- Once all Cryptid Jokers get support for this, these can be removed - j_cry_dropshot = true, - j_cry_wee_fib = true, - j_cry_whip = true, - j_cry_pickle = true, - j_cry_chili_pepper = true, - j_cry_cursor = true, - j_cry_jimball = true, - j_cry_eternalflame = true, - j_cry_fspinner = true, - j_cry_krustytheclown = true, - j_cry_antennastoheaven = true, - j_cry_mondrian = true, - j_cry_spaceglobe = true, - j_cry_m = true, - j_cry_exponentia = true, - j_cry_crustulum = true, - j_cry_primus = true, - j_cry_stella_mortis = true, - j_cry_hugem = true, - j_cry_mprime = true, +Cryptid.big_num_blacklist = { + ["j_cry_fractal"] = true, + ["j_cry_wonka_bar"] = true, + ["j_cry_oldcandy"] = true, + ["j_cry_negative"] = true, + + ["c_magician"] = true, + ["c_empress"] = true, + ["c_heirophant"] = true, + ["c_lovers"] = true, + ["c_chariot"] = true, + ["c_justice"] = true, + ["c_strength"] = true, + ["c_hanged_man"] = true, + ["c_death"] = true, + ["c_devil"] = true, + ["c_tower"] = true, + ["c_star"] = true, + ["c_moon"] = true, + ["c_sun"] = true, + ["c_world"] = true, + ["c_cry_eclipse"] = true, + ["c_cry_seraph"] = true, + ["c_cry_instability"] = true, + + ["v_cry_stickyhand"] = true, + ["v_cry_grapplinghook"] = true, + ["v_cry_hyperspacetether"] = true, + + -- Add your Jokers here if you *don't* want to have it's numbers go into BigNum + -- FORMAT: = true, + -- TARGET: BigNum Black List +} + +Cryptid.mod_whitelist = { + Cryptid = true, + + -- Add your ModName here if you want your mod to have it's jokers' values go into BigNum + -- FORMAT: = true, + -- TARGET: BigNum Mod Whitelist } function Cryptid.is_card_big(joker) @@ -567,7 +570,18 @@ function Cryptid.is_card_big(joker) if not center then return false end - return Cryptid.big_num_whitelist[center.key or "Nope!"] --[[or + + if center.immutable and center.immutable == true then + return false + end + + if center.mod and not Cryptid.mod_whitelist[center.mod.name] then + return false + end + + local in_blacklist = Cryptid.big_num_blacklist[center.key or "Nope!"] or false + + return not in_blacklist --[[or (center.mod and center.mod.id == "Cryptid" and not center.no_break_infinity) or center.break_infinity--]] end @@ -585,6 +599,7 @@ function Cryptid.safe_get(t, ...) end return current end + --Functions used by boss blinds function Blind:cry_ante_base_mod(dt) if not self.disabled then @@ -595,6 +610,7 @@ function Blind:cry_ante_base_mod(dt) end return 0 end + function Blind:cry_round_base_mod(dt) if not self.disabled then local obj = self.config.blind @@ -604,15 +620,20 @@ function Blind:cry_round_base_mod(dt) end return 1 end + function Blind:cry_cap_score(score) if not self.disabled then local obj = self.config.blind + if obj.cry_modify_score and type(obj.cry_modify_score) == "function" then + score = obj:cry_modify_score(score) + end if obj.cry_cap_score and type(obj.cry_cap_score) == "function" then return obj:cry_cap_score(score) end end return score end + function Blind:cry_after_play() if not self.disabled then local obj = self.config.blind @@ -621,6 +642,7 @@ function Blind:cry_after_play() end end end + function Blind:cry_before_play() if not self.disabled then local obj = self.config.blind @@ -629,6 +651,17 @@ function Blind:cry_before_play() end end end + +--The decision's ability to show a booster pack +function Blind:cry_before_cash() + if not self.disabled then + local obj = self.config.blind + if obj.cry_before_cash and type(obj.cry_before_cash) == "function" then + return obj:cry_before_cash() + end + end +end + function Blind:cry_calc_ante_gain() if G.GAME.modifiers.cry_spooky then --here is the best place to check when spooky should apply local card @@ -649,6 +682,7 @@ function Blind:cry_calc_ante_gain() end return 1 end + function Cryptid.enhanced_deck_info(deck) --only accounts for vanilla stuff at the moment (WIP) local edition, enhancement, sticker, suit, seal = @@ -679,6 +713,7 @@ function Cryptid.enhanced_deck_info(deck) end return ret.edition, ret.enhancement, ret.sticker, ret.suit, ret.seal end + function Cryptid.post_process(center) if center.pools and center.pools.M then local vc = center.calculate @@ -703,8 +738,11 @@ end -- For resetting localization on the fly for family friendly toggle function Cryptid.reload_localization() SMODS.handle_loc_file(Cryptid.path) + Cryptid.handle_other_localizations() return init_localization() end +-- Purely for crossmod purposes +function Cryptid.handle_other_localizations() end -- Checks if all jokers in shop will have editions (via Curate, Edition Decks, etc.) -- Will cause edition tags to Nope! @@ -760,3 +798,665 @@ function Cryptid.is_shiny() end return false end + +--Abstracted cards +function Cryptid.cry_enhancement_has_specific_suit(card) + for k, _ in pairs(SMODS.get_enhancements(card)) do + if G.P_CENTERS[k].specific_suit then + return true + end + end + return false +end + +function Cryptid.cry_enhancement_get_specific_suit(card) + for k, _ in pairs(SMODS.get_enhancements(card)) do + if G.P_CENTERS[k].specific_suit then + return G.P_CENTERS[k].specific_suit + end + end + return nil +end + +function Cryptid.cry_enhancement_has_specific_rank(card) + for k, _ in pairs(SMODS.get_enhancements(card)) do + if G.P_CENTERS[k].specific_rank then + return true + end + end + return false +end + +function Cryptid.cry_enhancement_get_specific_rank(card) + for k, _ in pairs(SMODS.get_enhancements(card)) do + if G.P_CENTERS[k].specific_rank then + return G.P_CENTERS[k].specific_rank + end + end + return nil +end + +--For better durability (at the expense of performance), this finds the rank ID of a custom rank (such as abstract). +function Cryptid.cry_rankname_to_id(rankname) + for i, v in pairs(SMODS.Rank.obj_buffer) do + if rankname == v then + return i + end + end + return nil +end +-- for buttercup +function G.FUNCS.can_store_card(e) + -- get shop highlighted + -- only from the jokers spot + local highlighted_shop_cards = {} + local areas_to_check = { + shop_jokers = G.shop_jokers, + shop_vouchers = G.shop_vouchers, + shop_booster = G.shop_booster, + } + local jok = e.config.ref_table + + for key, value in pairs(areas_to_check) do + if value == nil then + e.config.colour = G.C.UI.BACKGROUND_INACTIVE + e.config.button = nil + return + elseif #value.highlighted == 1 and #highlighted_shop_cards == 0 then + highlighted_shop_cards[1] = value.highlighted[1] + end + end + if #highlighted_shop_cards == 1 and jok:can_use_storage() then + e.config.colour = G.C.BLUE + e.config.button = "store_card" + else + e.config.colour = G.C.UI.BACKGROUND_INACTIVE + e.config.button = nil + end +end + +function G.FUNCS.store_card(e) + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.1, + func = function() + local areas_to_check = { + shop_jokers = G.shop_jokers, + shop_vouchers = G.shop_vouchers, + shop_booster = G.shop_booster, + } + local this_card = e.config.ref_table + -- This doesn't take into account the possibility that multiple cards might be selected in different areas + -- but can_store_card already does that for us, so who cares tbh + for shop_name, shop_area in pairs(areas_to_check) do + if #shop_area.highlighted == 1 then + local new_card = shop_area.highlighted[1] + new_card.T.orig = { w = new_card.T.w, h = new_card.T.h } + new_card.T.w = new_card.T.w * 0.5 + new_card.T.h = new_card.T.h * 0.5 + new_card.cry_from_shop = shop_name + if new_card.children.price then + new_card.children.price:remove() + end + new_card.children.price = nil + if new_card.children.buy_button then + new_card.children.buy_button:remove() + end + new_card.children.buy_button = nil + shop_area:remove_card(new_card) + this_card.cry_storage:emplace(new_card) + end + end + return true + end, + })) +end + +function Card:can_use_storage() + if self.cry_storage ~= nil then + return #self.cry_storage.cards < self.ability.extra.slots + elseif self.config.center.key == "j_cry_buttercup" then -- "where did my fucking storage go" + sendInfoMessage("creating missing card area") + self.cry_storage = CardArea(0.5, 0.5, 1, 1, storage_area_config) + end + return false +end +function Cryptid.reset_to_none() + update_hand_text({ delay = 0 }, { + mult = Cryptid.ascend(G.GAME.hands["cry_None"].mult), + chips = Cryptid.ascend(G.GAME.hands["cry_None"].chips), + level = G.GAME.hands["cry_None"].level, + handname = localize("cry_None", "poker_hands"), + }) +end + +function Card:is_food() + --you cant really check if vanilla jokers are in a pool because its hardcoded + --so i have to hardcode it here too for the starfruit unlock + local food = { + j_gros_michel = true, + j_egg = true, + j_ice_cream = true, + j_cavendish = true, + j_turtle_bean = true, + j_diet_cola = true, + j_popcorn = true, + j_ramen = true, + j_selzer = true, + } + if food[self.config.center.key] or Cryptid.safe_get(self.config.center, "pools", "Food") then + return true + end +end + +function Cryptid.get_highlighted_cards(areas, ignore, min, max, blacklist, seed) + ignore.checked = true + blacklist = blacklist or function() + return true + end + local cards = {} + for i, area in pairs(areas) do + if area.cards then + for i2, card in pairs(area.cards) do + if + card ~= ignore + and blacklist(card) + and (card.highlighted or G.cry_force_use) + and not card.checked + then + cards[#cards + 1] = card + card.checked = true + end + end + end + end + for i, v in ipairs(cards) do + v.checked = nil + end + if (#cards >= min and #cards <= max) or not G.cry_force_use then + ignore.checked = nil + return cards + else + for i, v in pairs(cards) do + v.f_use_order = i + end + pseudoshuffle(cards, pseudoseed("forcehighlight" or seed)) + local actual = {} + for i = 1, max do + if cards[i] and not cards[i].checked and actual ~= ignore then + actual[#actual + 1] = cards[i] + end + end + table.sort(actual, function(a, b) + return a.f_use_order < b.f_use_order + end) + for i, v in pairs(cards) do + v.f_use_order = nil + end + ignore.checked = nil + return actual + end + return {} +end + +function Cryptid.table_merge(...) + local tbl = {} + for _, t in ipairs({ ... }) do + if type(t) == "table" then + for _, v in pairs(t) do + tbl[#tbl + 1] = v + end + end + end + return tbl +end + +function Cryptid.get_circus_description() + local desc = {} + local ind = 1 + local extra_rarities = {} + if not Cryptid.circus_rarities then + Cryptid.circus_rarities = {} + end + for i, v in pairs(Cryptid.circus_rarities) do + if not v.hidden then + extra_rarities[#extra_rarities + 1] = v + end + end + table.sort(extra_rarities, function(a, b) + return a.order < b.order + end) + for i, v in pairs(extra_rarities) do + local rarity = v.rarity + rarity = localize(({ + [1] = "k_common", + [2] = "k_uncommon", + [3] = "k_rare", + [4] = "k_legendary", + })[rarity] or "k_" .. rarity) + local orig = localize("cry_circus_generic") + orig = string.gsub(orig, "#1#", ind) + orig = string.gsub(orig, "#2#", rarity) + orig = string.gsub(orig, "#3#", "#" .. tostring(ind) .. "#") + desc[#desc + 1] = orig + ind = ind + 1 + end + return desc +end + +function Cryptid.add_circus_rarity(rarity, dontreload) + Cryptid.circus_rarities[rarity.rarity] = rarity + if not dontreload then + Cryptid.reload_localization() + end +end + +function Cryptid.get_paved_joker() + if G.hand then + local total = 0 + for i, v in pairs(SMODS.find_card("j_cry_paved_joker")) do + total = total + v.ability.extra + end + local stones = 0 + for i, v in pairs(G.hand.highlighted) do + if v.config.center.key == "m_stone" then + stones = stones + 1 + end + end + for i, v in pairs(G.play.cards) do + if v.config.center.key == "m_stone" then + stones = stones + 1 + end + end + total = math.min(stones, total) + return total + end + return 0 +end + +function Card:has_stickers() + for i, v in pairs(SMODS.Sticker.obj_table) do + if self.ability[i] then + return true + end + end +end +function Card:remove_random_sticker(seed) + local s = {} + for i, v in pairs(SMODS.Sticker.obj_table) do + if not v.hidden and i ~= "cry_absolute" and self.ability[i] then + s[#s + 1] = i + end + end + if #s > 0 then + local sticker = pseudorandom_element(s, pseudoseed(seed)) + self.ability[sticker] = nil + if sticker == "perishable" then + self.ability.perish_tally = nil + end + end +end + +function create_UIBox_class() + return SMODS.card_collection_UIBox(G.P_CENTER_POOLS.Enhanced, { 4, 4 }, { + no_materialize = true, + snap_back = true, + h_mod = 1.03, + --infotip = localize('ml_edition_seal_enhancement_explanation'), + hide_single_page = true, + back_func = "exit_overlay_menu_code", + }) +end + +function create_UIBox_variable_code() + local cards = {} + local ranks = {} + for i, v in pairs(SMODS.Ranks) do + cards[#cards + 1] = G.P_CENTERS.c_base + ranks[#ranks + 1] = i + end + table.sort(ranks, function(a, b) + return SMODS.Ranks[a].id < SMODS.Ranks[b].id + end) + return SMODS.card_collection_UIBox(cards, { 5, 5, 5 }, { + no_materialize = true, + snap_back = true, + h_mod = 1.03, + --infotip = localize('ml_edition_seal_enhancement_explanation'), + hide_single_page = true, + back_func = "exit_overlay_menu_code", + modify_card = function(card, center, i, j) + SMODS.change_base(card, "Spades", ranks[(j - 1) * 5 + i]) + end, + }) +end + +function create_UIBox_exploit() + local cards = {} + local ranks = {} + for i, v in pairs(G.P_CENTER_POOLS.Planet) do + if v.config.handname then + cards[#cards + 1] = v + end + end + table.sort(ranks, function(a, b) + return G.GAME.hands[a.config.handname].order < G.GAME.hands[b.config.handname] + end) + return SMODS.card_collection_UIBox(cards, { 5, 5, 5 }, { + no_materialize = true, + snap_back = true, + h_mod = 1.03, + --infotip = localize('ml_edition_seal_enhancement_explanation'), + hide_single_page = true, + back_func = "exit_overlay_menu_code", + }) +end + +G.FUNCS.exit_overlay_menu_code = function(e) + G.FUNCS.exit_overlay_menu(e) + G.GAME.USING_CLASS = nil + G.GAME.USING_CODE = nil + G.GAME.USING_VARIABLE = nil + G.GAME.USING_EXPLOIT_HAND = nil + G.GAME.USING_EXPLOIT = nil + G.GAME.USING_POINTER = nil + G.GAME.POINTER_SUBMENU = nil + G.GAME.POINTER_PLAYING = nil + G.GAME.POINTER_COLLECTION = nil + if + G.GAME.CODE_DESTROY_CARD + and G.GAME.CODE_DESTROY_CARD.ability + and G.GAME.CODE_DESTROY_CARD.ability.cry_multiuse + then + G.GAME.CODE_DESTROY_CARD.ability.cry_multiuse = G.GAME.CODE_DESTROY_CARD.ability.cry_multiuse - 1 + elseif G.GAME.CODE_DESTROY_CARD then + G.GAME.CODE_DESTROY_CARD:start_dissolve() + G.GAME.CODE_DESTROY_CARD = nil + end + G.GAME.CODE_DESTROY_CARD = nil +end + +function G.UIDEF.exploit_menu() + return create_UIBox_generic_options({ + contents = { + create_tabs({ + tabs = { + { + label = localize("b_poker_hands"), + chosen = true, + tab_definition_function = create_UIBox_current_hands_exploit, + }, + }, + tab_h = 8, + snap_to_nav = true, + }), + }, + }) +end + +function create_UIBox_current_hands_exploit(simple) + local ref = create_UIBox_current_hand_row + local ret = create_UIBox_current_hands(simple) + create_UIBox_current_hand_row = ref + return ret +end + +local htref = create_UIBox_hand_tip +function create_UIBox_hand_tip(handname) + if G.GAME.USING_EXPLOIT then + G.GAME.USING_EXPLOIT_HAND = handname + end + return htref(handname) +end + +local lcpref = Controller.L_cursor_press +function Controller:L_cursor_press(x, y) + lcpref(self, x, y) + if G and G.GAME and G.GAME.hands and G.GAME.USING_EXPLOIT_HAND then + if + G.CONTROLLER.cursor_hover + and G.CONTROLLER.cursor_hover.target + and G.CONTROLLER.cursor_hover.target.config + and G.CONTROLLER.cursor_hover.target.config.on_demand_tooltip + and G.CONTROLLER.cursor_hover.target.config.on_demand_tooltip.filler + and G.CONTROLLER.cursor_hover.target.config.on_demand_tooltip.filler.args + and G.GAME.hands[G.CONTROLLER.cursor_hover.target.config.on_demand_tooltip.filler.args] + then + -- Re-use the Exploit card + if G.GAME.ACTIVE_CODE_CARD then + if + not G.GAME.ACTIVE_CODE_CARD.ability.cry_multiuse + or to_big(G.GAME.ACTIVE_CODE_CARD.ability.cry_multiuse) <= to_big(1) + then + G.GAME.ACTIVE_CODE_CARD:start_dissolve() + else + G.GAME.ACTIVE_CODE_CARD.ability.cry_multiuse = + lenient_bignum(to_big(G.GAME.ACTIVE_CODE_CARD.ability.cry_multiuse) - to_big(1)) + end + end + G.GAME.ACTIVE_CODE_CARD = nil + G.GAME.cry_exploit_override = G.GAME.USING_EXPLOIT_HAND + G.FUNCS.exit_overlay_menu_code() + end + end +end + +function create_UIBox_pointer_rank() + G.GAME.POINTER_SUBMENU = "Rank" + G.GAME.POINTER_PLAYING = {} + local cards = {} + local ranks = {} + for i, v in pairs(SMODS.Ranks) do + cards[#cards + 1] = G.P_CENTERS.c_base + ranks[#ranks + 1] = i + end + table.sort(ranks, function(a, b) + return SMODS.Ranks[a].id < SMODS.Ranks[b].id + end) + return SMODS.card_collection_UIBox(cards, { 5, 5, 5 }, { + no_materialize = true, + snap_back = true, + h_mod = 1.03, + --infotip = localize('ml_edition_seal_enhancement_explanation'), + hide_single_page = true, + back_func = "your_collection", + modify_card = function(card, center, i, j) + SMODS.change_base(card, "Spades", ranks[(j - 1) * 5 + i]) + if + center.hidden + or center.no_noe + or center.no_pointer + or center.no_code + or center.no_variable + or center.no_class + then + card.deuff = true + end + end, + }) +end + +function create_UIBox_pointer_suit() + G.GAME.POINTER_SUBMENU = "Suit" + local cards = {} + local suits = {} + for i, v in pairs(SMODS.Suits) do + cards[#cards + 1] = G.P_CENTERS.c_base + suits[#suits + 1] = i + end + table.sort(suits, function(a, b) + return SMODS.Suits[a].suit_nominal < SMODS.Suits[b].suit_nominal + end) + return SMODS.card_collection_UIBox(cards, { 4, 4, 4 }, { + no_materialize = true, + snap_back = true, + h_mod = 1.03, + --infotip = localize('ml_edition_seal_enhancement_explanation'), + hide_single_page = true, + back_func = "your_collection", + modify_card = function(card, center, i, j) + SMODS.change_base(card, suits[(j - 1) * 4 + i], G.GAME.POINTER_PLAYING.rank) + if + center.hidden + or center.no_noe + or center.no_pointer + or center.no_code + or center.no_variable + or center.no_class + then + card.deuff = true + end + end, + }) +end + +function create_UIBox_pointer_enhancement() + G.GAME.POINTER_SUBMENU = "Enhancement" + return create_UIBox_your_collection_enhancements_pointer() +end + +function create_UIBox_pointer_edition() + G.GAME.POINTER_SUBMENU = "Edition" + return create_UIBox_your_collection_editions_pointer() +end + +function create_UIBox_pointer_seal() + G.GAME.POINTER_SUBMENU = "Seal" + return create_UIBox_your_collection_seals_pointer() +end + +G.FUNCS.your_collection_create_card_rank = function(e) + G.SETTINGS.paused = true + G.FUNCS.overlay_menu({ + definition = create_UIBox_pointer_rank(), + }) +end + +create_UIBox_your_collection_enhancements_pointer = function() + local cards = { + G.P_CENTERS.c_base, + } + for i, v in pairs(G.P_CENTER_POOLS.Enhanced) do + cards[#cards + 1] = v + end + return SMODS.card_collection_UIBox(cards, { 4, 4 }, { + no_materialize = true, + snap_back = true, + h_mod = 1.03, + hide_single_page = true, + modify_card = function(card, center) + SMODS.change_base(card, G.GAME.POINTER_PLAYING.suit, G.GAME.POINTER_PLAYING.rank) + if + center.hidden + or center.no_noe + or center.no_pointer + or center.no_code + or center.no_variable + or center.no_class + then + card.deuff = true + end + end, + }) +end + +create_UIBox_your_collection_editions_pointer = function() + return SMODS.card_collection_UIBox(G.P_CENTER_POOLS.Edition, { 5, 5 }, { + snap_back = true, + h_mod = 1.03, + hide_single_page = true, + collapse_single_page = true, + modify_card = function(card, center) + if center.discovered then + card:set_edition(center.key, true, true) + SMODS.change_base(card, G.GAME.POINTER_PLAYING.suit, G.GAME.POINTER_PLAYING.rank) + card:set_ability(G.P_CENTERS[G.GAME.POINTER_PLAYING.center]) + if + center.hidden + or center.no_noe + or center.no_pointer + or center.no_code + or center.no_variable + or center.no_class + then + card.deuff = true + end + end + end, + }) +end + +create_UIBox_your_collection_seals_pointer = function() + local cards = { + { key = nil }, + } + for i, v in pairs(G.P_CENTER_POOLS.Seal) do + cards[#cards + 1] = v + end + return SMODS.card_collection_UIBox(cards, { 5, 5 }, { + snap_back = true, + hide_single_page = true, + collapse_single_page = true, + center = "c_base", + h_mod = 1.03, + modify_card = function(card, center) + card:set_seal(center.key, true) + SMODS.change_base(card, G.GAME.POINTER_PLAYING.suit, G.GAME.POINTER_PLAYING.rank) + card:set_ability(G.P_CENTERS[G.GAME.POINTER_PLAYING.center]) + card:set_edition(G.GAME.POINTER_PLAYING.edition, true, true) + if + center.hidden + or center.no_noe + or center.no_pointer + or center.no_code + or center.no_variable + or center.no_class + then + card.deuff = true + end + end, + }) +end + +function Cryptid.get_next_tag(override) + if next(SMODS.find_card("j_cry_kittyprinter")) then + return "tag_cry_cat" + end +end + +-- for Cryptid.isNonRollProbabilityContext +local probability_contexts = { + "mod_probability", + "fix_probability", +} + +-- Checks if a context table is a probability context called outside of a roll +function Cryptid.isNonRollProbabilityContext(context) + for _, ctx in ipairs(probability_contexts) do + if context[ctx] then + return context.from_roll + end + end + + return true +end + +function Cryptid.nuke_decimals(number, surviving_decimals, round) + surviving_decimals = surviving_decimals or 0 + --Set round to 0.5 to round or 0 to floor + round = round or 0 + local aaa = 10 ^ surviving_decimals + return math.floor(number * aaa + round) / aaa +end +-- "log base (x) of (y)". Pre-Calculus courses recommended +function Cryptid.funny_log(x, y) + return math.log(y) / math.log(x) +end + +local say_stuff_ref = Card_Character.say_stuff +function Card_Character:say_stuff(n, not_first, quip_key) + local quip = SMODS.JimboQuips[quip_key] + if quip then + return say_stuff_ref(self, n, not_first, quip_key) + end +end diff --git a/Cryptid/lib/misprintize.lua b/Cryptid/lib/misprintize.lua index 6460b08..b3aa39a 100644 --- a/Cryptid/lib/misprintize.lua +++ b/Cryptid/lib/misprintize.lua @@ -2,78 +2,195 @@ --Redefine these here because they're always used Cryptid.base_values = {} -function Cryptid.misprintize_tbl(name, ref_tbl, ref_value, clear, override, stack, big) + +Cryptid.misprintize_value_blacklist = { + perish_tally = false, + id = false, + suit_nominal = false, + base_nominal = false, + face_nominal = false, + qty = false, + h_x_chips = false, + d_size = false, + h_size = false, + selected_d6_face = false, + cry_hook_id = false, + colour = false, + suit_nominal_original = false, + times_played = false, + -- TARGET: Misprintize Value Blacklist (format: key = false, ) +} +Cryptid.misprintize_bignum_blacklist = { + odds = false, + cry_prob = false, + --nominal = false, +} + +function Cryptid.calculate_misprint(initial, min, max, grow_type, pow_level) + local big_initial = (type(initial) ~= "table" and to_big(initial)) or initial + local big_min = (type(min) ~= "table" and to_big(min)) or min + local big_max = (type(max) ~= "table" and to_big(max)) or max + + local grow = Cryptid.log_random(pseudoseed("cry_misprint" .. G.GAME.round_resets.ante), big_min, big_max) + + local calc = big_initial + if not grow_type then + calc = calc * grow + elseif grow_type == "+" then + calc = calc + grow + elseif grow_type == "-" then + calc = calc - grow + elseif grow_type == "/" then + calc = calc / grow + elseif grow_type == "^" then + pow_level = pow_level or 1 + if pow_level == 1 then + calc = calc ^ grow + else + local function hyper(level, base, height) + local big_base = (type(base) ~= "table" and to_big(base)) or base + local big_height = (type(height) ~= "table" and to_big(height)) or height + + if height == 1 then + return big_base + elseif level == 1 then + return big_base ^ big_height + else + local inner = hyper(level, base, height - 1) + return hyper(level - 1, base, inner) + end + end + + calc = hyper(pow_level, calc, grow) + end + end + + if calc > to_big(-1e100) and calc < to_big(1e100) then + calc = to_number(calc) + end + + return calc +end + +function Cryptid.misprintize_tbl(name, ref_tbl, ref_value, clear, override, stack, big, grow_type, pow_level) + local prob_max = 1e69 -- funny number + local max_slots = 100 + local max_booster_slots = 25 + + local function num_too_big(initial, min, max, limit) + return ( + to_big(initial) > to_big(limit) + or (min and to_big(initial) * min > to_big(limit)) + or (max and to_big(initial) * max > to_big(limit)) + ) + end + if name and ref_tbl and ref_value then - tbl = Cryptid.deep_copy(ref_tbl[ref_value]) + local tbl = Cryptid.deep_copy(ref_tbl[ref_value]) + + local function can_misprintize_value(k, v) + if + (k == "x_mult" and v == 1 and not tbl.override_x_mult_check) + or (k == "x_chips" and v == 1 and not tbl.override_x_chips_check) + then + return false + end + for key, val in pairs(Cryptid.misprintize_value_blacklist) do + if tostring(k) == tostring(key) then + return val + end + end + return true + end + for k, v in pairs(tbl) do if (type(tbl[k]) ~= "table") or is_number(tbl[k]) then - if - is_number(tbl[k]) - and not (k == "perish_tally") - and not (k == "id") - and not (k == "colour") - and not (k == "suit_nominal") - and not (k == "base_nominal") - and not (k == "face_nominal") - and not (k == "qty") - and not (k == "x_mult" and v == 1 and not tbl.override_x_mult_check) - and not (k == "x_chips" and v == 1 and not tbl.override_x_chips_check) - and not (k == "h_x_chips") - and not (k == "selected_d6_face") - then --Temp fix, even if I did clamp the number to values that wouldn't crash the game, the fact that it did get randomized means that there's a higher chance for 1 or 6 than other values + if is_number(tbl[k]) and can_misprintize_value(k, tbl[k]) then if not Cryptid.base_values[name] then Cryptid.base_values[name] = {} end - if not Cryptid.base_values[name][k] then - Cryptid.base_values[name][k] = tbl[k] + if not Cryptid.base_values[name][k .. ref_value] then + Cryptid.base_values[name][k .. ref_value] = tbl[k] end + local initial = (stack and tbl[k] or Cryptid.base_values[name][k .. ref_value]) + local min = override and override.min or G.GAME.modifiers.cry_misprint_min + local max = override and override.max or G.GAME.modifiers.cry_misprint_max + + if + ( + k == "cry_prob" + -- Hack for vanilla jokers that use the extra field to describe their odds + or ( + ( + name == "j_8_ball" + or name == "j_business" + or name == "j_space" + or name == "j_hallucination" + ) and k == "extra" + ) + ) and num_too_big(initial, min, max, prob_max) + then + initial = Cryptid.base_values[name][k .. ref_value] * prob_max + min = 1 + max = 1 + end + tbl[k] = Cryptid.sanity_check( - clear and Cryptid.base_values[name][k] - or cry_format( - (stack and tbl[k] or Cryptid.base_values[name][k]) - * Cryptid.log_random( - pseudoseed("cry_misprint" .. G.GAME.round_resets.ante), - override and override.min or G.GAME.modifiers.cry_misprint_min, - override and override.max or G.GAME.modifiers.cry_misprint_max - ), - "%.2g" - ), + clear and Cryptid.base_values[name][k .. ref_value] + or cry_format(Cryptid.calculate_misprint(initial, min, max, grow_type, pow_level), "%.2g"), big ) end - elseif not (k == "immutable") then + elseif not (k == "immutable") and not (k == "colour") then for _k, _v in pairs(tbl[k]) do - if - is_number(tbl[k][_k]) - and not (_k == "id") - and not (k == "colour") - and not (_k == "suit_nominal") - and not (_k == "base_nominal") - and not (_k == "face_nominal") - and not (_k == "qty") - and not (k == "x_mult" and v == 1 and not tbl[k].override_x_mult_check) - and not (k == "x_chips" and v == 1 and not tbl[k].override_x_chips_check) - and not (k == "h_x_chips") - and not (_k == "selected_d6_face") - then --Refer to above + if is_number(tbl[k][_k]) and can_misprintize_value(_k, tbl[k][_k]) then if not Cryptid.base_values[name] then Cryptid.base_values[name] = {} end - if not Cryptid.base_values[name][k] then - Cryptid.base_values[name][k] = {} + if not Cryptid.base_values[name][_k .. k] then + if + G.P_CENTERS[name] + and type(G.P_CENTERS[name].config[k]) == "table" + and G.P_CENTERS[name].config[k][_k] + then + Cryptid.base_values[name][_k .. k] = G.P_CENTERS[name].config[k][_k] + else + Cryptid.base_values[name][_k .. k] = tbl[k][_k] + end end - if not Cryptid.base_values[name][k][_k] then - Cryptid.base_values[name][k][_k] = tbl[k][_k] + + local initial = (stack and tbl[k][_k] or Cryptid.base_values[name][_k .. k]) + local min = override and override.min or G.GAME.modifiers.cry_misprint_min + local max = override and override.max or G.GAME.modifiers.cry_misprint_max + + if (_k == "odds") and num_too_big(initial, min, max, prob_max) then + initial = Cryptid.base_values[name][_k .. k] * prob_max + min = 1 + max = 1 end + + if + (_k == "slots" and (name == "j_cry_tenebris" or name == "j_cry_negative")) + and num_too_big(initial, min, max, max_slots) + then + initial = max_slots + min = 1 + max = 1 + end + + if + (_k == "booster_slots" and (name == "j_cry_booster")) + and num_too_big(initial, min, max, max_booster_slots) + then + initial = max_booster_slots + min = 1 + max = 1 + end + tbl[k][_k] = Cryptid.sanity_check( - clear and Cryptid.base_values[name][k][_k] + clear and Cryptid.base_values[name][_k .. k] or cry_format( - (stack and tbl[k][_k] or Cryptid.base_values[name][k][_k]) - * Cryptid.log_random( - pseudoseed("cry_misprint" .. G.GAME.round_resets.ante), - override and override.min or G.GAME.modifiers.cry_misprint_min, - override and override.max or G.GAME.modifiers.cry_misprint_max - ), + Cryptid.calculate_misprint(initial, min, max, grow_type, pow_level), "%.2g" ), big @@ -85,16 +202,17 @@ function Cryptid.misprintize_tbl(name, ref_tbl, ref_value, clear, override, stac ref_tbl[ref_value] = tbl end end -function Cryptid.misprintize_val(val, override, big) +function Cryptid.misprintize_val(val, override, big, grow_type, pow_level) if is_number(val) then val = Cryptid.sanity_check( cry_format( - val - * Cryptid.log_random( - pseudoseed("cry_misprint" .. G.GAME.round_resets.ante), - override and override.min or G.GAME.modifiers.cry_misprint_min, - override and override.max or G.GAME.modifiers.cry_misprint_max - ), + Cryptid.calculate_misprint( + val, + override and override.min or G.GAME.modifiers.cry_misprint_min, + override and override.max or G.GAME.modifiers.cry_misprint_max, + grow_type, + pow_level + ), "%.2g" ), big @@ -117,9 +235,19 @@ function Cryptid.sanity_check(val, is_big) if not val or type(val) == "number" and (val ~= val or val > 1e300 or val < -1e300) then return 1e300 end + if type(val) == "table" then + if val > to_big(1e300) then + return 1e300 + end + if val < to_big(-1e300) then + return -1e300 + end + return to_number(val) + end return val end -function Cryptid.misprintize(card, override, force_reset, stack) +function Cryptid.misprintize(card, override, force_reset, stack, grow_type, pow_level) + local clamps = card.config.center.misprintize_caps or {} if Card.no(card, "immutable", true) then force_reset = true end @@ -127,7 +255,7 @@ function Cryptid.misprintize(card, override, force_reset, stack) if card.infinifusion then if card.config.center == card.infinifusion_center or card.config.center.key == "j_infus_fused" then calculate_infinifusion(card, nil, function(i) - Cryptid.misprintize(card, override, force_reset, stack) + Cryptid.misprintize(card, override, force_reset, stack, grow_type, pow_level) end) end end @@ -137,9 +265,6 @@ function Cryptid.misprintize(card, override, force_reset, stack) and not stack or not Card.no(card, "immutable", true) then - if card.ability.name == "Ace Aequilibrium" then - return - end if G.GAME.modifiers.cry_jkr_misprint_mod and card.ability.set == "Joker" then if not override then override = {} @@ -157,7 +282,9 @@ function Cryptid.misprintize(card, override, force_reset, stack) nil, override, stack, - Cryptid.is_card_big(card) + Cryptid.is_card_big(card), + grow_type, + pow_level ) if card.base then Cryptid.misprintize_tbl( @@ -167,7 +294,9 @@ function Cryptid.misprintize(card, override, force_reset, stack) nil, override, stack, - Cryptid.is_card_big(card) + Cryptid.is_card_big(card), + grow_type, + pow_level ) end end @@ -182,7 +311,41 @@ function Cryptid.misprintize(card, override, force_reset, stack) card:set_cost() end else - Cryptid.misprintize_tbl(card.config.center_key, card, "ability", true, nil, nil, Cryptid.is_card_big(card)) + Cryptid.misprintize_tbl( + card.config.center_key, + card, + "ability", + true, + nil, + nil, + Cryptid.is_card_big(card), + grow_type, + pow_level + ) + end + if clamps then + for i, v in pairs(clamps) do + if type(v) == "table" and not v.tetrate then + for i2, v2 in pairs(v) do + if to_big(card.ability[i][i2]) > to_big(v2) then + card.ability[i][i2] = Cryptid.sanity_check(v2, Cryptid.is_card_big(card)) + if + to_big(card.ability[i][i2]) > to_big(-1e100) + or to_big(card.ability[i][i2]) < to_big(1e100) + then + card.ability[i][i2] = to_number(card.ability[i][i2]) + end + end + end + elseif (type(v) == "table" and v.tetrate) or type(v) == "number" then + if to_big(card.ability[i]) > to_big(v) then + card.ability[i] = Cryptid.sanity_check(v, Cryptid.is_card_big(card)) + if to_big(card.ability[i]) > to_big(-1e100) or to_big(card.ability[i]) < to_big(1e100) then + card.ability[i] = to_number(card.ability[i]) + end + end + end + end end if card.ability.consumeable then for k, v in pairs(card.ability.consumeable) do @@ -223,3 +386,187 @@ function Card:get_nominal(mod) + 10 * self.base.face_nominal * rank_mult + 0.000001 * self.unique_val end + +function Cryptid.manipulate(card, args) + if not Card.no(card, "immutable", true) or (args and args.bypass_checks) then + if not args then + return Cryptid.manipulate(card, { + min = (G.GAME.modifiers.cry_misprint_min or 1) * (G.GAME.modifiers.cry_jkr_misprint_mod or 1), + max = (G.GAME.modifiers.cry_misprint_max or 1) * (G.GAME.modifiers.cry_jkr_misprint_mod or 1), + type = "X", + dont_stack = true, + no_deck_effects = true, + }) + else + local func = function(card) + if not args.type then + args.type = "X" + end + --hardcoded whatever + if card.config.center.set == "Booster" then + args.big = false + end + local caps = card.config.center.misprintize_caps or {} + if card.infinifusion then + if card.config.center == card.infinifusion_center or card.config.center.key == "j_infus_fused" then + calculate_infinifusion(card, nil, function(i) + Cryptid.manipulate(card, args) + end) + end + end + Cryptid.manipulate_table(card, card, "ability", args) + if card.base then + Cryptid.manipulate_table(card, card, "base", args) + end + if G.GAME.modifiers.cry_misprint_min then + --card.cost = cry_format(card.cost / Cryptid.log_random(pseudoseed('cry_misprint'..G.GAME.round_resets.ante),override and override.min or G.GAME.modifiers.cry_misprint_min,override and override.max or G.GAME.modifiers.cry_misprint_max),"%.2f") + card.misprint_cost_fac = 1 + / Cryptid.log_random( + pseudoseed("cry_misprint" .. G.GAME.round_resets.ante), + override and override.min or G.GAME.modifiers.cry_misprint_min, + override and override.max or G.GAME.modifiers.cry_misprint_max + ) + card:set_cost() + end + if caps then + for i, v in pairs(caps) do + if type(v) == "table" and not v.tetrate then + for i2, v2 in pairs(v) do + if to_big(card.ability[i][i2]) > to_big(v2) then + card.ability[i][i2] = Cryptid.sanity_check(v2, Cryptid.is_card_big(card)) + end + end + elseif (type(v) == "table" and v.tetrate) or type(v) == "number" then + if to_big(card.ability[i]) > to_big(v) then + card.ability[i] = Cryptid.sanity_check(v, Cryptid.is_card_big(card)) + end + end + end + end + end + local config = copy_table(card.config.center.config) + if not Cryptid.base_values[card.config.center.key] then + Cryptid.base_values[card.config.center.key] = {} + for i, v in pairs(config) do + if (type(v) == "table" and v.tetrate) or type(v) == "number" and to_big(v) ~= to_big(0) then + Cryptid.base_values[card.config.center.key][i .. "ability"] = v + elseif type(v) == "table" then + for i2, v2 in pairs(v) do + Cryptid.base_values[card.config.center.key][i2 .. i] = v2 + end + end + end + end + if not args.bypass_checks and not args.no_deck_effects then + Cryptid.with_deck_effects(card, func) + else + func(card) + end + if card.ability.consumeable then + for k, v in pairs(card.ability.consumeable) do + card.ability.consumeable[k] = Cryptid.deep_copy(card.ability[k]) + end + end + --ew ew ew ew + G.P_CENTERS[card.config.center.key].config = config + end + return true + end +end + +function Cryptid.manipulate_table(card, ref_table, ref_value, args, tblkey) + if ref_value == "consumeable" then + return + end + for i, v in pairs(ref_table[ref_value]) do + if + (type(v) == "number" or (type(v) == "table" and v.tetrate)) + and Cryptid.misprintize_value_blacklist[i] ~= false + then + local num = v + if args.dont_stack then + if + Cryptid.base_values[card.config.center.key] + and ( + Cryptid.base_values[card.config.center.key][i .. ref_value] + or (ref_value == "ability" and Cryptid.base_values[card.config.center.key][i .. "consumeable"]) + ) + then + num = Cryptid.base_values[card.config.center.key][i .. ref_value] + or Cryptid.base_values[card.config.center.key][i .. "consumeable"] + end + end + if args.big ~= nil then + ref_table[ref_value][i] = Cryptid.manipulate_value(num, args, args.big, i) + else + ref_table[ref_value][i] = Cryptid.manipulate_value(num, args, Cryptid.is_card_big(card), i) + end + elseif i ~= "immutable" and type(v) == "table" and Cryptid.misprintize_value_blacklist[i] ~= false then + Cryptid.manipulate_table(card, ref_table[ref_value], i, args) + end + end +end + +function Cryptid.manipulate_value(num, args, is_big, name) + if args.func then + num = args.func(num, args, is_big, name) + else + if args.min and args.max then + local new_args = args + local big_min = to_big(args.min) + local big_max = to_big(args.max) + local new_value = Cryptid.log_random( + pseudoseed(args.seed or ("cry_misprint" .. G.GAME.round_resets.ante)), + big_min, + big_max + ) + if args.type == "+" then + if to_big(num) ~= to_big(0) and to_big(num) ~= to_big(1) then + num = num + new_value + end + elseif args.type == "X" then + if + to_big(num) ~= to_big(0) and (to_big(num) ~= to_big(1) or (name ~= "x_chips" and name ~= "x_mult")) + then + num = num * new_value + end + elseif args.type == "^" then + num = to_big(num) ^ new_value + elseif args.type == "hyper" then + if to_big(num) ~= to_big(0) and to_big(num) ~= to_big(1) then + num = to_big(num):arrow(args.value.arrows, to_big(new_value)) + end + end + elseif args.value then + if args.type == "+" then + if to_big(num) ~= to_big(0) and to_big(num) ~= to_big(1) then + num = num + to_big(args.value) + end + elseif args.type == "X" then + if + to_big(num) ~= to_big(0) and (to_big(num) ~= to_big(1) or (name ~= "x_chips" and name ~= "x_mult")) + then + num = num * args.value + end + elseif args.type == "^" then + num = to_big(num) ^ args.value + elseif args.type == "hyper" then + num = to_big(num):arrow(args.value.arrows, to_big(args.value.height)) + end + end + end + if Cryptid.misprintize_bignum_blacklist[name] == false then + num = to_number(num) + return to_number(Cryptid.sanity_check(num, false)) + end + local val = Cryptid.sanity_check(num, is_big) + if to_big(val) > to_big(-1e100) and to_big(val) < to_big(1e100) then + return to_number(val) + end + return val +end + +local get_nominalref = Card.get_nominal +function Card:get_nominal(...) + return to_number(get_nominalref(self, ...)) +end diff --git a/Cryptid/lib/modifiers.lua b/Cryptid/lib/modifiers.lua index fb80535..6deaaa4 100644 --- a/Cryptid/lib/modifiers.lua +++ b/Cryptid/lib/modifiers.lua @@ -318,14 +318,7 @@ function Card:update(dt) if self.flipping == "f2b" then self.flipping = "b2f" end - self:dbl_side_flip() - end - if self.ability.cry_absolute then -- feedback loop... may be problematic - self.cry_absolute = true - end - if self.cry_absolute then - self.ability.cry_absolute = true - self.ability.eternal = true + self:flip_side() end if self.ability.pinned then self.pinned = true @@ -395,7 +388,7 @@ function cry_best_interest_cap() } for _, table in ipairs(vouchers) do for i, v in ipairs(table) do - if v.ability.extra >= best then + if to_big(v.ability.extra) >= to_big(best) then best = v.ability.extra end end @@ -407,6 +400,7 @@ G.FUNCS.evaluate_round = function() G.GAME.interest_cap = cry_best_interest_cap() -- blehhhhhh --Semicolon Stuff if G.GAME.current_round.semicolon then + G.GAME.saved_text = ";" add_round_eval_row({ dollars = 0, name = "blind1", pitch = 0.95, saved = true }) G.E_MANAGER:add_event(Event({ trigger = "before", @@ -578,7 +572,7 @@ function Card:set_eternal(_eternal) end function Card:calculate_banana() if not self.ability.extinct then - if self.ability.banana and (pseudorandom("banana") < G.GAME.probabilities.normal / 10) then + if self.ability.banana and SMODS.pseudorandom_probability(self, "banana", 1, 10, "Banana Sticker") then self.ability.extinct = true G.E_MANAGER:add_event(Event({ func = function() @@ -676,6 +670,16 @@ SMODS.Sticker:take_ownership("eternal", { return { key = "cry_eternal_booster" } end end, + draw = function(self, card) + local notilt = nil + if card.area and card.area.config.type == "deck" then + notilt = true + end + if not card.ability.cry_absolute then + G.shared_stickers[self.key].role.draw_major = card + G.shared_stickers[self.key]:draw_shader("dissolve", nil, nil, notilt, card.children.center) + end + end, }) SMODS.Sticker:take_ownership("rental", { loc_vars = function(self, info_queue, card) @@ -713,13 +717,16 @@ SMODS.Sticker({ should_apply = false, loc_vars = function(self, info_queue, card) if card.ability.consumeable then - return { key = "cry_banana_consumeable", vars = { G.GAME.probabilities.normal or 1, 4 } } + return { + key = "cry_banana_consumeable", + vars = { SMODS.get_probability_vars(card, 1, 4, "Banana Sticker") }, + } elseif card.ability.set == "Voucher" then - return { key = "cry_banana_voucher", vars = { G.GAME.probabilities.normal or 1, 12 } } + return { key = "cry_banana_voucher", vars = { SMODS.get_probability_vars(card, 1, 12, "Banana Sticker") } } elseif card.ability.set == "Booster" then return { key = "cry_banana_booster" } else - return { vars = { G.GAME.probabilities.normal or 1, 10 } } + return { vars = { SMODS.get_probability_vars(card, 1, 10, "Banana Sticker") } } end end, calculate = function(self, card, context) @@ -730,7 +737,15 @@ SMODS.Sticker({ and not context.individual then if card.ability.set == "Voucher" then - if pseudorandom("byebyevoucher") < G.GAME.probabilities.normal / G.GAME.cry_voucher_banana_odds then + if + SMODS.pseudorandom_probability( + card, + "byebyevoucher", + 1, + G.GAME.cry_voucher_banana_odds, + "Banana Sticker" + ) + then local area if G.STATE == G.STATES.HAND_PLAYED then if not G.redeemed_vouchers_during_hand then @@ -873,78 +888,70 @@ function G.UIDEF.used_vouchers() { n = G.UIT.R, config = { align = "cm", padding = 0, no_fill = true }, nodes = voucher_tables } ) + -- Code by IcyEthics: Generates sliders dynamically + local cryptid_voucher_nodes = {} + if silent then + for i, _info in ipairs(Cryptid.voucher_acclimator_data) do + if next(SMODS.find_card(_info.voucher_key)) then + cryptid_voucher_nodes[#cryptid_voucher_nodes + 1] = { + n = G.UIT.R, + config = { align = "cm" }, + nodes = { + create_slider({ + label = localize(_info.localization_key), + label_scale = 0.4, + text_scale = 0.3, + w = 4, + h = 0.4, + ref_table = G.GAME.cry_percrate, + ref_value = _info.ref_value, + colour = _info.colour, + min = 0, + max = 100, + }), + }, + } + end + end + + cryptid_voucher_nodes[#cryptid_voucher_nodes + 1] = { + n = G.UIT.R, + config = { align = "cm" }, + nodes = { + { + n = G.UIT.O, + config = { + object = DynaText({ + string = { localize("ph_vouchers_redeemed") }, + colours = { G.C.UI.TEXT_LIGHT }, + bump = true, + scale = 0.6, + }), + }, + }, + }, + } + + cryptid_voucher_nodes[#cryptid_voucher_nodes + 1] = { + n = G.UIT.R, + config = { align = "cm", minh = 0.5 }, + nodes = {}, + } + + cryptid_voucher_nodes[#cryptid_voucher_nodes + 1] = { + n = G.UIT.R, + config = { align = "cm", colour = G.C.BLACK, r = 1, padding = 0.15, emboss = 0.05 }, + nodes = { + { n = G.UIT.R, config = { align = "cm" }, nodes = voucher_table_rows }, + }, + } + end + local t = silent and { n = G.UIT.ROOT, config = { align = "cm", colour = G.C.CLEAR }, - nodes = { - - -- tarot/planet acclimator sliders - next(SMODS.find_card("v_cry_tacclimator")) - and { - n = G.UIT.R, - config = { align = "cm" }, - nodes = { - create_slider({ - label = localize("b_tarot_rate"), - label_scale = 0.4, - text_scale = 0.3, - w = 4, - h = 0.4, - ref_table = G.GAME.cry_percrate, - ref_value = "tarot", - colour = G.C.SECONDARY_SET.Tarot, - min = 0, - max = 100, - }), - }, - } - or nil, - next(SMODS.find_card("v_cry_pacclimator")) and { - n = G.UIT.R, - config = { align = "cm" }, - nodes = { - create_slider({ - label = localize("b_planet_rate"), - label_scale = 0.4, - text_scale = 0.3, - w = 4, - h = 0.4, - ref_table = G.GAME.cry_percrate, - ref_value = "planet", - colour = G.C.SECONDARY_SET.Planet, - min = 0, - max = 100, - }), - }, - } or nil, - - { - n = G.UIT.R, - config = { align = "cm" }, - nodes = { - { - n = G.UIT.O, - config = { - object = DynaText({ - string = { localize("ph_vouchers_redeemed") }, - colours = { G.C.UI.TEXT_LIGHT }, - bump = true, - scale = 0.6, - }), - }, - }, - }, - }, - { n = G.UIT.R, config = { align = "cm", minh = 0.5 }, nodes = {} }, - { - n = G.UIT.R, - config = { align = "cm", colour = G.C.BLACK, r = 1, padding = 0.15, emboss = 0.05 }, - nodes = { - { n = G.UIT.R, config = { align = "cm" }, nodes = voucher_table_rows }, - }, - }, - }, + nodes = cryptid_voucher_nodes, } or { n = G.UIT.ROOT, diff --git a/Cryptid/lib/overrides.lua b/Cryptid/lib/overrides.lua index ca92b75..d27325e 100644 --- a/Cryptid/lib/overrides.lua +++ b/Cryptid/lib/overrides.lua @@ -1,5 +1,45 @@ -- overrides.lua - Adds hooks and overrides used by multiple features. +--Get Pack hooks + +-- dumb hook because i don't feel like aggressively patching get_pack to do stuff +-- very inefficient +-- maybe smods should overwrite the function and make it more targetable? +local getpackref = get_pack +function get_pack(_key, _type) + local temp_banned = copy_table(G.GAME.banned_keys) + --Add banished keys (via DELETE) to banned_keys so they don't appear in shop + for k, v in pairs(G.GAME.cry_banished_keys) do + G.GAME.banned_keys[k] = v + end + local abc = getpackref(_key, _type) + --Convert banned keys back to what it was originally + G.GAME.banned_keys = copy_table(temp_banned) + if G.GAME.modifiers.cry_equilibrium then + if not P_CRY_ITEMS then + P_CRY_ITEMS = {} + local valid_pools = { "Joker", "Consumeables", "Voucher", "Booster" } + for _, id in ipairs(valid_pools) do + for k, v in pairs(G.P_CENTER_POOLS[id]) do + if not Cryptid.no(v, "doe", k) then + P_CRY_ITEMS[#P_CRY_ITEMS + 1] = v.key + end + end + end + for k, v in pairs(G.P_CARDS) do + if not Cryptid.no(v, "doe", k) then + P_CRY_ITEMS[#P_CRY_ITEMS + 1] = v.key + end + end + end + return G.P_CENTERS[pseudorandom_element( + P_CRY_ITEMS, + pseudoseed("cry_equipackbrium" .. G.GAME.round_resets.ante) + )] + end + return abc +end + -- get_currrent_pool hook for Deck of Equilibrium and Copies local gcp = get_current_pool function get_current_pool(_type, _rarity, _legendary, _append, override_equilibrium_effect) @@ -21,7 +61,7 @@ function get_current_pool(_type, _rarity, _legendary, _append, override_equilibr pool[i] = "tag_cry_quintuple" end end - -- Deck of Equilibrium stuff + -- Deck of Equilibrium stuff elseif G.GAME.modifiers.cry_equilibrium and not override_equilibrium_effect @@ -57,16 +97,37 @@ function get_current_pool(_type, _rarity, _legendary, _append, override_equilibr end return gcp(_type, _rarity, _legendary, _append) end + local gnb = get_new_boss function get_new_boss() + local bl = gnb() --Fix an issue with adding bosses mid-run for k, v in pairs(G.P_BLINDS) do if not G.GAME.bosses_used[k] then G.GAME.bosses_used[k] = 0 end end + -- Force Clock and Lavender Loop for Rush hour + if G.GAME.modifiers.cry_rush_hour then + --Check if Clock and Lavender Loop are both enabled + if (Cryptid.enabled("bl_cry_clock") == true) and (Cryptid.enabled("bl_cry_lavender_loop") == true) then + return (G.GAME.round_resets.ante % G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2) + and "bl_cry_lavender_loop" + or "bl_cry_clock" + else + -- Note: code elsewhere will force losses until both blinds are enabled + return bl + end + end + -- Log + if G.GAME.LOG_BOSS then + local v = "" .. G.GAME.LOG_BOSS + if not G.GAME.USING_LOG then + G.GAME.LOG_BOSS = nil + end + return v + end --This is how nostalgic deck replaces the boss blinds with Nostalgic versions - local bl = gnb() if G.GAME.modifiers.cry_beta then local bl_key = string.sub(bl, 4) local nostalgicblinds = { @@ -94,30 +155,53 @@ function G.FUNCS.evaluate_play(e) G.GAME.blind:cry_after_play() end ---Add context for Just before cards are played -local pcfh = G.FUNCS.play_cards_from_highlighted -function G.FUNCS.play_cards_from_highlighted(e) - G.GAME.before_play_buffer = true - G.GAME.blind:cry_before_play() - pcfh(e) - G.GAME.before_play_buffer = nil -end - --Track defeated blinds for Obsidian Orb local dft = Blind.defeat function Blind:defeat(s) dft(self, s) local obj = self.config.blind - -- Ignore blinds with loc_vars because orb does not properly work with them yet - if obj.boss and (obj.boss.no_orb or obj.boss.epic or obj.loc_vars) then + if + (obj.boss and obj.boss.yes_orb) + or ( + obj.name == "The Hook" + or obj.name == "The Ox" + or obj.name == "The House" + or obj.name == "The Wall" + or obj.name == "The Wheel" + or obj.name == "The Arm" + or obj.name == "The Club" + or obj.name == "The Fish" + or obj.name == "The Psychic" + or obj.name == "The Goad" + or obj.name == "The Water" + or obj.name == "The Window" + or obj.name == "The Manacle" + or obj.name == "The Eye" + or obj.name == "The Mouth" + or obj.name == "The Plant" + or obj.name == "The Serpent" + or obj.name == "The Pillar" + or obj.name == "The Needle" + or obj.name == "The Head" + or obj.name == "The Tooth" + or obj.name == "The Flint" + or obj.name == "The Mark" + or obj.name == "Amber Acorn" + or obj.name == "Verdant Leaf" + or obj.name == "Violet Vessel" + or obj.name == "Crimsion Heart" + or obj.name == "Cerulean Bell" + ) + then + else return end if - self.name ~= "cry-Obsidian Orb" --Stop impossible blind combinations from happening - and self.name ~= "The Sink" - and (self.name ~= "cry-oldarm" or not G.GAME.defeated_blinds["bl_psychic"]) + (self.name ~= "cry-oldarm" or not G.GAME.defeated_blinds["bl_psychic"]) and (self.name ~= "The Psychic" or not G.GAME.defeated_blinds["bl_cry_oldarm"]) + and (self.name ~= "cry-oldarm" or not G.GAME.defeated_blinds["bl_cry_scorch"]) + and (self.name ~= "cry-scorch" or not G.GAME.defeated_blinds["bl_cry_oldarm"]) and (self.name ~= "The Eye" or not G.GAME.defeated_blinds["bl_mouth"]) and (self.name ~= "The Mouth" or not G.GAME.defeated_blinds["bl_eye"]) and (self.name ~= "cry-Lavender Loop" or not G.GAME.defeated_blinds["bl_cry_tax"]) @@ -125,7 +209,7 @@ function Blind:defeat(s) and (self.name ~= "The Needle" or not G.GAME.defeated_blinds["bl_cry_tax"]) and (self.name ~= "cry-Tax" or not G.GAME.defeated_blinds["bl_needle"]) then - G.GAME.defeated_blinds[self.config.blind.key] = true + G.GAME.defeated_blinds[self.config.blind.key or ""] = true end end @@ -166,6 +250,7 @@ function reset_blinds() end rb() end + --Init stuff at the start of the game local gigo = Game.init_game_object function Game:init_game_object() @@ -174,40 +259,53 @@ function Game:init_game_object() g.current_round.cry_nb_card = { rank = "Ace" } g.current_round.cry_dropshot_card = { suit = "Spades" } g.monstermult = 1 + g.neutronstarsusedinthisrun = 0 + g.sunlevel = 1 + g.sunnumber = { modest = 0, not_modest = 0 } + g.bonus_asc_power = 0 + g.cry_oboe = 0 + g.boostertag = 0 -- Create G.GAME.events when starting a run, so there's no errors g.events = {} g.jokers_sold = {} + g.cry_banished_keys = {} + g.cry_last_used_consumeables = {} + g.cry_function_stupid_workaround = {} + + -- Added by IcyEthics: Converted the voucher-related modifiers for the tier 3 + -- acclimator vouchers to be more generically accessible + g.cry_bonusvouchercount = 0 + g.cry_bonusvouchersused = {} + + -- Automatically sets up the cry_percrate for each consumable type and sets it to 100 as a default + g.cry_percrate = {} + for _, v in ipairs(SMODS.ConsumableType.ctype_buffer) do + g.cry_percrate[v:lower()] = 100 + end + return g end -- reset_castle_card hook for things like Dropshot and Number Blocks +-- Also exclude specific ranks/suits (such as abstract cards) local rcc = reset_castle_card function reset_castle_card() rcc() G.GAME.current_round.cry_nb_card = { rank = "Ace" } - if not G.GAME.current_round.cry_dropshot_card then - G.GAME.current_round.cry_dropshot_card = {} - end - G.GAME.current_round.cry_dropshot_card.suit = "Spades" + G.GAME.current_round.cry_dropshot_card = { suit = "Spades" } local valid_castle_cards = {} for k, v in ipairs(G.playing_cards) do - if not SMODS.has_no_suit(v) then + if not SMODS.has_no_suit(v) and not SMODS.has_enhancement(v, "m_cry_abstract") then valid_castle_cards[#valid_castle_cards + 1] = v end end if valid_castle_cards[1] then --Dropshot local castle_card = pseudorandom_element(valid_castle_cards, pseudoseed("cry_dro" .. G.GAME.round_resets.ante)) - if not G.GAME.current_round.cry_dropshot_card then - G.GAME.current_round.cry_dropshot_card = {} - end G.GAME.current_round.cry_dropshot_card.suit = castle_card.base.suit --Number Blocks local castle_card_two = pseudorandom_element(valid_castle_cards, pseudoseed("cry_nb" .. G.GAME.round_resets.ante)) - if not G.GAME.current_round.cry_nb_card then - G.GAME.current_round.cry_nb_card = {} - end G.GAME.current_round.cry_nb_card.rank = castle_card_two.base.value G.GAME.current_round.cry_nb_card.id = castle_card_two.base.id end @@ -251,13 +349,27 @@ Cryptid.C = { SELECTED = { HEX("e38039"), HEX("ccdd1b") }, GREENGRADIENT = { HEX("51e099"), HEX("1e523a") }, ALTGREENGRADIENT = { HEX("6bb565"), HEX("bd28bf") }, + TAX_MULT = { HEX("FE5F55"), HEX("40ff40") }, + TAX_CHIPS = { HEX("009dff"), HEX("40ff40") }, } cry_pointer_dt = 0 cry_jimball_dt = 0 cry_glowing_dt = 0 +cry_glowing_dt2 = 0 +local none_eval = 0 function Game:update(dt) upd(self, dt) - + if not Cryptid.member_count_delay then + Cryptid.member_count_delay = 0 + end + if (Cryptid.member_count_delay > 5) or not Cryptid.member_count then -- it doesn't need to update this frequently? but it also doesn't need to be higher tbh... + if Cryptid.update_member_count then + Cryptid.update_member_count() + end -- i honestly hate nil checks like this, wish there was a shorthand + Cryptid.member_count_delay = 0 + else + Cryptid.member_count_delay = Cryptid.member_count_delay + dt + end --Gradients based on Balatrostuck code local anim_timer = self.TIMERS.REAL * 1.5 local p = 0.5 * (math.sin(anim_timer) + 1) @@ -281,6 +393,7 @@ function Game:update(dt) cry_pointer_dt = cry_pointer_dt + dt cry_jimball_dt = cry_jimball_dt + dt cry_glowing_dt = cry_glowing_dt + dt + cry_glowing_dt2 = cry_glowing_dt2 + dt end --Update sprite positions each frame on certain cards to give the illusion of an animated card if G.P_CENTERS and G.P_CENTERS.c_cry_pointer and cry_pointer_dt > 0.5 then @@ -314,25 +427,32 @@ function Game:update(dt) glowingobj.pos.y = glowingobj.pos.y + 1 end end + if G.P_CENTERS and G.P_CENTERS.sleeve_cry_glowing_sleeve and cry_glowing_dt2 > 0.1 then + cry_glowing_dt2 = 0 + local glowingobj = G.P_CENTERS.sleeve_cry_glowing_sleeve + if glowingobj.pos.x == 1 and glowingobj.pos.y == 4 then + glowingobj.pos.x = 0 + glowingobj.pos.y = 0 + elseif glowingobj.pos.x < 4 then + glowingobj.pos.x = glowingobj.pos.x + 1 + elseif glowingobj.pos.y < 6 then + glowingobj.pos.x = 0 + glowingobj.pos.y = glowingobj.pos.y + 1 + end + end for k, v in pairs(G.I.CARD) do if v.children.back and v.children.back.atlas.name == "cry_glowing" then v.children.back:set_sprite_pos(G.P_CENTERS.b_cry_glowing.pos or G.P_CENTERS["b_red"].pos) end end - if not G.OVERLAY_MENU and not G.CHOOSE_CARD and G.GAME.USING_POINTER then - G.CHOOSE_CARD = UIBox({ - definition = create_UIBox_pointer(card), - config = { - align = "cm", - offset = { x = 0, y = 10 }, - major = G.ROOM_ATTACH, - bond = "Weak", - instance_type = "POPUP", - }, - }) - G.CHOOSE_CARD.alignment.offset.y = 0 - G.ROOM.jiggle = G.ROOM.jiggle + 1 - G.CHOOSE_CARD:align_to_major() + if not G.OVERLAY_MENU and G.GAME.CODE_DESTROY_CARD and not G.OVERLAY_MENU_POINTER then + G.FUNCS.exit_overlay_menu_code() + end + + if not G.OVERLAY_MENU then + G.GAME.USING_POINTER = nil + else + G.OVERLAY_MENU_POINTER = nil end --Increase the blind size for The Clock and Lavender Loop @@ -368,9 +488,7 @@ function Game:update(dt) G.GAME.CRY_BLINDS[c] = (G.GAME.CRY_BLINDS[c] or G.P_BLINDS[G.GAME.round_resets.blind_choices[c]].mult) + ( G.P_BLINDS[G.GAME.round_resets.blind_choices[c]].cry_ante_base_mod - and G.P_BLINDS[G.GAME.round_resets.blind_choices[c]]:cry_ante_base_mod( - dt * (G.GAME.modifiers.cry_rush_hour_iii and 2 or 1) - ) + and G.P_BLINDS[G.GAME.round_resets.blind_choices[c]]:cry_ante_base_mod(dt) or 0 ) --Update UI @@ -408,7 +526,7 @@ function Game:update(dt) and to_big(G.GAME.chips) < to_big(G.GAME.blind.chips) then G.GAME.blind.chips = G.GAME.blind.chips - + G.GAME.blind:cry_ante_base_mod(dt * (G.GAME.modifiers.cry_rush_hour_iii and 2 or 1)) + + G.GAME.blind:cry_ante_base_mod(dt) * get_blind_amount(G.GAME.round_resets.ante) * G.GAME.starting_params.ante_scaling G.GAME.blind.chip_text = number_format(G.GAME.blind.chips) @@ -422,21 +540,30 @@ function Game:update(dt) and to_big(G.GAME.chips) < to_big(G.GAME.blind.chips) then G.GAME.blind.chips = G.GAME.blind.chips - * ( - G.GAME.blind.cry_round_base_mod - and G.GAME.blind:cry_round_base_mod(dt * (G.GAME.modifiers.cry_rush_hour_iii and 2 or 1)) - or 1 - ) + * (G.GAME.blind.cry_round_base_mod and G.GAME.blind:cry_round_base_mod(dt) or 1) G.GAME.blind.chip_text = number_format(G.GAME.blind.chips) end end + if + G.STATE == G.STATES.DRAW_TO_HAND + and not G.hand.cards[1] + and not G.deck.cards[1] + and G.PROFILES[G.SETTINGS.profile].cry_none + then + G.STATE = G.STATES.SELECTING_HAND + G.STATE_COMPLETE = false + end + if G.STATE == G.STATES.NEW_ROUND or G.STATE == G.STATES.HAND_PLAYED then + none_eval = none_eval + dt + else + none_eval = 0 + end end -- All the scattered set_cost hooks from all the pre refactor files moved into one hook local sc = Card.set_cost function Card:set_cost() -- Makes the edition cost increase usually present not apply if this variable is true - -- Used for some of the Jen's almanac edition decks because having the price increase apply was "unfun" if self.edition and G.GAME.modifiers.cry_no_edition_price then local m = Cryptid.deep_copy(self.edition) self.edition = nil @@ -456,25 +583,48 @@ function Card:set_cost() if self.ability.name == "cry-Big Cube" then self.cost = 27 end + --Make Tarots free if Tarot Acclimator is redeemed + --Make Planets free if Planet Acclimator is redeemed + if self.ability.set == "Tarot" and G.GAME.used_vouchers.v_cry_tacclimator then + self.cost = 0 + end + if self.ability.set == "Planet" and G.GAME.used_vouchers.v_cry_pacclimator then + self.cost = 0 + end --Multiplies voucher cost by G.GAME.modifiers.cry_voucher_price_hike --Used by bronze stake to make vouchers %50 more expensive if self.ability.set == "Voucher" and G.GAME.modifiers.cry_voucher_price_hike then self.cost = math.floor(self.cost * G.GAME.modifiers.cry_voucher_price_hike) - --Update related costs - self.sell_cost = math.max(1, math.floor(self.cost / 2)) + (self.ability.extra_value or 0) - if self.area and self.ability.couponed and (self.area == G.shop_jokers or self.area == G.shop_booster) then - self.cost = 0 + end + --Clone Tag + for i = 1, #G.GAME.tags do + if G.GAME.tags[i].key == "tag_cry_clone" then + self.cost = self.cost * 1.5 + break end - self.sell_cost_label = self.facing == "back" and "?" or self.sell_cost end + --Update related costs + self.sell_cost = math.max(1, math.floor(self.cost / 2)) + (self.ability.extra_value or 0) + if + self.area + and self.ability.couponed + and (self.area == G.shop_jokers or self.area == G.shop_booster) + and self.ability.name ~= "cry-Cube" + then + self.cost = 0 + end --Makes Cursed Jokers always sell for $0 if self.config and self.config.center and self.config.center.rarity == "cry_cursed" then self.sell_cost = 0 - self.sell_cost_label = 0 + --Rotten Egg + elseif G.GAME.cry_rotten_amount then + self.sell_cost = G.GAME.cry_rotten_amount end + self.sell_cost_label = self.facing == "back" and "?" or self.sell_cost end + local sell_card_stuff = Card.sell_card function Card:sell_card() if self.config.center.set == "Joker" then @@ -504,7 +654,6 @@ function Card:sell_card() end end end - --G.P_CENTERS.j_jolly sell_card_stuff(self) end @@ -655,7 +804,13 @@ function SMODS.create_mod_badges(obj, badges) } end end - if Cryptid.safe_get(G, "ACTIVE_MOD_UI", "id") == "Cryptid" and obj and not obj.force_gameset then + local id = obj and obj.mod and obj.mod.id + if + Cryptid.safe_get(G, "ACTIVE_MOD_UI", "id") == id + and obj + and not obj.force_gameset + and Cryptid.mod_gameset_whitelist[id] + then local set = Cryptid.gameset(obj) if set == "disabled" or obj.set == "Content Set" then return @@ -676,6 +831,14 @@ end -- This is short enough that I'm fine overriding it function calculate_reroll_cost(skip_increment) + local limit = G.GAME.reroll_limit_buffer or nil + if not limit then + if next(find_joker("cry-candybuttons")) then + limit = 1 + elseif G.GAME.used_vouchers.v_cry_rerollexchange then + limit = 2 + end + end if not G.GAME.current_round.free_rerolls or G.GAME.current_round.free_rerolls < 0 then G.GAME.current_round.free_rerolls = 0 end @@ -683,14 +846,17 @@ function calculate_reroll_cost(skip_increment) G.GAME.current_round.reroll_cost = 0 return end - if next(find_joker("cry-candybuttons")) then - G.GAME.current_round.reroll_cost = 1 - return - end - if G.GAME.used_vouchers.v_cry_rerollexchange then - G.GAME.current_round.reroll_cost = 2 + if + limit + and (G.GAME.round_resets.temp_reroll_cost or G.GAME.round_resets.reroll_cost) + + G.GAME.current_round.reroll_cost_increase + >= limit + then + G.GAME.current_round.reroll_cost_increase = 0 + G.GAME.current_round.reroll_cost = limit return end + G.GAME.current_round.reroll_cost_increase = G.GAME.current_round.reroll_cost_increase or 0 if not skip_increment then G.GAME.current_round.reroll_cost_increase = G.GAME.current_round.reroll_cost_increase @@ -700,7 +866,7 @@ function calculate_reroll_cost(skip_increment) + G.GAME.current_round.reroll_cost_increase end --- We're modifying so much of this for Brown and Yellow Stake, Equilibrium Deck, etc. that it's fine to override... +local create_card_ref = create_card function create_card(_type, area, legendary, _rarity, skip_materialize, soulable, forced_key, key_append) local area = area or G.jokers local pseudo = function(x) @@ -713,7 +879,6 @@ function create_card(_type, area, legendary, _rarity, skip_materialize, soulable end ps = Cryptid.predict_pseudoseed end - local center = G.P_CENTERS.b_red if (_type == "Joker" or _type == "Meme") and G.GAME and G.GAME.modifiers and G.GAME.modifiers.all_rnj then forced_key = "j_cry_rnjoker" end @@ -738,64 +903,18 @@ function create_card(_type, area, legendary, _rarity, skip_materialize, soulable forced_key = G.P_CENTER_POOLS["Joker"][aeqactive].key end end - --should pool be skipped with a forced key - if not forced_key and soulable and not G.GAME.banned_keys["c_soul"] then - for _, v in ipairs(SMODS.Consumable.legendaries) do - if - (_type == v.type.key or _type == v.soul_set) - and not (G.GAME.used_jokers[v.key] and not next(find_joker("Showman")) and not v.can_repeat_soul) - then - if pseudo("soul_" .. v.key .. _type .. G.GAME.round_resets.ante) > (1 - v.soul_rate) then - forced_key = v.key - end - end - end - if - (_type == "Tarot" or _type == "Spectral" or _type == "Tarot_Planet") - and not (G.GAME.used_jokers["c_soul"] and not next(find_joker("Showman"))) - then - if pseudo("soul_" .. _type .. G.GAME.round_resets.ante) > 0.997 then - forced_key = "c_soul" - end - end - if - (_type == "Planet" or _type == "Spectral") - and not (G.GAME.used_jokers["c_black_hole"] and not next(find_joker("Showman"))) - then - if pseudo("soul_" .. _type .. G.GAME.round_resets.ante) > 0.997 then - forced_key = "c_black_hole" - end - end - end - if _type == "Base" then forced_key = "c_base" end - if forced_key then --vanilla behavior change, mainly for M Joker reasons - center = G.P_CENTERS[forced_key] - _type = (center.set ~= "Default" and center.set or _type) - else - gcparea = area - local _pool, _pool_key = get_current_pool(_type, _rarity, legendary, key_append) - gcparea = nil - center = pseudorandom_element(_pool, ps(_pool_key)) - local it = 1 - while center == "UNAVAILABLE" do - it = it + 1 - center = pseudorandom_element(_pool, ps(_pool_key .. "_resample" .. it)) - end - - center = G.P_CENTERS[center] + if forced_key and not G.GAME.banned_keys[forced_key] then + _type = (G.P_CENTERS[forced_key].set ~= "Default" and G.P_CENTERS[forced_key].set or _type) end - local front = ( - (_type == "Base" or _type == "Enhanced") - and pseudorandom_element(G.P_CARDS, ps("front" .. (key_append or "") .. G.GAME.round_resets.ante)) - ) or nil + local front = (SMODS.set_create_card_front and (_type == "Base" or _type == "Enhanced")) or nil if area == "ERROR" then - local ret = (front or center) + local ret = (front or G.P_CENTERS[forced_key] or G.P_CENTERS.b_red) if not ret.config then ret.config = {} end @@ -811,28 +930,8 @@ function create_card(_type, area, legendary, _rarity, skip_materialize, soulable return ret --the config.center.key stuff prevents a crash with Jen's Almanac hook end - local card = Card( - area and (area.T.x + area.T.w / 2) or 0, - area and area.T.y or 0, - G.CARD_W * (center and center.set == "Booster" and 1.27 or 1), - G.CARD_H * (center and center.set == "Booster" and 1.27 or 1), - front, - center, - { - bypass_discovery_center = area == G.shop_jokers - or area == G.pack_cards - or area == G.shop_vouchers - or (G.shop_demo and area == G.shop_demo) - or area == G.jokers - or area == G.consumeables, - bypass_discovery_ui = area == G.shop_jokers - or area == G.pack_cards - or area == G.shop_vouchers - or (G.shop_demo and area == G.shop_demo), - discover = area == G.jokers or area == G.consumeables, - bypass_back = G.GAME.selected_back.pos, - } - ) + local card = create_card_ref(_type, area, legendary, _rarity, skip_materialize, soulable, forced_key, key_append) + local center = card and card.config and card.config.center or {} if front and G.GAME.modifiers.cry_force_suit then card:change_suit(G.GAME.modifiers.cry_force_suit) end @@ -841,23 +940,11 @@ function create_card(_type, area, legendary, _rarity, skip_materialize, soulable end if front and G.GAME.modifiers.cry_force_edition then card:set_edition({ [G.GAME.modifiers.cry_force_edition] = true }, true, true) + card:add_to_deck() end if front and G.GAME.modifiers.cry_force_seal then card:set_seal(G.GAME.modifiers.cry_force_seal) end - if card.ability.consumeable and not skip_materialize then - card:start_materialize() - end - for k, v in ipairs(SMODS.Sticker.obj_buffer) do - local sticker = SMODS.Stickers[v] - if - sticker.should_apply - and type(sticker.should_apply) == "function" - and sticker:should_apply(card, center, area) - then - sticker:apply(card, true) - end - end if G.GAME.modifiers.cry_force_sticker == "eternal" or ( @@ -998,25 +1085,24 @@ function create_card(_type, area, legendary, _rarity, skip_materialize, soulable end end if - not card.ability.eternal + not SMODS.is_eternal(card) and G.GAME.modifiers.cry_enable_flipped_in_shop and pseudorandom("cry_flip" .. (key_append or "") .. G.GAME.round_resets.ante) > 0.7 then card.cry_flipped = true end end - if _type == "Joker" and not G.GAME.modifiers.cry_force_edition then - local edition = poll_edition("edi" .. (key_append or "") .. G.GAME.round_resets.ante) - card:set_edition(edition) - check_for_unlock({ type = "have_edition" }) - end end - if - (card.ability.set == "Code") - and G.GAME.used_vouchers.v_cry_quantum_computing - and pseudorandom("cry_quantum_computing") > 0.7 - then - card:set_edition({ negative = true }) + if (card.ability.set == "Code") and G.GAME.used_vouchers.v_cry_quantum_computing then + local tot = 0 + for k, v in pairs(SMODS.find_card("v_cry_quantum_computing")) do + tot = tot + v.ability.extra + end + if card.ability.cry_multiuse then + card.ability.cry_multiuse = math.ceil((card.ability.cry_multiuse + tot)) + else + card.ability.cry_multiuse = tot + 1 + end end if G.GAME.modifiers.cry_force_edition @@ -1030,16 +1116,16 @@ function create_card(_type, area, legendary, _rarity, skip_materialize, soulable card:set_edition(edition, true) end if not (card.edition and (card.edition.cry_oversat or card.edition.cry_glitched)) then - Cryptid.misprintize(card) + Cryptid.manipulate(card) end if card.ability.set == "Joker" and G.GAME.modifiers.cry_common_value_quad then if card.config.center.rarity == 1 then - Cryptid.misprintize(card, { min = 4, max = 4 }, nil, true) + Cryptid.manipulate(card, { value = 4 }) end end if card.ability.set == "Joker" and G.GAME.modifiers.cry_uncommon_value_quad then if card.config.center.rarity == 2 then - Cryptid.misprintize(card, { min = 4, max = 4 }, nil, true) + Cryptid.manipulate(card, { value = 4 }) end end if card.ability.consumeable and card.pinned then -- counterpart is in Sticker.toml @@ -1071,68 +1157,22 @@ function create_card(_type, area, legendary, _rarity, skip_materialize, soulable -- during the update function. Cryptid can create jokers mid-scoring, meaning -- those values will be unset during scoring unless update() is manually called. card:update(0.016) -- dt is unused in the base game, but we're providing a realistic value anyway - - --Debuff jokers if certain boss blinds are active - if _type == "Joker" and G.GAME and G.GAME.blind and not G.GAME.blind.disabled then - if - G.GAME.blind.name == "cry-box" - or (G.GAME.blind.name == "cry-Obsidian Orb" and G.GAME.defeated_blinds["bl_cry_box"] == true) - then - if card.config.center.rarity == 1 and not card.debuff then - card.debuff = true - card.debuffed_by_blind = true - end - end - if - G.GAME.blind.name == "cry-windmill" - or (G.GAME.blind.name == "cry-Obsidian Orb" and G.GAME.defeated_blinds["bl_cry_windmill"] == true) - then - if card.config.center.rarity == 2 and not card.debuff then - card.debuff = true - card.debuffed_by_blind = true - end - end - if - G.GAME.blind.name == "cry-striker" - or (G.GAME.blind.name == "cry-Obsidian Orb" and G.GAME.defeated_blinds["bl_cry_striker"] == true) - then - if card.config.center.rarity == 3 and not card.debuff then - card.debuff = true - card.debuffed_by_blind = true - end - end - if - G.GAME.blind.name == "cry-shackle" - or (G.GAME.blind.name == "cry-Obsidian Orb" and G.GAME.defeated_blinds["bl_cry_shackle"] == true) - then - if (card.edition and card.edition.negative == true) and not card.debuff then - card.debuff = true - card.debuffed_by_blind = true - end - end - if - G.GAME.blind.name == "cry-pin" - or (G.GAME.blind.name == "cry-Obsidian Orb" and G.GAME.defeated_blinds["bl_cry_pin"] == true) - then - if - card.config.center.rarity ~= 3 - and card.config.center.rarity ~= 2 - and card.config.center.rarity ~= 1 - and card.config.center.rarity ~= 5 - then - card.debuff = true - card.debuffed_by_blind = true - end - end - end return card end --- Make tags fit if there's more than 13 of them --- These two overrides modify the offset to squeeze in more tags when needed local at = add_tag function add_tag(tag) at(tag) + -- Update Costs for Clone Tag + if tag.name == "cry-Clone Tag" then + for k, v in pairs(G.I.CARD) do + if v.set_cost then + v:set_cost() + end + end + end + -- Make tags fit if there's more than 13 of them + -- This + Tag.remove Hook modify the offset to squeeze in more tags when needed if #G.HUD_tags > 13 then for i = 2, #G.HUD_tags do G.HUD_tags[i].config.offset.y = 0.9 - 0.9 * 13 / #G.HUD_tags @@ -1150,45 +1190,87 @@ function Tag:remove() end end ---add calculation context and callback to tag function ---used for Energia, etc. -local at2 = add_tag -function add_tag(tag, from_skip, no_copy) - if no_copy then - at2(tag) - return - end - local added_tags = 1 - local ret = {} - SMODS.calculate_context({ cry_add_tag = true }, ret) - for i = 1, #ret do - if ret[i].jokers then - added_tags = added_tags + (ret[i].jokers.tags or 0) +local nr = new_round +function new_round() + -- I don't remember exactly what this patch was for, perhaps issues with syncing hand size with jokers like Effarcire? + G.hand:change_size(0) + nr() + -- Reset Semicolon + G.GAME.current_round.semicolon = false + -- Force losses if Rush hour is played with clock and lavender loop disabled + if G.GAME.modifiers.cry_rush_hour then + if not (Cryptid.enabled("bl_cry_clock") == true) or not (Cryptid.enabled("bl_cry_lavender_loop") == true) then + G.E_MANAGER:add_event(Event({ + func = function() + if G.STAGE == G.STAGES.RUN then + G.STATE = G.STATES.GAME_OVER + G.STATE_COMPLETE = false + end + print(localize("rush_hour_reminder")) + return true + end, + })) end end - if added_tags >= 1 then - at2(tag) - end - for i = 2, added_tags do - local ab = copy_table(G.GAME.tags[#G.GAME.tags].ability) - local new_tag = Tag(tag.key) - at2(new_tag) - new_tag.ability = ab - end end --- I don't remember exactly what this patch was for, perhaps issues with syncing hand size with jokers like Effarcire? -local nr = new_round -function new_round() - G.hand:change_size(0) - nr() +local stamp_can_play = G.FUNCS.can_play +G.FUNCS.can_play = function(e) + local value = 0 + -- Allow 0 card hand to always be played if none is unlocked and poker hands aren't disabled + if Cryptid.enabled("set_cry_poker_hand_stuff") == true and G.PROFILES[G.SETTINGS.profile].cry_none then + value = -1 + end + -- Prevent 1 card hand from being played if Sapphire Stamp is active and poker hands aren't enabled (would result in 0 card hand) + if G.GAME.stamp_mod and Cryptid.enabled("set_cry_poker_hand_stuff") ~= true then + value = 1 + end + + if value == 0 then + stamp_can_play(e) + else + if + #G.hand.highlighted <= value + or G.GAME.blind.block_play + or #G.hand.highlighted > math.max(G.GAME.starting_params.play_limit, 1) + then + e.config.colour = G.C.UI.BACKGROUND_INACTIVE + e.config.button = nil + else + e.config.colour = G.C.BLUE + e.config.button = "play_cards_from_highlighted" + end + end +end +local stamp_can_discard = G.FUNCS.can_discard +G.FUNCS.can_discard = function(e) + local value = 0 + -- Allow 0 card hand to always be discarded if none is unlocked and poker hands aren't disabled + if Cryptid.enabled("set_cry_poker_hand_stuff") == true and G.PROFILES[G.SETTINGS.profile].cry_none then + value = -1 + end + if value == 0 then + stamp_can_discard(e) + else + if + G.GAME.current_round.discards_left <= 0 + or #G.hand.highlighted <= value + or #G.hand.highlighted > math.max(G.GAME.starting_params.discard_limit, 0) + then + e.config.colour = G.C.UI.BACKGROUND_INACTIVE + e.config.button = nil + else + e.config.colour = G.C.RED + e.config.button = "discard_cards_from_highlighted" + end + end end -- These allow jokers that add joker slots to be obtained even without room, like with Negative Jokers in vanilla local gfcfbs = G.FUNCS.check_for_buy_space G.FUNCS.check_for_buy_space = function(card) if - (card.ability.name == "cry-Negative Joker" and card.ability.extra >= 1) + (card.ability.name == "cry-Negative Joker" and card.ability.extra.slots >= 1) or (card.ability.name == "cry-soccer" and card.ability.extra.holygrail >= 1) or (card.ability.name == "cry-Tenebris" and card.ability.extra.slots >= 1) then @@ -1200,7 +1282,7 @@ end local gfcsc = G.FUNCS.can_select_card G.FUNCS.can_select_card = function(e) if - (e.config.ref_table.ability.name == "cry-Negative Joker" and e.config.ref_table.ability.extra >= 1) + (e.config.ref_table.ability.name == "cry-Negative Joker" and e.config.ref_table.ability.extra.slots >= 1) or (e.config.ref_table.ability.name == "cry-soccer" and e.config.ref_table.ability.extra.holygrail >= 1) or (e.config.ref_table.ability.name == "cry-Tenebris" and e.config.ref_table.ability.extra.slots >= 1) then @@ -1271,6 +1353,24 @@ function init_localization() end end end + + for _, group in pairs(G.localization.descriptions) do + if + _ ~= "Back" + and _ ~= "Content Set" + and _ ~= "Edition" + and _ ~= "Enhanced" + and _ ~= "Stake" + and _ ~= "Other" + then + for key, card in pairs(group) do + if G.P_CENTERS[key] then + Cryptid.pointeraliasify(key, card.name, true) + end + end + end + end + Cryptid.inject_pointer_aliases() end --Fix a corrupted game state @@ -1287,6 +1387,7 @@ function Controller:queue_L_cursor_press(x, y) end self.L_cursor_queue = { x = x, y = y } end + -- Lemon Trophy's effect local trophy_mod_mult = mod_mult function mod_mult(_mult) @@ -1296,6 +1397,7 @@ function mod_mult(_mult) end return trophy_mod_mult(_mult) end + -- Fix a CCD-related crash local cuc = Card.can_use_consumeable function Card:can_use_consumeable(any_state, skip_check) @@ -1350,3 +1452,762 @@ function create_UIBox_generic_options(args) end return ret end + +local scuref = set_consumeable_usage +function set_consumeable_usage(card) + if not G.GAME.cry_last_used_consumeables then + G.GAME.cry_last_used_consumeables = {} + end + for i = 1, #G.GAME.cry_last_used_consumeables do + if not G.GAME.cry_function_stupid_workaround then + G.GAME.cry_function_stupid_workaround = {} + end + G.GAME.cry_function_stupid_workaround[i] = G.GAME.cry_last_used_consumeables[i] + end + local nextindex = #G.GAME.cry_last_used_consumeables + 1 + G.GAME.cry_last_used_consumeables[nextindex] = card.config.center_key + if nextindex > 3 then + table.remove(G.GAME.cry_last_used_consumeables, 1) + end + scuref(card) +end + +--Abstract cards: Fix to avoid "ghost cards", as aresult of destroying discarded cards by adding a flag checcking its not destroyed +G.FUNCS.draw_from_discard_to_deck = function(e) + G.E_MANAGER:add_event(Event({ + trigger = "immediate", + func = function() + local discard_count = #G.discard.cards + for i = 1, discard_count do --draw cards from deck + local card = G.discard.cards[i] + if not card.shattered and not card.destroyed then + draw_card( + G.discard, + G.deck, + i * 100 / discard_count, + "up", + nil, + card, + 0.005, + i % 2 == 0, + nil, + math.max((21 - i) / 20, 0.7) + ) + end + end + return true + end, + })) +end + +--Add a hook to getID for abstracts (and to conditionally enable the check) +local getIDenhance = Card.get_id +function Card:get_id() + --Force suit to be suit X if specified in enhancement, only if not vampired + if Cryptid.cry_enhancement_has_specific_rank(self) and not self.vampired then + --Get the max value + 1, to always be the last at the list + return SMODS.Rank.max_id.value + 1 + end + local vars = getIDenhance(self) + return vars +end + +--override shatter function to adjust volume (it has been requested that at end of deck, abstract cards should shatter a bit quieter) +function Card:shatter(volume) + local dissolve_time = 0.7 + self.shattered = true + self.dissolve = 0 + self.dissolve_colours = { { 1, 1, 1, 0.8 } } + self:juice_up() + local childParts = Particles(0, 0, 0, 0, { + timer_type = "TOTAL", + timer = 0.007 * dissolve_time, + scale = 0.3, + speed = 4, + lifespan = 0.5 * dissolve_time, + attach = self, + colours = self.dissolve_colours, + fill = true, + }) + G.E_MANAGER:add_event(Event({ + trigger = "after", + blockable = false, + delay = 0.5 * dissolve_time, + func = function() + childParts:fade(0.15 * dissolve_time) + return true + end, + })) + G.E_MANAGER:add_event(Event({ + blockable = false, + func = function() + play_sound("glass" .. math.random(1, 6), math.random() * 0.2 + 0.9, volume or 0.5) + play_sound("generic1", math.random() * 0.2 + 0.9, volume or 0.5) + return true + end, + })) + G.E_MANAGER:add_event(Event({ + trigger = "ease", + blockable = false, + ref_table = self, + ref_value = "dissolve", + ease_to = 1, + delay = 0.5 * dissolve_time, + func = function(t) + return t + end, + })) + G.E_MANAGER:add_event(Event({ + trigger = "after", + blockable = false, + delay = 0.55 * dissolve_time, + func = function() + self:remove() + return true + end, + })) + G.E_MANAGER:add_event(Event({ + trigger = "after", + blockable = false, + delay = 0.51 * dissolve_time, + })) +end + +-- Buttercup's store joker mechanic, creates a specified joker +local ccfs = create_card_for_shop +function create_card_for_shop(area) + local guaranteed_card = Card( + area.x, + area.y, + G.CARD_W, + G.CARD_H, + nil, + G.P_CENTERS.j_jolly, + { bypass_discovery_center = true, bypass_discovery_ui = true } + ) + local areas_to_check = { + shop_jokers = G.shop_jokers, + shop_vouchers = G.shop_vouchers, + shop_booster = G.shop_booster, + } + local loaded_card_data = nil + local loaded_card_pos = -1 + -- check if there's a card for `area` within `next_shop_cards`, + -- then put its data in `loaded_card_data` and its index in the table in `loaded_card_pos` + if G.GAME.next_shop_cards and #G.GAME.next_shop_cards > 0 then + for i, card in ipairs(G.GAME.next_shop_cards) do + if not card.cry_from_shop then + card.cry_from_shop = "shop_jokers" + end -- failsafe :3 + if areas_to_check[card.cry_from_shop] == area and loaded_card_pos == -1 then + loaded_card_data = card + loaded_card_pos = i + break + elseif areas_to_check[card.cry_from_shop] ~= G.shop_jokers then + local other_card = Card( + area.x, + area.y, + G.CARD_W, + G.CARD_H, + nil, + G.P_CENTERS.j_jolly, + { bypass_discovery_center = true, bypass_discovery_ui = true } + ) + other_card:load(card, nil) + other_card.VT.h = other_card.T.h + table.remove(G.GAME.next_shop_cards, i) + create_shop_card_ui( + other_card, + G.P_CENTERS[card.save_fields.center], + set, + areas_to_check[card.cry_from_shop] + ) + areas_to_check[card.cry_from_shop]:emplace(other_card) + other_card.states.visible = false + G.E_MANAGER:add_event(Event({ + delay = 0.4, + trigger = "after", + func = function() + other_card:start_materialize() + other_card:set_cost() + return true + end, + })) + other_card:set_cost() + end + end + end + if loaded_card_data then + -- guaranteed_card.T.h = G.CARD_H + guaranteed_card:load(loaded_card_data, nil) + guaranteed_card.VT.h = guaranteed_card.T.h + table.remove(G.GAME.next_shop_cards, loaded_card_pos) + create_shop_card_ui(guaranteed_card, "Joker", area) + guaranteed_card.states.visible = false + G.E_MANAGER:add_event(Event({ + delay = 0.4, + trigger = "after", + func = function() + guaranteed_card:start_materialize() + guaranteed_card:set_cost() + return true + end, + })) + guaranteed_card:set_cost() + return guaranteed_card + else + guaranteed_card:remove() + end + return ccfs(area) +end + +-- Again, buttercup, making sure you can savescum safely :gjumbsup: +local carsv = Card.save +function Card:save() + local saved_table = carsv(self) + if self.cry_storage then + saved_table.cry_storage = self.cry_storage:save() + end + if self.cry_from_shop then + saved_table.cry_from_shop = self.cry_from_shop + end + return saved_table +end + +local carld = Card.load +function Card:load(cardTable, other_card) + carld(self, cardTable, other_card) + + local storage_area_config = { + type = "play", + card_w = G.CARD_W, + } + if cardTable.cry_storage then + self.cry_storage = CardArea(self.T.x, 2, 1, 1, storage_area_config) + self.cry_storage:load(cardTable.cry_storage) + for i, card in ipairs(self.cry_storage.cards) do + card.T.orig = { w = card.T.w, h = card.T.h } + card.T.w = card.T.w * 0.5 + card.T.h = card.T.h * 0.5 + end + end + if cardTable.cry_from_shop then + self.cry_from_shop = cardTable.cry_from_shop + end +end + +-- Attach Buttercup's stored cards card area +local carmv = Card.move +function Card:move(dt) + carmv(self, dt) + if self.cry_storage ~= nil and self.cry_storage.cards ~= nil then + self.cry_storage.config.card_limit = #self.cry_storage.cards + 1 + self.cry_storage.T.w = G.CARD_W * 2 + self.cry_storage.T.x = self.T.x - (G.CARD_W * 0.5) + self.cry_storage.T.y = self.T.y + self.cry_storage.VT.x = self.VT.x + self.cry_storage.VT.y = self.VT.y + end +end + +--Hook for booster skip to automatically destroy and banish the rightmost Joker, regardless of eternal +local banefulSkipPenalty = G.FUNCS.skip_booster +G.FUNCS.skip_booster = function(e) + --Imported from my Epic Decision and also works in Polterworx and with unpleasant card, in the event youc an still skip with all eternals/cursed jokers + local obj = SMODS.OPENED_BOOSTER.config.center + -- local obj2 = G.P_BLINDS[G.GAME.round_resets.blind_choices.Boss] + if obj.unskippable and type(obj.unskippable) == "function" and obj:unskippable() == true then + if G.GAME.blind then + --Unplesant card will continously spam, so that will do for now without patching that; it is "unpleasant" after all; + -- play_sound('cancel', 0.8, 1) + -- local text = localize('k_nope_ex') + -- attention_text({ + -- scale = 0.9, text = text, hold = 0.75, align = 'cm', offset = {x = 0,y = -2.7},major = G.play,colour = obj2.boss_colour or G.C.RED + -- }) + G.GAME.blind:wiggle() + G.GAME.blind.triggered = true + end + if e and e.disable_button then + e.disable_button = nil + -- print("disble") + end + else + if SMODS.OPENED_BOOSTER.config.center.cry_baneful_punishment then + if not G.GAME.banned_keys then + G.GAME.banned_keys = {} + end -- i have no idea if this is always initialised already tbh + if not G.GAME.cry_banned_pcards then + G.GAME.cry_banished_keys = {} + end + local c = nil + c = G.jokers.cards[#G.jokers.cards] --fallback to rightmost if somehow, you skipped without disabling and its unskippable. + --Iterate backwards to get the rightmost valid (non eternal or cursed) Joker + if G.jokers and G.jokers.cards then + for i = #G.jokers.cards, 1, -1 do + if + not ( + SMODS.is_eternal(G.jokers.cards[i]) + or G.jokers.cards[i].config.center.rarity == "cry_cursed" + ) + then + c = G.jokers.cards[i] + break + end + end + end + + if c.config.center.rarity == "cry_exotic" then + check_for_unlock({ type = "what_have_you_done" }) + end + + G.GAME.cry_banished_keys[c.config.center.key] = true + if G.GAME.blind then + G.GAME.blind:wiggle() + G.GAME.blind.triggered = true + end + c:start_dissolve() + end + banefulSkipPenalty(e) + end +end + +--Overriding the skip booster function. +G.FUNCS.can_skip_booster = function(e) + if + G.pack_cards + and not (G.GAME.STOP_USE and G.GAME.STOP_USE > 0) + and ( + G.STATE == G.STATES.SMODS_BOOSTER_OPENED + or G.STATE == G.STATES.PLANET_PACK + or G.STATE == G.STATES.STANDARD_PACK + or G.STATE == G.STATES.BUFFOON_PACK + or G.hand + ) + then + --if a booster is unskippable (when its unskippable conditionsa re fulfilled), unhighlight it + local obj = SMODS.OPENED_BOOSTER.config.center + if obj.unskippable and type(obj.unskippable) == "function" then + if obj:unskippable() == true then + e.config.colour = G.C.UI.BACKGROUND_INACTIVE + e.config.button = nil + else + e.config.colour = G.C.GREY + e.config.button = "skip_booster" + end + else + e.config.colour = G.C.GREY + e.config.button = "skip_booster" + end + else + e.config.colour = G.C.UI.BACKGROUND_INACTIVE + e.config.button = nil + end +end +--none stuff +local set_blindref = Blind.set_blind +function Blind:set_blind(blind, reset, silent) + set_blindref(self, blind, reset, silent) + if + G.GAME.hands["cry_None"].visible + and (G.STATE == G.STATES.SELECTING_HAND or G.STATE == G.STATES.DRAW_TO_HAND) + and #G.hand.highlighted == 0 + then + G.E_MANAGER:add_event(Event({ + trigger = "after", + func = function() + Cryptid.reset_to_none() + return true + end, + })) + end +end + +local end_roundref = end_round +function end_round() + if + ((#G.hand.cards < 1 and #G.deck.cards < 1 and #G.play.cards < 1) or (#G.hand.cards < 1 and #G.deck.cards < 1)) + and G.STATE == G.STATES.SELECTING_HAND + then + if + Cryptid.enabled("set_cry_poker_hand_stuff") == true + and not Cryptid.safe_get(G.PROFILES, G.SETTINGS.profile, "cry_none") + then + G.PROFILES[G.SETTINGS.profile].cry_none = true + end + if not Cryptid.enabled("set_cry_poker_hand_stuff") then + end_roundref() + end + else + end_roundref() + end + G.E_MANAGER:add_event(Event({ + trigger = "after", + func = function() + update_hand_text({ delay = 0 }, { mult = 0, chips = 0, handname = "", level = "" }) + + return true + end, + })) +end + +local after_ref = evaluate_play_after +function evaluate_play_after(text, disp_text, poker_hands, scoring_hand, non_loc_disp_text, percent, percent_delta) + local ret = after_ref(text, disp_text, poker_hands, scoring_hand, non_loc_disp_text, percent, percent_delta) + if G.GAME.hands["cry_None"].visible then + G.reset_to_none = true + end + return ret +end +local update_handref = Game.update_selecting_hand +function Game:update_selecting_hand(dt) + local ret = update_handref(self, dt) + if G.reset_to_none then + G.E_MANAGER:add_event(Event({ + trigger = "after", + func = function() + Cryptid.reset_to_none() + + return true + end, + })) + G.reset_to_none = nil + end + return ret +end + +local blind_loadref = Blind.load +function Blind:load(blindTable) + blind_loadref(self, blindTable) + if + G.GAME.hands["cry_None"].visible + and self.blind_set + and (G.STATE == G.STATES.SELECTING_HAND or G.STATE == G.STATES.DRAW_TO_HAND) + then + G.E_MANAGER:add_event(Event({ + trigger = "after", + func = function() + Cryptid.reset_to_none() + return true + end, + })) + end +end + +local evaluate_ref = G.FUNCS.evaluate_round +G.FUNCS.evaluate_round = function() + evaluate_ref() + update_hand_text({ delay = 0 }, { mult = 0, chips = 0, handname = "", level = "" }) + G.E_MANAGER:add_event(Event({ + trigger = "after", + func = function() + update_hand_text({ delay = 0 }, { mult = 0, chips = 0, handname = "", level = "" }) + return true + end, + })) +end + +local discard_ref = G.FUNCS.discard_cards_from_highlighted +G.FUNCS.discard_cards_from_highlighted = function(e, hook) + --Labyrinth: set current_round_discards_used to 0 for effects + G.GAME.current_round.discards_used2 = G.GAME.current_round.discards_used + if next(find_joker("cry-maze")) then + G.GAME.current_round.discards_used = 0 + end + discard_ref(e, hook) + local highlighted_count = math.min(#G.hand.highlighted, G.discard.config.card_limit - #G.play.cards) + if highlighted_count <= 0 then + table.sort(G.hand.highlighted, function(a, b) + return a.T.x < b.T.x + end) + check_for_unlock({ type = "discard_custom", cards = {} }) + for j = 1, #G.jokers.cards do + G.jokers.cards[j]:calculate_joker({ pre_discard = true, full_hand = G.hand.highlighted, hook = hook }) + end + if not hook then + if G.GAME.modifiers.discard_cost then + ease_dollars(-G.GAME.modifiers.discard_cost) + end + ease_discard(-1) + G.GAME.current_round.discards_used = G.GAME.current_round.discards_used + 1 + G.STATE = G.STATES.DRAW_TO_HAND + G.E_MANAGER:add_event(Event({ + trigger = "immediate", + func = function() + G.STATE_COMPLETE = false + return true + end, + })) + end + end + if G.GAME.hands["cry_None"].visible then + G.E_MANAGER:add_event(Event({ + trigger = "after", + func = function() + Cryptid.reset_to_none() + return true + end, + })) + end + --Labyrinth: return current_round_discards_used back to the amount it is supposed to be after + G.GAME.current_round.discards_used = G.GAME.current_round.discards_used2 + 1 +end +local play_ref = G.FUNCS.play_cards_from_highlighted +G.FUNCS.play_cards_from_highlighted = function(e) + --Labyrinth: set current_round_hands played to 0 for effects + G.E_MANAGER:add_event(Event({ + trigger = "immediate", + func = function() + G.GAME.current_round.hands_played2 = G.GAME.current_round.hands_played + if next(find_joker("cry-maze")) then + G.GAME.current_round.hands_played = 0 + end + return true + end, + })) + G.GAME.before_play_buffer = true + -- None Stuff + if G.GAME.stamp_mod and not G.PROFILES[G.SETTINGS.profile].cry_none and #G.hand.highlighted == 1 then + G.PROFILES[G.SETTINGS.profile].cry_none = true + print("nonelock stuff here") + G.GAME.hands["cry_None"].visible = true + end + if G.PROFILES[G.SETTINGS.profile].cry_none and #G.hand.highlighted == 0 then + G.GAME.hands["cry_None"].visible = true + end + --Add blind context for Just before cards are played + G.GAME.blind:cry_before_play() + play_ref(e) + --Labyrinth: return current_round_hands played to the amount it is supposed to be at after + G.E_MANAGER:add_event(Event({ + trigger = "immediate", + func = function() + G.E_MANAGER:add_event(Event({ + trigger = "after", + delay = 0.1, + func = function() + G.GAME.current_round.hands_played = G.GAME.current_round.hands_played2 + 1 + return true + end, + })) + return true + end, + })) + G.GAME.before_play_buffer = nil +end + +local use_cardref = G.FUNCS.use_card +G.FUNCS.use_card = function(e, mute, nosave) + use_cardref(e, mute, nosave) + if G.STATE == G.STATES.SELECTING_HAND then + G.E_MANAGER:add_event(Event({ + trigger = "after", + func = function() + G.hand:parse_highlighted() + return true + end, + })) + else + update_hand_text({ delay = 0 }, { mult = 0, chips = 0, handname = "", level = "" }) + end +end +local emplace_ref = CardArea.emplace +function CardArea:emplace(card, location, stay_flipped) + return emplace_ref(self, card or {}, location, stay_flipped) +end +-- Added by IcyEthics: Adding a hook to the shuffle function so that there can be a context to modify randomization +-- Any card using this will most likely want to use cry_post_shuffle. +-- added cry_pre_shuffle for posterity +local o_ca_shuffle = CardArea.shuffle +function CardArea:shuffle(_seed) + SMODS.calculate_context({ cry_shuffling_area = true, cardarea = self, cry_pre_shuffle = true }) + + o_ca_shuffle(self, _seed) + + SMODS.calculate_context({ cry_shuffling_area = true, cardarea = self, cry_post_shuffle = true }) +end + +local smods_four_fingers = SMODS.four_fingers +function SMODS.four_fingers() + return smods_four_fingers() - Cryptid.get_paved_joker() +end + +function Cryptid.create_dummy_from_stone(rank) + local r = tostring(rank) + rank = SMODS.Ranks[r].id + return { + get_id = function() + return rank + end, + config = { + center = {}, + }, + ability = {}, + base = { + id = rank, + value = rank >= 11 and "Queen" or "10", + }, + } +end +function Cryptid.next_ranks(key, start, recurse) + key = ({ + ["14"] = "Ace", + ["13"] = "King", + ["12"] = "Queen", + ["11"] = "Jack", + })[tostring(key)] or key + local rank = SMODS.Ranks[tostring(key)] + local ret = {} + if not rank or (not start and not wrap and rank.straight_edge) then + return ret + end + for _, v in ipairs(rank.next) do + ret[#ret + 1] = v + local curr = #ret + if recurse and recurse > 0 then + for i, v in pairs(Cryptid.next_ranks(ret[#ret], start, recurse - 1)) do + ret[#ret + 1] = v + end + end + end + return ret +end + +local function append(t, new) + local clone = {} + for _, item in ipairs(t) do + clone[#clone + 1] = item + end + clone[#clone + 1] = new + return clone +end + +function Cryptid.unique_combinations(tbl, sub, min) + sub = sub or {} + min = min or 1 + local wrap, yield = coroutine.wrap, coroutine.yield + return wrap(function() + if #sub > 0 then + yield(sub) -- yield short combination. + end + if #sub < #tbl then + for i = min, #tbl do -- iterate over longer combinations. + for combo in Cryptid.unique_combinations(tbl, append(sub, tbl[i]), i + 1) do + yield(combo) + end + end + end + end) +end +get_straight_ref = get_straight +function get_straight(hand, min_length, skip, wrap) + local permutations = {} + local ranks = {} + local cards = {} + local stones = Cryptid.get_paved_joker() + if stones > 0 then + for i, v in pairs(hand) do + if v.config.center.key ~= "m_stone" then + cards[#cards + 1] = v + for i, v in pairs(Cryptid.next_ranks(v:get_id(), nil, stones)) do --this means its inaccurate in some situations like K S S S S but its fine there isnt a better way + ranks[v] = true + end + end + if v:get_id() >= 11 then + new_ranks = { + "Ace", + "King", + "Queen", + "Jack", + 10, + } + for i, v in pairs(new_ranks) do + ranks[v] = true + end + end + end + local rranks = {} + for i, v in pairs(ranks) do + rranks[#rranks + 1] = i + end + for i, v in Cryptid.unique_combinations(rranks) do + if #i == stones then + permutations[#permutations + 1] = i + end + end + for i, v in ipairs(permutations) do + local actual = {} + local ranks = {} + for i, v in pairs(cards) do + actual[#actual + 1] = v + ranks[v:get_id()] = true + end + for i, p in pairs(v) do + local d = Cryptid.create_dummy_from_stone(p) + if not ranks[d:get_id()] then + actual[#actual + 1] = d + end + end + local ret = get_straight_ref(actual, min_length + stones, skip, true) + if ret and #ret > 0 then + return ret + end + end + end + + return get_straight_ref(hand, min_length + stones, skip, wrap) +end + +local get_prob_vars_ref = SMODS.get_probability_vars +function SMODS.get_probability_vars(trigger_obj, base_numerator, base_denominator, identifier, from_roll) + local mod = trigger_obj and trigger_obj.ability and trigger_obj.ability.cry_prob or 1 + local numerator = base_numerator * mod + if trigger_obj and trigger_obj.ability and trigger_obj.ability.cry_rigged then + numerator = base_denominator + end + return get_prob_vars_ref(trigger_obj, numerator, base_denominator, identifier, from_roll) +end + +local pseudorandom_probability_ref = SMODS.pseudorandom_probability +function SMODS.pseudorandom_probability(trigger_obj, seed, base_numerator, base_denominator, identifier) + local mod = trigger_obj and trigger_obj.ability and trigger_obj.ability.cry_prob or 1 + local numerator = base_numerator * mod + if trigger_obj and trigger_obj.ability and trigger_obj.ability.cry_rigged then + SMODS.post_prob = SMODS.post_prob or {} + SMODS.post_prob[#SMODS.post_prob + 1] = { + pseudorandom_result = true, + result = true, + trigger_obj = trigger_obj, + numerator = base_denominator, + denominator = base_denominator, + identifier = identifier or seed, + } + return true + end + return pseudorandom_probability_ref(trigger_obj, seed, numerator, base_denominator, identifier) +end + +local is_eternalref = SMODS.is_eternal +function SMODS.is_eternal(card) + if Cryptid.safe_get(card, "ability", "cry_absolute") then + return true + end + return is_eternalref(card) +end + +local unlock_allref = G.FUNCS.unlock_all +G.FUNCS.unlock_all = function(e) + unlock_allref(e) + G.PROFILES[G.SETTINGS.profile].cry_none = (Cryptid.enabled("set_cry_poker_hand_stuff") == true) +end + +-- Calc ante gain for The Joke (Scuffed) +local smods_calc = SMODS.calculate_context +function SMODS.calculate_context(context, return_table, no_resolve) + local aaa = smods_calc(context, return_table, no_resolve) + if context.modify_ante and context.ante_end then + if G.GAME.blind then + aaa.modify = G.GAME.blind:cry_calc_ante_gain() - 1 + end + end + return aaa +end diff --git a/Cryptid/lib/pointerlib.lua b/Cryptid/lib/pointerlib.lua new file mode 100644 index 0000000..b688cbd --- /dev/null +++ b/Cryptid/lib/pointerlib.lua @@ -0,0 +1,193 @@ +-- if it works, it works +Cryptid.pointerblist = {} +Cryptid.pointerblisttype = {} +Cryptid.pointeralias = {} + +function Cryptid.pointerblistify(target, remove) -- Add specific joker to blacklist, must input either a card object or a key as string, eg: + if not Cryptid.pointerblist then + Cryptid.pointerblist = {} + end + if not remove then + Cryptid.pointerblist[#Cryptid.pointerblist + 1] = target + return true + else + for i = 1, #Cryptid.pointerblist do + if Cryptid.pointerblist[i] == target then + table.remove(Cryptid.pointerblisttype, i) + end + end + end + return false +end + +function Cryptid.pointeraliasify(target, key, remove) -- Add a specific alias/key combo to the alias list + if type(key) == "string" then + if string.len(key) ~= 1 then + key = string.lower(key:gsub("%b{}", ""):gsub("%s+", "")) + end + if not remove then + Cryptid.pointeralias[key] = target + return true + else + Cryptid.pointeralias[key] = nil + end + end + return false +end + +function Cryptid.pointerblistifytype(target, key, remove) -- eg: blacklists a certain card value, see pointer.lua + if not remove then + for target1, key1 in pairs(Cryptid.pointerblisttype) do + if target1 == target then + for _, key2 in ipairs(Cryptid.pointerblisttype[target]) do + if key2 == key then + return true + end + end + Cryptid.pointerblisttype[target][(#Cryptid.pointerblisttype[target] + 1)] = key + return true + end + end + if not Cryptid.pointerblisttype[target] then + Cryptid.pointerblisttype[target] = {} + end + Cryptid.pointerblisttype[target][1] = key + return true + else + if Cryptid.pointerblisttype[target] then + for index, value in ipairs(Cryptid.pointerblisttype[target]) do + if key == value then + table.remove(Cryptid.pointerblisttype[target], index) + return true + end + end + if key == nil then + Cryptid.pointerblisttype[target] = nil + return true + end + end + end + return false +end + +function Cryptid.pointergetalias(target) -- "Is this alias legit?" + target = tostring(target) + local function apply_lower(strn) + if type(strn) ~= string then -- safety + strn = tostring(strn) + end + -- Remove content within {} and any remaining spaces + strn = strn:gsub("%b{}", ""):gsub("%s+", "") + --this weirdness allows you to get m and M separately + if string.len(strn) == 1 then + return strn + end + return string.lower(strn) + end + if Cryptid.pointeralias[apply_lower(target)] then + return Cryptid.pointeralias[apply_lower(target)] + end + if G.P_CENTERS[apply_lower(target)] then + return G.P_CENTERS[apply_lower(target)].key + end + if Cryptid.pointeralias[target] then + return Cryptid.pointeralias[target] + end + if G.P_CENTERS[target] then + return G.P_CENTERS[target].key + end + return false +end + +function Cryptid.pointergetblist(target) -- "Is this card pointer banned?" + target = Cryptid.pointergetalias(target) or target + target = target + results = {} + results[1] = false + if not target then + results[1] = true + end + if G.GAME.banned_keys[target] or (type(target) == "table" and G.GAME.banned_keys[target.key]) then + results[1] = true + end + for index, value in ipairs(Cryptid.pointerblist) do + if target == value or (type(target) == "table" and target.key) then + results[1] = true + end + end + if results[1] ~= true and (G.P_CENTERS[target] or (type(target) == "table" and G.P_CENTERS[target.key])) then + target = (G.P_CENTERS[target] or (type(target) == "table" and G.P_CENTERS[target.key])) + for value, power in pairs(Cryptid.pointerblisttype) do + for index, val2 in pairs(target) do + if value == index then + if power == ({} or true or nil) then + results[1] = true + end + for _, val3 in ipairs(power) do + if target[index] == val3 then + results[1] = true + end + end + end + end + end + end + if G.DEBUG_POINTER then + results[1] = false + end + target = G.P_CENTERS[target] or target + if results[1] == false then + if target and target.set == "Joker" then + results[2] = "Joker" + if + target.unlocked -- If card unlocked + and #G.jokers.cards + G.GAME.joker_buffer < G.jokers.config.card_limit -- and you have room + then + results[3] = true + elseif G.DEBUG_POINTER then + results[3] = true + else + results[3] = false + end + elseif target and target.consumeable then + results[2] = "Consumeable" + if #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then + results[3] = true + elseif G.DEBUG_POINTER then + results[3] = true + else + results[3] = false + end + elseif target and target.set == "Voucher" then + results[2] = "Voucher" + if target.unlocked then + results[3] = true + elseif G.DEBUG_POINTER then + results[3] = true + else + results[3] = false + end + elseif target and target.set == "Booster" then + results[2] = "Booster" + if + not ( -- no boosters if already in booster + G.STATE ~= G.STATES.TAROT_PACK + and G.STATE ~= G.STATES.SPECTRAL_PACK + and G.STATE ~= G.STATES.STANDARD_PACK + and G.STATE ~= G.STATES.BUFFOON_PACK + and G.STATE ~= G.STATES.PLANET_PACK + and G.STATE ~= G.STATES.SMODS_BOOSTER_OPENED + ) + then + if target.unlocked then + results[3] = true + elseif G.DEBUG_POINTER then + results[3] = true + else + results[3] = false + end + end + end + end + return results +end diff --git a/Cryptid/lib/ui.lua b/Cryptid/lib/ui.lua index ae81f44..a896066 100644 --- a/Cryptid/lib/ui.lua +++ b/Cryptid/lib/ui.lua @@ -14,23 +14,6 @@ SMODS.DrawStep({ self.params.viewed_back ) == "table" and self.params.viewed_back or (self.params.viewed_back and G.GAME.viewed_back or G.GAME.selected_back)) or Back(G.P_CENTERS["b_red"]) - if currentBack.effect.config.cry_force_edition and not currentBack.effect.config.cry_antimatter then - if currentBack.effect.config.cry_force_edition_shader then - self.children.back:draw_shader( - currentBack.effect.config.cry_force_edition_shader, - nil, - self.ARGS.send_to_shader, - true - ) - else - self.children.back:draw_shader( - currentBack.effect.config.cry_force_edition, - nil, - self.ARGS.send_to_shader, - true - ) - end - end if currentBack.effect.config.cry_force_seal and not currentBack.effect.config.hide_seal @@ -200,34 +183,67 @@ SMODS.DrawStep({ then local scale_mod = 0.07 -- + 0.02*math.cos(1.8*G.TIMERS.REAL) + 0.00*math.cos((G.TIMERS.REAL - math.floor(G.TIMERS.REAL))*math.pi*14)*(1 - (G.TIMERS.REAL - math.floor(G.TIMERS.REAL)))^3 local rotate_mod = 0 --0.05*math.cos(1.219*G.TIMERS.REAL) + 0.00*math.cos((G.TIMERS.REAL)*math.pi*5)*(1 - (G.TIMERS.REAL - math.floor(G.TIMERS.REAL)))^2 - self.children.floating_sprite2:draw_shader( - "dissolve", - 0, - nil, - nil, - self.children.center, - scale_mod, - rotate_mod, - nil, - 0.1 --[[ + 0.03*math.cos(1.8*G.TIMERS.REAL)--]], - nil, - 0.6 - ) - self.children.floating_sprite2:draw_shader( - "dissolve", - nil, - nil, - nil, - self.children.center, - scale_mod, - rotate_mod - ) + if self.children.floating_sprite2 then + self.children.floating_sprite2:draw_shader( + "dissolve", + 0, + nil, + nil, + self.children.center, + scale_mod, + rotate_mod, + nil, + 0.1 --[[ + 0.03*math.cos(1.8*G.TIMERS.REAL)--]], + nil, + 0.6 + ) + self.children.floating_sprite2:draw_shader( + "dissolve", + nil, + nil, + nil, + self.children.center, + scale_mod, + rotate_mod + ) + else + local center = self.config.center + if _center and _center.soul_pos and _center.soul_pos.extra then + self.children.floating_sprite2 = Sprite( + self.T.x, + self.T.y, + self.T.w, + self.T.h, + G.ASSET_ATLAS[_center.atlas or _center.set], + _center.soul_pos.extra + ) + self.children.floating_sprite2.role.draw_major = self + self.children.floating_sprite2.states.hover.can = false + self.children.floating_sprite2.states.click.can = false + end + end end end, conditions = { vortex = false, facing = "front" }, }) SMODS.draw_ignore_keys.floating_sprite2 = true +-- CCD Drawstep +local interceptorSprite = nil +SMODS.DrawStep({ + key = "ccd_interceptor", + order = -5, + func = function(self) + local card_type = self.ability.set or "None" + if card_type ~= "Default" and card_type ~= "Enhanced" and self.playing_card and self.facing == "front" then + interceptorSprite = interceptorSprite + or Sprite(0, 0, G.CARD_W, G.CARD_H, G.ASSET_ATLAS["cry_misc"], { x = 3, y = 1 }) + interceptorSprite.role.draw_major = self + interceptorSprite:draw_shader("dissolve", nil, nil, nil, self.children.center) + end + end, +}) + -- Make hover UI collidable - so we can detect collision and display tooltips local m = Card.move function Card:move(dt) @@ -278,7 +294,7 @@ end -- Unfortunately this doesn't play nicely with gameset UI local cainit = CardArea.init function CardArea:init(X, Y, W, H, config) - if config.collection then + if config and config.collection then config.highlight_limit = config.card_limit end return cainit(self, X, Y, W, H, config) @@ -393,12 +409,13 @@ function G.UIDEF.use_and_sell_buttons(card) if card.config and card.config.center and card.config.center.key == "c_cry_potion" then table.remove(abc.nodes[1].nodes, 1) end + -- i love buttercup if card.area - and card.edition - and (card.area == G.jokers or card.area == G.consumeables or card.area == G.hand) - and card.edition.cry_double_sided - and not Card.no(card, "dbl") + and card.area.config.type == "joker" + and card.config + and card.config.center + and card.ability.name == "cry-Buttercup" then local use = { n = G.UIT.C, @@ -411,20 +428,20 @@ function G.UIDEF.use_and_sell_buttons(card) align = "cr", maxw = 1.25, padding = 0.1, - r = 0.08, + r = 0.05, hover = true, shadow = true, colour = G.C.UI.BACKGROUND_INACTIVE, one_press = true, - button = "flip", - func = "can_flip_card", + button = "store", + func = "can_store_card", }, nodes = { { n = G.UIT.B, config = { w = 0.1, h = 0.3 } }, { n = G.UIT.T, config = { - text = localize("b_flip"), + text = localize("b_store"), colour = G.C.UI.TEXT_LIGHT, scale = 0.3, shadow = true, @@ -447,63 +464,5 @@ function G.UIDEF.use_and_sell_buttons(card) } }) return abc end - if - card.area - and (card.area == G.jokers or card.area == G.consumeables or card.area == G.hand) - and (not card.edition or not card.edition.cry_double_sided) - and not card.ability.eternal - and not Card.no(card, "dbl") - then - for i = 1, #card.area.cards do - if card.area.cards[i].edition and card.area.cards[i].edition.cry_double_sided then - local use = { - n = G.UIT.C, - config = { align = "cr" }, - nodes = { - { - n = G.UIT.C, - config = { - ref_table = card, - align = "cr", - maxw = 1.25, - padding = 0.1, - r = 0.08, - hover = true, - shadow = true, - colour = G.C.UI.BACKGROUND_INACTIVE, - one_press = true, - button = "flip_merge", - func = "can_flip_merge_card", - }, - nodes = { - { n = G.UIT.B, config = { w = 0.1, h = 0.3 } }, - { - n = G.UIT.T, - config = { - text = localize("b_merge"), - colour = G.C.UI.TEXT_LIGHT, - scale = 0.3, - shadow = true, - }, - }, - }, - }, - }, - } - local m = abc.nodes[1] - if not card.added_to_deck then - use.nodes[1].nodes = { use.nodes[1].nodes[2] } - if card.ability.consumeable then - m = abc - end - end - m.nodes = m.nodes or {} - table.insert(m.nodes, { n = G.UIT.R, config = { align = "cl" }, nodes = { - use, - } }) - return abc - end - end - end return abc end diff --git a/Cryptid/localization/de.lua b/Cryptid/localization/de.lua index d7ba2c0..61f53ff 100644 --- a/Cryptid/localization/de.lua +++ b/Cryptid/localization/de.lua @@ -1,4 +1,5 @@ --Translation by Foegro +--Proofreading and Additions by Avery (@onichama) return { descriptions = { Back = { @@ -8,6 +9,11 @@ return { "Hat die {C:legendary,E:1}positiven Effekte{}", "von {C:attention}jedem{} Deck", }, + unlock = { + "Gewinne einen Durchlauf", + "mit {C:attention}Unbedrucktem Deck", + "auf {C:attention}Goldener Einsatz", + }, }, b_cry_antimatter_balanced = { name = "Antimaterie Deck", @@ -23,15 +29,24 @@ return { "{C:attention}Gewöhnliche{} Joker haben", "{C:attention}vierfache{} Werte", }, + unlock = { + "Entdecke mindestens", + "{C:attention}200{} Gegenstände", + "deiner Sammlung", + }, }, b_cry_beta = { name = "Nostalgisches Deck", text = { - "{C:attention}Joker{} und {C:attention}Verbrauchgegenstände{}", - "Slots sind {C:attention}zusammengefasst", + "{C:attention}Joker{} und {C:attention}Verbrauchsgegenstände{}", + "Slots sind {C:attention}zusammengefasst,", "{C:attention}Nostalgische{} Blinds ersetzen", "ihre neuen Versionen.", }, + unlock = { + "Gewinne einen Durchlauf", + "auf {C:attention}Pinker Einsatz", + }, }, b_cry_blank = { name = "Unbedrucktes Deck", @@ -40,11 +55,15 @@ return { }, }, b_cry_bountiful = { - name = "Größzügiges Deck", + name = "Großzügiges Deck", text = { "Ziehe immer 5 Karten nach", "{C:attention}Gespielter Hand{} oder {C:attention}Abwurf{}", }, + unlock = { + "Schlage {C:attention}Die Schlange", + "ohne {C:red}Abwurf", + }, }, b_cry_CCD = { name = "CCD Deck", @@ -52,31 +71,55 @@ return { "Jede Karte ist auch", "ein {C:attention}zufälliger{} Verbrauchsgegenstand", }, + unlock = { + "Benutze {C:spectral}Hammerspace", + }, }, b_cry_conveyor = { - name = "Fließband Deck", + name = "Fließband-Deck", text = { "Joker können {C:attention}nicht{} bewegt werden", "Am Anfang der Runde,", - "{C:attention}dupliziere{} den rechtesten Joker", - "und {C:attention}zerstöre{} den linkesten Joker", + "{C:attention}dupliziere{} den Joker ganz rechts", + "und {C:attention}zerstöre{} den Joker ganz links", + }, + unlock = { + "Benutze {C:spectral}Analog", }, }, b_cry_critical = { name = "Kritisches Deck", text = { "Nach jeder gespielten Hand,", - "Chance von {C:green}#1# zu 4{} für {X:dark_edition,C:white} ^2 {} Mult", - "Chance von {C:green}#1# zu 8{} für {X:dark_edition,C:white} ^0.5 {} Mult", + "Chance von {C:green}#1# zu #2#{} für {X:dark_edition,C:white} ^2 {} Mult", + "Chance von {C:green}#1# zu #3#{} für {X:dark_edition,C:white} ^0.5 {} Mult", + }, + unlock = { + "Erhalte einen {C:attention}Manipulierten Joker", + }, + }, + b_cry_e_deck = { + name = "Editionen-Deck", + text = { + "Alle Karten sind {C:dark_edition}#1#{},", + "Karten können Edition nicht ändern", + "{C:inactive}(Klicke zum Ändern)", + }, + unlock = { + "Entdecke jede", + "{C:dark_edition}Edition", }, }, b_cry_encoded = { name = "Verschlüsseltes Deck", text = { "Starte mit einem {C:cry_code,T:j_cry_CodeJoker}Code Joker{}", - "und einem {C:cry_code,T:j_cry_copypaste}Copy/Paste{}", + "und einem {C:cry_code,T:j_cry_copypaste}Copy/Paste{},", "Nur {C:cry_code}Code Karten{} erscheinen im Shop", }, + unlock = { + "Benutze {C:spectral}POINTER://", + }, }, b_cry_equilibrium = { name = "Deck des Gleichgewichts", @@ -87,6 +130,21 @@ return { "beginne den Durchlauf mit", "{C:attention,T:v_overstock_plus}Überbestand Plus", }, + unlock = { + "Habe gleichzeitig", + "{C:attention}100 Joker", + }, + }, + b_cry_et_deck = { + name = "Verstärktes Deck", + text = { + "Alle {C:attention}Spielkarten{}", + "sind {C:attention}#1#{}", + "{C:inactive}(Klicke zum Ändern)", + }, + unlock = { + "Benutze {C:spectral}Vakuum", + }, }, b_cry_glowing = { name = "Glühendes Deck", @@ -96,6 +154,10 @@ return { "wenn die Boss Blind besiegt wurde.", "{X:cry_jolly,C:white,s:0.8} Jolly#1#Open#1#Winner#1#-#1#wawa#1#person", --peak loc_vars right here }, + unlock = { + "Gewinne einen Durchlauf", + "mit {C:attention}Beiges Deck", + }, }, b_cry_infinite = { name = "Unendliches Deck", @@ -104,6 +166,10 @@ return { "Karten auswählen.", "{C:attention}+1{} Handgröße", }, + unlock = { + "Spiele eine Hand mit", + "{C:attention}6{} oder mehr Karten", + }, }, b_cry_misprint = { name = "Fehlgedrucktes Deck", @@ -112,6 +178,9 @@ return { "und Pokerhänden", "sind {C:attention}zufällig", }, + unlock = { + "Erhalte einen {C:dark_edition}Fehlerhaften{C:attention} Joker", + }, }, b_cry_redeemed = { name = "Eingelöstes Deck", @@ -119,6 +188,31 @@ return { "Wenn ein {C:attention}Gutschein{} gekauft wird,", "bekomme seine {C:attention}verbesserten Versionen", }, + unlock = { + "Entdecke jeden", + "{C:attention}Gutschein", + }, + }, + b_cry_sk_deck = { + name = "Sticker-Deck", + text = { + "Alle Karten sind {C:attention}#1#{}", + "{C:inactive}(Klicke zum Ändern)", + }, + unlock = { + "Benutze {C:spectral}Schloss", + }, + }, + b_cry_sl_deck = { + name = "Siegel-Deck", + text = { + "Alle Spielkarten haben ein {C:dark_edition}#1#{},", + "Karten können Siegel nicht ändern", + "{C:inactive}(Klicke zum Ändern)", + }, + unlock = { + "Benutze {C:spectral}Taifun", + }, }, b_cry_spooky = { name = "Gruseliges Deck", @@ -127,6 +221,20 @@ return { "Nach jeder {C:attention}Ante{}, erstelle eine", "{C:cry_candy}Süßigkeit{} oder einen {X:cry_cursed,C:white}Verfluchten{} Joker", }, + unlock = { + "Erhalte einen {C:cry_candy}Süßigkeiten{C:attention} Joker", + }, + }, + b_cry_st_deck = { + name = "Farben-Deck", + text = { + "Alle Spielkarten sind {C:dark_edition}#1#", + "und können Farbe nicht ändern", + "{C:inactive}(Klicke zum Ändern)", + }, + unlock = { + "Benutze {C:spectral}Replik", + }, }, b_cry_very_fair = { name = "Sehr Faires Deck", @@ -136,22 +244,34 @@ return { "{C:attention}Gutscheine{} erscheinen", "nicht mehr im Shop", }, + unlock = { + "Gewinne einen Durchlauf", + "mit {C:attention}Unbedrucktes Deck", + }, }, b_cry_wormhole = { name = "Wurmloch Deck", text = { "Beginne mit einem {C:cry_exotic}Exotischen{C:attention} Joker", - "Joker sind {C:attention}20X{} warscheinlicher", + "Joker sind {C:attention}20X{} wahrscheinlicher", "{C:dark_edition}Negativ{} zu sein", "{C:attention}-2{} Joker-Slots", }, + unlock = { + "Erhalte einen {C:cry_exotic}Exotischen{C:attention} Joker", + }, }, b_cry_legendary = { name = "Legendäres Deck", text = { "Beginne mit einem {C:legendary}Legendären{C:legendary} Joker", - "Chance von {C:green}1 in 5{} einen weiteren zu erstellen", - "wenn Boss Blind besiegt wurde {C:inactive}(Muss Platz haben){}", + "Chance von {C:green}#1# in #2#{}, einen Weiteren zu erstellen", + "wenn Boss Blind besiegt wurde", + "{C:inactive}(Muss Platz haben){}", + }, + unlock = { + "Habe gleichzeitig", + "{C:attention}2 Legendäre Joker", }, }, }, @@ -167,7 +287,8 @@ return { name = "Die Uhr", text = { "+0.1X Blindgröße für alle", - "12 Sekunden, die du in dieser Ante verbringst.", + "12 Sekunden, die du in dieser Ante verbringst,", + "multipliziert mit Spielgeschwindigkeit", }, }, bl_cry_hammer = { @@ -180,8 +301,8 @@ return { bl_cry_joke = { name = "Der Witz", text = { - "Wenn deine Chips mehr als 2x die benötigten sind,", - "setze die Ante zu einer mehrzahl von #1#", + "Wenn deine Chips 2x mehr als benötigt sind,", + "setze die Ante auf #1#", }, }, bl_cry_magic = { @@ -195,7 +316,8 @@ return { name = "Lavendelschleife", text = { "1.25X Blindgröße für alle", - "6 Sekunden, die du in dieser Runde verbringst", + "6 Sekunden, die du in dieser Runde verbringst,", + "multipliziert mit Spielgeschwindigkeit", }, }, bl_cry_obsidian_orb = { @@ -208,7 +330,7 @@ return { bl_cry_oldarm = { name = "Nostalgischer Arm", text = { - "Du musst 4 oder weniger", + "Muss 4 oder weniger", "Karten spielen", }, }, @@ -240,7 +362,7 @@ return { bl_cry_oldmark = { name = "Nostalgische Marke", text = { - "Keine Hände die", + "Keine Hände, die", "ein Paar enthalten", }, }, @@ -254,63 +376,103 @@ return { bl_cry_oldpillar = { name = "Nostalgische Säule", text = { - "Keine Straßen", + "Keine Straights", }, }, bl_cry_oldserpent = { name = "Nostalgische Schlange", text = { - "Dividiere Mult durch das Level", - "der gespielten Poker Hand", + "Dividiere Mult durch Level", + "der gespielten Pokerhand", }, }, bl_cry_pin = { name = "Die Stecknadel", text = { - "Joker mit epischer oder höherer", - "Seltenheit sind geschwächt.", + "Joker mit Epischer oder höherer", + "Seltenheit sind geschwächt", + }, + }, + bl_cry_scorch = { + name = "Der Brandfleck", + text = { + "Muss 5 Karten spielen,", + "zerstöre alle gespielten", + "und abgeworfenen Karten", + }, + }, + bl_cry_greed = { + name = "Die Gier", + text = { + "+#2# Blindgröße", + "pro $#1# wenn ausgewählt", + }, + }, + bl_cry_repulsor = { + name = "Der Abstoßer", + text = { + "Löse den Joker ganz rechts und", + "ganz links erneut aus, alle anderen", + "Joker werden nicht ausgelöst", + }, + }, + bl_cry_chromatic = { + name = "Die Chromatik", + text = { + "Punktzahl wird", + "subtrahiert bei", + "ungerader Anzahl von Händen", + }, + }, + bl_cry_landlord = { + name = "Der Vermieter", + text = { + "Fuegt Gemietet einem", + "zufälligen Joker hinzu", + "wenn Hand gespielt wird", }, }, bl_cry_pinkbow = { name = "Pinke Schleife", text = { "Rang der Karten in der Hand", - "werden beim Spielen einer Hand verzufälligt", + "werden beim Spielen einer Hand zufällig", }, }, bl_cry_sapphire_stamp = { name = "Saphirstempel", text = { - "Du kannst eine weitere Karte auswählen, vor der", - "Auswertung wird die Auswahl einer zufälligen Karte aufgehoben", + "Wähle eine weitere Karte aus,", + "vor Auswertung wird eine", + "zufällige Karte abgewählt", }, }, bl_cry_shackle = { name = "Die Schelle", text = { - "Alle negativen Joker", + "Alle Negativen Joker", "sind geschwächt", }, }, bl_cry_striker = { name = "Der Stürmer", text = { - "Alle seltenen Joker", + "Alle Seltenen Joker", "sind geschwächt", }, }, bl_cry_tax = { name = "Die Steuer", text = { - "Wert einer Hand kann nicht", - "mehr als 0.4 mal das benötigte sein", + "Punktzahl einer Hand", + "begrenzt auf #1#", }, }, bl_cry_tornado = { name = "Türkiser Tornado", text = { "Chance von #1# zu #2#, dass", - "die gespielte Hand nicht gewertet wird", + "gespielte Hand nicht gewertet wird", }, }, bl_cry_trick = { @@ -320,6 +482,13 @@ return { "mit dem Gesicht oben in der Hand um", }, }, + bl_cry_trophy = { + name = "Lemon Trophy", + text = { + "Mult kann nicht größer", + "sein als Chips", + }, + }, bl_cry_vermillion_virus = { name = "Zinnober Virus", text = { @@ -330,17 +499,78 @@ return { bl_cry_windmill = { name = "Die Windmühle", text = { - "Alle ungewöhnlichen Joker", + "Alle Ungewöhnlichen Joker", "sind geschwächt", }, }, + bl_cry_decision = { + name = "The Decision", + text = { + "Fixiere Joker beim Spielen oder Abwerfen", + "Öffne ein Unheilvolles Clownspaket", + "nach der Runde", + }, + }, }, Code = { - c_cry_class = { - name = "://CLASS", + c_cry_crash = { + name = "://CRASH", text = { - "Mache {C:cry_code}#1#{} ausgewählte Karte", - "zu einer {C:cry_code}gewählten{} Verstärkung", + "{C:cry_code,E:1}Nein", + }, + }, + c_cry_keygen = { + name = "://KEYGEN", + text = { + "Erzeuge einen zufälligen {C:cry_code}Verderblichen Bananen{}-", + "Gutschein, {C:cry_code}zerstöre{} zuvor auf diese", + "Weise erzeugte Gutscheine.", + }, + }, + c_cry_payload = { + name = "://PAYLOAD", + text = { + "Nächster besiegter Blind", + "gibt {C:cry_code}X#1#{} Zinsen", + }, + }, + c_cry_exploit = { + name = "://EXPLOIT", + text = { + "Die {C:cry_code}nächste{} gespielte Hand wird", + "gewertet, als wäre sie eine {C:cry_code}gewählte{} Pokerhand", + "und erhält {C:cry_code}eine{} temporäre {C:cry_code}Aufstiegskraft{}", + }, + }, + c_cry_malware = { + name = "://MALWARE", + text = { + "Füge {C:dark_edition}Fehlerhaft{} zu allen", + "Karten {C:cry_code}in der Hand{} hinzu", + }, + }, + c_cry_nperror = { + name = "://NPERROR", + text = { + "Holt die {C:cry_code}letzte gespielte Hand{}", + "zurück auf deine Hand", + }, + }, + c_cry_rework = { + name = "://REWORK", + text = { + "Zerstöre einen {C:cry_code}gewählten{} Joker,", + "erstelle ein {C:cry_code}Überarbeitungs-Tag{} mit", + "einer Edition {C:cry_code}besser{}", + "{C:inactive,s:0.8}Nutzt Reihenfolge in der Sammlung", + }, + }, + c_cry_merge = { + name = "://MERGE", + text = { + "Verschmelze ein gewählten", + "{C:cry_code}Verbrauchsgegenstand", + "mit einer gewählten {C:cry_code}Spielkarte", }, }, c_cry_commit = { @@ -351,134 +581,17 @@ return { "mit der {C:cry_code}selben Seltenheit", }, }, - c_cry_crash = { - name = "://CRASH", - text = { - "{C:cry_code,E:1}Nein", - }, - }, - c_cry_ctrl_v = { - name = "://CTRL+V", - text = { - "Erstelle eine Kopie einer {C:cry_code}gewälten{} Spielkarte oder Gebrauchsgegenstand.", - }, - }, - c_cry_delete = { - name = "://DELETE", - text = { - "Entferne ein {C:cry_code}gewählten{}", - "Shopgegenstand {C:cry_code}permanent{}", - "{C:inactive,s:0.8}Item kann in diesem Durchlauf nicht mehr auftauchen.", - }, - }, - c_cry_divide = { - name = "://DIVIDE", - text = { - "{C:cry_code}Halbiere{} alle gelisteten Preise", - "Im momentanen Shop", - }, - }, - c_cry_exploit = { - name = "://EXPLOIT", - text = { - "Die {C:cry_code}nächste{} gespielte Hand wird", - "gewertet als ob sie eine {C:cry_code}gewählte{} Pokerhand enthält.", - "{C:inactive,s:0.8}Geheime Hände müssen", - "{C:inactive,s:0.8}entdeckt weden um gültig zu sein.", - }, - }, - c_cry_hook = { - name = "HOOK://", - text = { - "Wähle zwei Joker", - "die {C:cry_code}Verhackt{} werden", - }, - }, - c_cry_inst = { - name = "://INSTANTIATE", - text = { - "Ziehe eine Karte mit dem {C:attention}Rang{} einer ausgewählten Karte", - "und eine mit der {C:attention}Farbe{} der ausgewählten Karte", - "{C:inactive}(Wenn möglich){}", - }, - }, c_cry_machinecode = { name = "://MACHINECODE", text = { "", }, }, - c_cry_malware = { - name = "://MALWARE", - text = { "Füge {C:dark_edition}Fehlerhaft{} zu allen", "Karten {C:cry_code}in der Hand{} hinzu" }, - }, - c_cry_merge = { - name = "://MERGE", + c_cry_spaghetti = { + name = "://SPAGHETTI", text = { - "Verschmelze ein gewählten {C:cry_code}Verbrauchsgegenstand", - "mit einer gewählten {C:cry_code}Spielkarte", - }, - }, - c_cry_multiply = { - name = "://MULTIPLY", - text = { - "{C:cry_code}Verdopple{} alle Werte", - "eines gewählten {C:cry_code}Jokers{} bis", - "zum ende der Runde.", - }, - }, - c_cry_patch = { - name = "://PATCH", - text = { - "Entfernt alle Sticker und Schwächungen von", - "allen momentan sichtbaren Gegenständen", - }, - }, - c_cry_payload = { - name = "://PAYLOAD", - text = { - "Nächste besiegte Blind", - "gibt {C:cry_code}X#1#{} Zinsen", - }, - }, - c_cry_oboe = { - name = "://OFFBYONE", - text = { - "Nächstes {C:cry_code}Booster Packet{} hat", - "{C:cry_code}#1#{} zusätzliche Karte und", - "{C:cry_code}#1#{} zusätzliche Auswahl", - "{C:inactive}(Momentan {C:cry_code}+#2#{C:inactive})", - }, - }, - c_cry_reboot = { - name = "://REBOOT", - text = { - "Erfrische {C:blue}Hände{} und {C:red}Abwürfe{},", - "tue {C:cry_code}alle{} Karten zurück ins Deck", - "und ziehe eine {C:cry_code}neue{} Hand", - }, - }, - c_cry_revert = { - name = "://REVERT", - text = { - "Setzt {C:cry_code}Spielstand{} zum", - "Start {C:cry_code}dieser Ante{}", - }, - }, - c_cry_rework = { - name = "://REWORK", - text = { - "Zerstöre einen {C:cry_code}gewählten{} Joker,", - "erstelle einen {C:cry_code}Überarbeitungs-Tag{} mit", - "einer Edition {C:cry_code}besser{}", - "{C:inactive,s:0.8}Nutzt Reinfolge in der Sammlung", - }, - }, - c_cry_run = { - name = "://RUN", - text = { - "Besuche einen {C:cry_code}Shop", - "während einer {C:cry_code}Blind", + "Erzeuge einen {C:cry_code}Fehlerhaften{}", + "Essen-Joker", }, }, c_cry_seed = { @@ -489,24 +602,304 @@ return { "um {C:cry_code}Manipuliert{} zu werden", }, }, - c_cry_semicolon = { - name = ";//", - text = { "Enden momentane nicht-Boss {C:cry_code}Blind{}", "{C:cry_code}ohne{} Preisgeld zu bekommen" }, - }, - c_cry_spaghetti = { - name = "://SPAGHETTI", + c_cry_patch = { + name = "://PATCH", text = { - "Erstelle einen {C:cry_code}Fehlerhaften{}", - "Essen Joker", + "Entfernt alle Schwächungen von", + "aktuell sichtbaren Gegenständen", + }, + }, + c_cry_cryupdate = { + name = "://UPDATE", + text = { + "Kommt in einem", + "zukünftigen {C:cry_code}Update{}", + }, + }, + c_cry_hook = { + name = "HOOK://", + text = { + "Wähle zwei Joker", + "die {C:cry_code}Verhakt{} werden", + }, + }, + c_cry_oboe = { + name = "://OFFBYONE", + text = { + "Nächstes {C:cry_code}Booster Paket{} hat", + "{C:cry_code}#1#{} zusätzliche Karte#1# und", + "{C:cry_code}#1#{} zusätzliche Auswahl#1#", + "{C:inactive}(Aktuell {C:cry_code}+#2#{C:inactive})", + }, + }, + c_cry_assemble = { + name = "://ASSEMBLE", + text = { + "Addiere Anzahl der Joker zu", + "{C:cry_code}Mult{} der {C:cry_code}gewählten Hand{}", + }, + }, + c_cry_inst = { + name = "://INSTANTIATE", + text = { + "Ziehe eine Karte mit dem {C:attention}Rang{} einer ausgewählten Karte", + "und eine mit der {C:attention}Farbe{} der ausgewählten Karte", + "{C:inactive}(Wenn möglich){}", + }, + }, + c_cry_revert = { + name = "://REVERT", + text = { + "Setze {C:cry_code}Spielstand{} zum", + "Start {C:cry_code}dieser Ante{}", + }, + }, + c_cry_cryfunction = { + name = "FUNCTION://", + text = { + "Speichert die {C:cry_code}letzten 3{} benutzten Verbrauchsgegenstände,", + "erneute Benutzung dieser Karte erzeugt", + "den Ersten mit einem {C:cry_code}Function://{} Sticker", + }, + }, + c_cry_run = { + name = "://RUN", + text = { + "Besuche einen {C:cry_code}Shop", + "während eines {C:cry_code}Blinds", + }, + }, + c_cry_class = { + name = "://CLASS", + text = { + "Mache {C:cry_code}#1#{} ausgewählte Karte", + "zu einer {C:cry_code}gewählten{} Verstärkung", + }, + }, + c_cry_global = { + name = "://GLOBAL", + text = { + "Wähle eine Spielkarte,", + "um {C:cry_code}Global{} zu werden", }, }, c_cry_variable = { name = "://VARIABLE", text = { - "Mache {C:cry_code}#1#{} gewählte Karten", + "Mache {C:cry_code}#1#{} gewählte Karte#1#", "zu einem {C:cry_code}gewählten{} Rang", }, }, + c_cry_log = { + name = "://LOG", + text = { + "{C:cry_code}Anzeige{} von einer dieser Optionen: ", + "{C:attention}Boss-Blind{} der {C:attention}nächsten{} Ante und {C:attention}Gutscheine{},", + "die nächsten {C:attention}5{} {C:attention}Joker{} im Shop, oder", + "die nächsten {C:attention}10{} zu {C:attention}ziehenden{} Spielkarten", + "{C:inactive}(Falls in einem Blind){}", + }, + }, + c_cry_quantify = { + name = "://QUANTIFY", + text = { + "Verschiebe {C:attention}#1#{} gewählte", + "{C:attention}Karte#1#{}, oder {C:attention}Booster{}", + "in die {C:attention}Joker{}-Ablage", + }, + }, + c_cry_divide = { + name = "://DIVIDE", + text = { + "{C:cry_code}Halbiere{} alle gelisteten Preise", + "im momentanen Shop", + }, + }, + c_cry_multiply = { + name = "://MULTIPLY", + text = { + "{C:cry_code}Verdopple{} alle Werte", + "eines gewählten {C:cry_code}Jokers{} bis", + "zum Ende der Runde.", + }, + }, + c_cry_delete = { + name = "://DELETE", + text = { + "Entferne einen {C:cry_code}gewählten{}", + "Shopgegenstand {C:cry_code}permanent{}", + "{C:inactive,s:0.8}Item kann in diesem Durchlauf nicht mehr auftauchen.", + }, + }, + c_cry_alttab = { + name = "://ALTTAB", + text = { + "Erzeugt den Skip-Tag des", + "{C:cry_code}aktuellen{} Blinds", + "{C:inactive}(Aktuell: {C:cry_code}#1#{C:inactive})", + }, + }, + c_cry_ctrl_v = { + name = "://CTRL+V", + text = { + "Erstelle eine Kopie einer {C:cry_code}gewählten{}", + "Spielkarte oder Gebrauchsgegenstand", + }, + }, + c_cry_reboot = { + name = "://REBOOT", + text = { + "Erfrische {C:blue}Hände{} und {C:red}Abwürfe{},", + "hole {C:cry_code}alle{} Karten zurück ins Deck", + "und ziehe eine {C:cry_code}neue{} Hand", + }, + }, + c_cry_semicolon = { + name = ";//", + text = { + "Ende momentanen Nicht-Boss {C:cry_code}Blind{}", + "{C:cry_code}ohne{} Preisgeld zu bekommen", + }, + }, + c_cry_declare = { + name = "://DECLARE", + text = { + "Die {C:attention}aktuell{} gewählten Spielkarten", + "werden zu einer {C:cry_code}neuen{} Pokerhand, welche", + "gewertet wird, als würde sie ein {C:attention}#1#{} enthalten", + "Es können bis zu {C:attention}3{} {C:inactive}[#2#]{} Hände erzeugt werden", + }, + }, + }, + ["Content Set"] = { + set_cry_blind = { + name = "Blinds", + text = { + "{C:attention}Boss Blinds{}", + "hinzugefügt von Cryptid", + }, + }, + set_cry_code = { + name = "Code Karten", + text = { + "{C:cry_code}Code Karten{} und", + "dazugehöriger Inhalt", + }, + }, + set_cry_cursed = { + name = "Verfluchte Joker", + text = { + "Schädliche Joker mit", + "{X:cry_cursed,C:white}Verfluchter{} Seltenheit", + }, + }, + set_cry_deck = { + name = "Decks", + text = { + "{C:attention}Decks{} hinzugefügt", + "von Cryptid", + }, + }, + set_cry_epic = { + name = "Epische Joker", + text = { + "Joker mit", + "{C:cry_epic}Epischer{} Seltenheit", + "{C:inactive,s:0.8}(Zwischen Selten und Legendär)", + }, + }, + set_cry_exotic = { + name = "Exotische Joker", + text = { + "Mächtige Joker mit", + "{C:cry_exotic}Exotischer{} Seltenheit", + }, + }, + set_cry_m = { + name = "M Joker", + text = { + "Joker im Zusammenhang mit", + "dem Buchstaben {C:attention}M{}", + "und {C:attention}Lustiger Joker", + }, + }, + set_cry_meme = { + name = "Meme", + text = { + "Dinge im Zusammenhang mit", + "mehreren Referenzen", + }, + }, + set_cry_misc = { + name = "Verschiedenes", + text = { + "Dinge, die nicht in andere", + "{C:cry_ascendant}Thematische Sets{} passen", + }, + }, + set_cry_misc_joker = { + name = "Verschiedene Joker", + text = { + "{C:attention}Joker{}, die nicht in andere", + "{C:cry_ascendant}Thematische Sets{} passen", + }, + }, + set_cry_planet = { + name = "Planeten-Karten", + text = { + "Verschiedene {C:planet}Planeten-Karten", + "hinzugefügt von Cryptid", + }, + }, + set_cry_poker_hand_stuff = { + name = "Pokerhand Zeugs", + text = { + "Füge 5 neue {C:attention}Pokerhände{} hinzu", + "und aktiviere {C:attention}Aufgestiegene Hände", + }, + }, + set_cry_spectral = { + name = "Geister-Karten", + text = { + "{C:spectral}Geister-Karten{}", + "hinzugefügt von Cryptid", + }, + }, + set_cry_spooky = { + name = "Gruseliges Update", + text = { + "Gruseliges Update, inklusive", + "{C:cry_candy}Süßigkeiten{}-Joker", + }, + }, + set_cry_tag = { + name = "Tags", + text = { + "{C:attention}Tags{} hinzugefügt", + "von Cryptid", + }, + }, + set_cry_tier3 = { + name = "Stufe 3 Gutscheine", + text = { + "Eine zusätzliche {C:attention}Stufe{}", + "von Gutscheinen", + }, + }, + set_cry_timer = { + name = "Zeit-Mechanismen", + text = { + "Gegenstände mit {C:attention}zeitbasierten", + "Effekten und Mechanismen", + }, + }, + set_cry_voucher = { + name = "Versch. Gutscheine", + text = { + "Stufe 1 und 2 {C:attention}Gutscheine{}", + "hinzugefügt von Cryptid", + }, + }, }, Edition = { e_cry_astral = { @@ -522,14 +915,14 @@ return { "{C:attention}1{} mal mehr {C:attention}aus{}", "Chance von {C:green}#1# zu #2#{}", "sie {C:attention}#3#{} weiteres", - "mal {C:attention}auszulösen", + "Mal {C:attention}auszulösen", }, }, e_cry_double_sided = { name = "Doppelseitig", text = { "Diese Karte kann", - "{C:attention}gedreht{} werden um", + "{C:attention}gedreht{} werden, um", "eine andere Karte zu zeigen.", "{C:inactive}(Leere Seite kann mit anderer", "{C:inactive}Karte verschmolzen werden)", @@ -541,7 +934,7 @@ return { text = { "{C:white,X:mult} X#3# {} Mult", "Chance von {C:green}#1# zu #2#{}, dass diese", - "Karte beim auslösen", + "Karte beim Auslösen", "{C:attention}nicht{} {C:red}zerstört{} wird", }, }, @@ -550,13 +943,14 @@ return { text = { "Alle Werte auf dieser Karte sind", "ein {C:dark_edition}zufälliger{} Wert", - "zwichen {C:attention}X0.1{} und {C:attention}X10{} des originalen.", + "zwischen {C:attention}X0.1{} und {C:attention}X10{} des Originalwerts", "{C:inactive}(Wenn möglich){}", }, }, + -- TN: changed from 'golden' to better differentiate it from you regular gold card e_cry_gold = { - name = "Golden", - label = "Golden", + name = "Vergoldet", + label = "Vergoldet", text = { "Verdiene {C:money}$#1#{} bei Benutzung", "oder beim Auslösen", @@ -577,7 +971,7 @@ return { }, }, e_cry_noisy = { - name = "Geräuchvoll", + name = "Geräuschvoll", text = { "???", }, @@ -601,8 +995,55 @@ return { "wenn sie gewertet wird", }, }, + m_cry_light = { + name = "Licht-Karte", + text = { + "Wenn mit {C:attention}#4#{} {C:inactive}(#3#){} anderen", + "Spielkarten ausgelöst, erhalte {X:mult,C:white}X#1#{} Mult und", + "erhöhe Bedingung um {C:attention}5{}", + "{C:inactive}(Aktuell {X:mult,C:white}X#2#{C:inactive} Mult)", + }, + }, + m_cry_abstract = { + name = "Abstrakte Karte", + text = { + "{X:dark_edition,C:white}^#1#{} Mult,", + "Zählt als {C:attention}eigener{} Rank und Farbe", + "Chance von {C:green}#4# in #5#{}, Karte zu", + "{C:red,E:2}zerstören{} wenn in der Hand", + "am {C:attention}Ende der Runde{} oder", + "wenn {C:attention}Hand gespielt{} wird", + }, + }, }, Joker = { + j_cry_test_modest = { + name = "Test Joker", + text = { + "{C:chips}+#1#{} Chip#1#", + }, + }, + j_cry_test_mainline = { + name = "Test Joker", + text = { + "{C:chips}+#1#{} Chip#1#", + "{C:money}+$44{} am Anfang des {C:attention}Blinds{}", + }, + }, + j_cry_test_madness = { + name = "Test Joker", + text = { + "{C:chips}+#1#{} Chip#1#", + "{C:money}+$44444{} am Anfang des {C:attention}Blinds{}", + }, + }, + j_cry_test_cryptid_in_2025 = { + name = "Test Joker", + text = { + "{C:chips}+#1#{} Chip#1#", + "{C:money}+$44444{} am Anfang des {C:attention}Blinds{}", + }, + }, j_cry_adroit = { name = "Geschickter Joker", text = { @@ -615,15 +1056,16 @@ return { name = "Nostalgische Googol Play Karte", text = { "Verkaufe diese Karte um", - "{C:attention}2{} Kopien von dem linkesten {C:attention}Joker{} zu machen", + "{C:attention}#1#{} Kopie#1# vom {C:attention}Joker{} ganz links zu machen", "{C:inactive,s:0.8}Kopiert keine Nostalgischen Googol Play Karten{}", + "{C:inactive}(Muss Platz haben){}", }, }, j_cry_altgoogol_balanced = { name = "Nostalgische Googol Play Karte", text = { "Verkaufe diese Karte um", - "{C:attention}#1#{} Kopie#1# von dem linkesten {C:attention}Joker{} zu machen", + "{C:attention}#1#{} Kopie#1# vom {C:attention}Joker{} ganz links zu machen", "{C:inactive,s:0.8}Kopiert keine Nostalgischen Googol Play Karten{}", "{C:inactive}(Muss Platz haben){}", --todo: add "removes negative from copy" like Ankh/Invis Joker @@ -642,6 +1084,38 @@ return { name = "AP Joker", text = { "{X:mult,C:white} X#1# {} Mult gegen {C:attention}Boss Blinds{}" }, }, + j_cry_arsonist = { + name = "Brandstifter", + text = { + "Wenn gespielte Hand", + "ein {C:attention}Full House{} enthält,", + "{C:red}zerstöre{} alle Karten", + "nach Auszählung", + }, + }, + j_cry_astral_bottle = { + name = "Astral in einer Flasche", + text = { + "Wenn verkauft, füge {C:dark_edition}Astral{}", + "und {C:attention}Verderblich{} einem", + "zufälligen {C:attention}Joker{} hinzu", + }, + }, + j_cry_astral_bottle_mainline = { + name = "Astral in einer Flasche", + text = { + "Wenn verkauft, füge {C:dark_edition}Astral{}", + "und {C:attention}Verderblich{} einem", + "anderen, zufälligen {C:attention}Joker{} hinzu", + }, + }, + j_cry_astral_bottle_madness = { + name = "Astral in einer Flasche", + text = { + "Wenn verkauft, füge {C:dark_edition}Astral{}", + "einem zufälligen {C:attention}Joker{} hinzu", + }, + }, j_cry_big_cube = { name = "Großer Würfel", text = { @@ -651,11 +1125,11 @@ return { j_cry_biggestm = { name = "Riesig", text = { - "{X:mult,C:white} X#1# {} Mult bis zum Ende", - "der Runde wenn {C:attention}Pokerhand{}", - "ein {C:attention}#2#{} ist", + "{X:mult,C:white} X#1# {} Mult bis zum Ende der Runde,", + "wenn {C:attention}Pokerhand{} ein {C:attention}#2#{} ist", "{C:inactive}(Momentan {C:attention}#3#{}{C:inactive}){}", - "{C:inactive,s:0.8}nicht fett, hat nur große Knochen.", + "{C:inactive,s:0.8}Nicht fett, hat nur große Knochen.", + -- TODO localize #3# }, }, j_cry_blacklist = { @@ -663,15 +1137,25 @@ return { text = { "Wenn ein(e) {C:attention}#1#{} in der Hand oder gespielt ist,", "setze {C:chips}Chips{} und {C:mult}Mult{} zu 0", - "{C:red,E:2}zerstört sich selbst{} wenn kein {C:attention}#1#{} im deck ist", + "{C:red,E:2}zerstört sich selbst{} wenn kein {C:attention}#1#{} im Deck ist", "{C:inactive,s:0.8}Rang ändert sich nicht", }, }, + j_cry_rotten_egg = { + name = "Faules Ei", + text = { + "Setzt bei Erhalt den Verkaufswert", + "aller aktueller und zukünfitger Joker auf {C:attention}$#1#{}", + "Reduziert den Verkaufswert aller {C:attention}Joker{} um {C:attention}$#2#{}", + "am Ende der Runde, nach Erhalt von {C:attention}$#3#{} {C:inactive}[#4#]{}", + "durch den Verkauf von {C:attention}Jokern{}, {C:red}Zerstört sich selbst{}", + }, + }, j_cry_blender = { name = "Blender", text = { - "Erstelle ein {C:attention}zufäligen{}", - "Verbrauchsgegenstand wenn eine", + "Erstelle ein {C:attention}zufälligen{}", + "Verbrauchsgegenstand, wenn eine", "{C:cry_code}Code{} Karte benutzt wird.", "{C:inactive}(Muss Platz haben){}", }, @@ -679,7 +1163,7 @@ return { j_cry_blurred = { name = "Verschwommener Joker", text = { - "Gain {C:blue}+#1#{} Hand/Hände wenn", + "Erhalte {C:blue}+#1#{} H#<ände,and>1# wenn", "{C:attention}Blind{} ausgewählt wird", }, }, @@ -687,15 +1171,15 @@ return { name = "Bonk", text = { "Jeder {C:attention}Joker{} gibt {C:chips}+#1#{} Chips", - "Erhöhe anzahl um {C:chips}+#2#{} wenn", + "Erhöhe Anzahl um {C:chips}+#2#{} wenn", "{C:attention}Pokerhand{} ein {C:attention}#3#{} ist", - "{C:inactive,s:0.8}Lustige Joker geben statdessen{} {C:chips,s:0.8}+#4#{} {C:inactive,s:0.8}Chips{}", + "{C:inactive,s:0.8}Lustige Joker geben stattdessen{} {C:chips,s:0.8}+#4#{} {C:inactive,s:0.8}Chips{}", }, }, j_cry_bonkers = { name = "Bekloppter Joker", text = { - "{C:red}+#1#{} Mult wenn", + "{C:red}+#1#{} Mult, wenn", "gespielte Hand", "ein {C:attention}#2#{} enthält", }, @@ -704,17 +1188,17 @@ return { name = "Bonus Joker", text = { "Chance von {C:green}#1# zu #2#{} für jede", - "gespielte {C:attention}Bonus{} Karte die", - "{C:attention}Joker{} or {C:attention}Verbrauchgegenstand Slots", - "um {C:dark_edition}1{} zu erhöhen wenn sie gewertet werden.", - "{C:red}Funktioniert einmal pro Runde", - "{C:inactive,s:0.8}(Gleiche Chance für beide){}", + "gespielte {C:attention}Bonus{} Karte, die", + "{C:attention}Joker-{} oder {C:attention}Verbrauchsgegenstände-Slots", + "um {C:dark_edition}1{} zu erhöhen, wenn sie gewertet werden.", + "{C:red}Funktioniert zweimal pro Runde", + "{C:inactive,s:0.8}(Gleiche Chance für Beide){}", }, }, j_cry_booster = { name = "Booster Joker", text = { - "{C:attention}+#1#{} Booster Packet Slot", + "{C:attention}+#1#{} Booster Paket Slot#1#", "im Shop verfügbar", }, }, @@ -726,21 +1210,26 @@ return { "{C:attention}Spielkarte{} erneut {C:attention}auszulösen{}", "{C:inactive,s:0.8}Funktioniert nicht auf andere Lange Weilen{}", }, + unlock = { + "Mache nichts auf dem", + "Titelbildschirm für", + "{C:attention}10 Minuten{}", + }, }, j_cry_brittle = { name = "Zerbrechliche Süßigkeit", text = { "Für die nächsten {C:attention}#1#{} Hände,", - "füge {C:attention}Stein{}, {C:attention}Gold{}, oder {C:attention}Stahl{} zu", - "der rechtesten gewerteten Karte hinzu", + "füge {C:attention}Stein{}, {C:attention}Gold{}, oder {C:attention}Stahl{}", + "zur gewerteten Karte ganz rechts hinzu", }, }, j_cry_bubblem = { name = "Blasen M", text = { "Erstelle einen {C:dark_edition}Foil {C:attention}Lustigen Joker{}", - "wenn gespielte Hand einen", - "{C:attention}#1#{} enthält.", + "wenn gespielte Hand ein", + "{C:attention}#1#{} enthält", "{C:red,E:2}Zerstört sich selbst{}", }, }, @@ -753,12 +1242,20 @@ return { "für {C:mult}-#2#{} Mult", }, }, + j_cry_buttercup = { + name = "Butterblume", + text = { + "Kann {C:attention}#1#{} gewählt#1# Gegen#1# im Shop speichern", + "Wenn verkauft: Füge d#1# gespeicherten Gegen#1#", + "dem nächsten Shop hinzu", --man, german can be needlessly complicated #-.- + }, + }, j_cry_candy_basket = { name = "Süßigkeitenkorb", text = { - "Verkaufe diese Karte up {C:attention}#1#{} {C:cry_candy}Süßigkeiten{} zu erstellen", - "{C:attention}+#2#{} {C:cry_candy}Süßigkeiten{} für alle {C:attention}2{} besiegte Blinds", - "{C:attention}+#3#{} {C:cry_candy}Süßigkeiten{} für jede besiegte {C:attention}Boss Blind{}", + "Verkaufe diese Karte um {C:attention}#1#{} {C:cry_candy}Süßigkeiten{} zu erstellen", + "{C:attention}+#2#{} {C:cry_candy}Süßigkeiten{} für alle {C:attention}2{} besiegten Blinds", + "{C:attention}+#3#{} {C:cry_candy}Süßigkeiten{} für alle besiegten {C:attention}Boss Blinds{}", }, }, j_cry_candy_buttons = { @@ -771,7 +1268,7 @@ return { j_cry_candy_cane = { name = "Zuckerstange", text = { - "Für die nächsten {C:attention}#1#{} Runden,", + "Für die nächste#1# {C:attention}#1#{} Runde#1#,", "geben gespielte Karten {C:money}$#2#", "wenn {C:attention}erneut ausgelöst", }, @@ -779,53 +1276,67 @@ return { j_cry_candy_dagger = { name = "Süßigkeitendolch", text = { - "Wenn {C:attention}Blind{} ausgewält wurde,", + "Wenn {C:attention}Blind{} ausgewählt wird,", "zerstöre rechten Joker", "um eine {C:cry_candy}Süßigkeit{} zu erstellen.", }, }, j_cry_candy_sticks = { - name = "Zuckerstöcke", + name = "Zuckerstangen", text = { - "Der Effekt der nächsten Boss Bind ist nicht Aktiv", - "bis {C:attention}#1#{} Hand gespielt wurde.", + "Der Effekt der nächsten Boss Blind ist nicht aktiv", + "bis {C:attention}#1#{} #1# gespielt wurde.", }, }, j_cry_canvas = { name = "Leinwand", text = { - "{C:attention}Löse{} alle {C:attention}Jokers{} auf der linken Seite", + "{C:attention}Löse{} alle {C:attention}Joker{} auf der linken Seite", "{C:attention}so oft neu aus{} wie du nicht-{C:blue}Gewöhnliche{C:attention} Joker{}", "auf der rechten Seite hast", }, + unlock = { + "Löse einen {C:attention}Joker", + "{C:attention}114{} Mal in einer", + "Hand erneut aus", + }, }, j_cry_canvas_balanced = { name = "Leinwand", text = { - "{C:attention}Löse{} alle {C:attention}Jokers{} auf der linken Seite", + "{C:attention}Löse{} alle {C:attention}Joker{} auf der linken Seite", "{C:attention}so oft neu aus{} wie du nicht-{C:blue}Gewöhnliche{C:attention} Joker{}", "auf der rechten Seite hast", - "{C:inactive}(Up to 2 retriggers)", + "{C:inactive}(Bis zu 2 Mal)", }, unlock = { "Löse einen {C:attention}Joker", - "{C:attention}114{} mal in einer", - "Hand erneut aus.", + "{C:attention}114{} Mal in einer", + "Hand erneut aus", }, }, j_cry_caramel = { - name = "Karamel", + name = "Karamell", text = { "Jede gespielte Karte gibt", "{X:mult,C:white}X#1#{} Mult wenn gewertet", - "für die nächsten {C:attention}#2#{} Runden", + "für die nächste#2# {C:attention}#2#{} Runde#2#", + }, + }, + j_cry_cat_owl = { + name = "Katzen-Eule", + text = { + "{C:attention}Lucky Cards{} werden auch", + "als {C:attention}Echo Karten{} gewertet", + "{C:attention}Echo Karten{} werden auch", + "als {C:attention}Glückskarten{} gewertet", }, }, j_cry_chad = { name = "Chad", text = { - "Löse {C:attention}linkesten{} Joker", - "{C:attention}#1#{} weitere(s) mal(e) aus", + "Löse den Joker {C:attention}ganz links{}", + "{C:attention}#1#{} #1# aus", }, }, j_cry_chili_pepper = { @@ -833,17 +1344,17 @@ return { text = { "Dieser Joker bekommt {X:mult,C:white} X#2# {} Mult", "am Ende der Runde,", - "{C:red,E:2}zerstört sich selbst{} nach {C:attention}#3#{} Runden", - "{C:inactive}(Momentan{} {X:mult,C:white} X#1# {} {C:inactive}Mult){}", + "{C:red,E:2}zerstört sich selbst{} nach {C:attention}#3#{} Runde#3#", + "{C:inactive}(Aktuell{} {X:mult,C:white} X#1# {} {C:inactive}Mult){}", }, }, j_cry_chocolate_dice = { name = "Schokoladenwürfel", text = { - "Werfe einen {C:green}Zehnerwürfel{} wenn", + "Werfe einen {C:green}D10{} wenn", "{C:attention}Boss Blind{} besiegt wurde", - "um ein {C:cry_ascendant,E:1}Event{} zu starten.", - "{C:inactive}(Currently: #1#)", + "um ein {C:cry_ascendant,E:1}Event{} zu starten", + "{C:inactive}(Aktuell: #1#)", }, }, j_cry_circulus_pistoris = { @@ -851,25 +1362,60 @@ return { text = { "{X:dark_edition,C:white}^#1#{} Chips und {X:dark_edition,C:white}^#1#{} Mult", "wenn {C:attention}genau{} #2#", - "Hände ubrig sind.", + "#2# übrig #2#", }, }, j_cry_circus = { name = "Zirkus", - text = { - "{C:red}Seltene{} Joker geben {X:mult,C:white} X#1# {} Mult", - "{C:cry_epic}Epische{} Joker geben {X:mult,C:white} X#2# {} Mult", - "{C:legendary}Legendäre{} Joker geben {X:mult,C:white} X#3# {} Mult", - "{C:cry_exotic}Exotische{} Joker geben {X:mult,C:white} X#4# {} Mult", + text = Cryptid.get_circus_description(), --for translaters: this is automatically localized you can copy it over as long as cry_circus_generic is translated too + unlock = { + "Erhalten einen {C:red}Seltenen{},", + "{C:cry_epic}Epischen{} und {C:legendary}Legendären{}", + "Joker vor {C.attention}Ante 9{}", }, }, j_cry_clash = { name = "Der Kampf", text = { - "{X:mult,C:white} X#1# {} Mult wenn", + "{X:mult,C:white} X#1# {} Mult, wenn", "gespielte Hand", "ein {C:attention}#2#{} enthält", }, + unlock = { + "Gewinne einen Durchlauf", + "mit {E:1,C:attention}Ultimatives Paar{}", + "als letzte Hand", + }, + }, + j_cry_the = { + name = "Der", + text = { + "{X:mult,C:white} X#1# {} Mult, wenn", + "gespielte Hand {C:attention}#2# ist", + }, + unlock = { + "Gewinne einen Durchlauf", + "mit {E:1,C:attention}Nichts{}", + "als letzte Hand", + }, + }, + j_cry_clicked_cookie = { + name = "Angeklickter Keks", + text = { + "{C:chips}+#1#{} Chip#1#", + "{C:chips}-#2#{} Chip#2# wenn", + "du {C:attention}klickst", + }, + }, + j_cry_clockwork = { + name = "Uhrwerk Joker", + text = { + "Löse Stahl-Karten in der Hand alle {C:attention}#9#{} {C:inactive}(#1#){} Hände erneut aus", + "Dieser Joker erhält {X:mult,C:white}X#6#{} Mult {C:inactive}(X#5#){} alle {C:attention}#10#{} {C:inactive}(#2#){} Hände", + "Verwandle die erste gespielte Karte in eine Stahl-Karte alle {C:attention}#11#{} {C:inactive}(#3#){} Hände", + "Stahl-Karten in der Hand geben +{X:mult,C:white}X#8#{} Mult {C:inactive}(X#7#){} alle {C:attention}#12#{} {C:inactive}(#4#){} Hände", + }, + -- so. much. text. }, j_cry_CodeJoker = { name = "Code Joker", @@ -878,6 +1424,22 @@ return { "{C:cry_code}Code Karte{} wenn", "{C:attention}Blind{} ausgewählt wird", }, + unlock = { + "Entdecke {C:attention}jede", + "{C:cry_code}Code Karte", + }, + }, + j_cry_CodeJoker_modest = { + name = "Code Joker", + text = { + "Erstelle eine {C:dark_edition}Negative{}", + "{C:cry_code}Code Karte{} wenn", + "{C:attention}Boss Blind{} ausgewählt wird", + }, + unlock = { + "Entdecke {C:attention}jede", + "{C:cry_code}Code Karte", + }, }, j_cry_coin = { name = "Crypto Coin", @@ -890,8 +1452,8 @@ return { j_cry_compound_interest = { name = "Zinseszins", text = { - "Bekomme {C:money}#1#%{} deines gesammten Geldes", - "am ende der Runde,", + "Bekomme {C:money}#1#%{} deines gesamten Geldes", + "am Ende der Runde,", "erhöht sich um {C:money}#2#%{} für jede", "aufeinenderfolgende Auszahlung", }, @@ -899,9 +1461,25 @@ return { j_cry_copypaste = { name = "Copy/Paste", text = { - "Wenn eine {C:cry_code}Code{} Karte benutzt wird,", - "Chance von {C:green}#1# zu #2#{} um eine Kopie", - "zu deinen Verbrauchsgegenständen hinzuzufügen", + "Chance von {C:green}#1# zu #2#{}, eine Kopie", + "der genutzten {C:code}Code{} Karte zu erzeugen", + "{C:red}Funktioniert einmal pro Runde{}", + "{C:inactive}(Muss Platz haben)", + }, + }, + j_cry_copypaste_modest = { + name = "Copy/Paste", + text = { + "Kopiere gezogene", + "{C:cry_code}Code{} Karten", + "{C:inactive}(Muss Platz haben)", + }, + }, + j_cry_copypaste_madness = { + name = "Copy/Paste", + text = { + "Chance von {C:green}#1# zu #2#{}, eine Kopie", + "der genutzten {C:code}Code{} Karte zu erzeugen", "{C:inactive}(Muss Platz haben)", }, }, @@ -915,10 +1493,10 @@ return { j_cry_crustulum = { name = "Crustulum", text = { - "Dieser Joker bekommt {C:chips}+#2#{} Chips", + "Dieser Joker bekommt {C:chips}+#2#{} Chip#2#", "für jede {C:attention}Aktualisierung{} im Shop", "{C:green}Alle Aktualisierungen sind kostenlos{}", - "{C:inactive}(Momentan {C:chips}+#1#{C:inactive} chips)", + "{C:inactive}(Aktuell {C:chips}+#1#{C:inactive} Chip#1#)", }, }, j_cry_cryptidmoment = { @@ -932,7 +1510,7 @@ return { j_cry_cube = { name = "Würfel", text = { - "{C:chips}+#1#{} Chips", + "{C:chips}+#1#{} Chip#1#", }, }, j_cry_curse_sob = { @@ -943,13 +1521,17 @@ return { "{C:dark_edition,E:1}du kannst nicht entkommen...{}", "{C:inactive}(Muss Platz haben){}", }, + unlock = { + "Erhalte einen {C:purple}Ewigen{}", + "{C:attention}Obelisk", + }, }, j_cry_cursor = { name = "Cursor", text = { - "Dieser Joker bekommt {C:chips}+#2#{} Chips", + "Dieser Joker bekommt {C:chips}+#2#{} Chip#2#", "für jede {C:attention}gekaufte{} Karte", - "{C:inactive}(Momentan {C:chips}+#1#{C:inactive} Chips)", + "{C:inactive}(Aktuell {C:chips}+#1#{C:inactive} Chip#1#)", }, }, j_cry_cut = { @@ -958,24 +1540,48 @@ return { "Dieser Joker zerstört", "eine zufällige {C:cry_code}Code{} Karte", "und bekommt {X:mult,C:white} X#1# {} Mult", - "am ende des {C:attention}Shops{}", - "{C:inactive}(Momentan {X:mult,C:white} X#2# {C:inactive} Mult)", + "am Ende des {C:attention}Shops{}", + "{C:inactive}(Aktuell {X:mult,C:white} X#2# {C:inactive} Mult)", }, }, j_cry_delirious = { - name = "Deliriouser Joker", + name = "Joker im Delirium", text = { - "{C:red}+#1#{} Mult wenn", + "{C:red}+#1#{} Mult, wenn", "gespielte Hand", "einen {C:attention}#2#{} enthält", }, }, + j_cry_demicolon = { + name = "Demicolon", + text = { + "{C:attention}Erzwinge Auslösen{} des Jokers", + "auf der rechten Seite", + }, + }, + j_cry_starfruit = { --why is this here and not alphabetically sorted? cause en-us.lua said so + name = "Sternfrucht", + text = { + "{X:dark_edition,C:white}^#1#{} Mult", + "-{X:dark_edition,C:white}^#2#{} Mult pro", + "{C:attention}Aktualisierung{} im Shop", + }, + }, + j_cry_digitalhallucinations = { + name = "Digitale Halluzinationen", + text = { + "Wenn ein {C:attention}Booster Paket{} geöffnet wird,", + "Chance von {C:green}#1# in #2#{}, eine", + "zufällige {C:dark_edition}Negative{} Karte", + "dieses {C:attention}Typs{} zu erzeugen", + }, + }, j_cry_discreet = { name = "Diskreter Joker", text = { "{C:chips}+#1#{} Chips wenn", "gespielte Hand", - "einen {C:attention}#2#{} enthält", + "ein {C:attention}#2#{} enthält", }, }, j_cry_doodlem = { @@ -988,21 +1594,34 @@ return { }, }, ["j_cry_Double Scale"] = { - name = "Doppelwage", + name = "Doppelwaage", text = { - "Steigende {C:attention}Jokers{}", + "Steigende {C:attention}Joker{}", "steigen {C:attention}Quadratisch", "{C:inactive,s:0.8}(z.B. +1, +3, +6, +10)", "{C:inactive,s:0.8}(wächst um +1, +2, +3)", }, }, + ["j_cry_Double Scale_modest"] = { + name = "Doppelwaage", + text = { + "Steigende {C:attention}Joker{}", + "steigen {C:attention}doppelt{} so schnell", + '{C:inactive,s:0.8}"Es heißt Doppelwaage, nicht Quadratische Waage!"', + }, + }, j_cry_dropshot = { name = "Dropshot", text = { "Dieser Joker bekommt {X:mult,C:white} X#1# {} Mult für", - "jede gespielte, {C:attention}nicht gewertete{} {V:1}#2#{} Karte,", + "jede gespielte, aber {C:attention}nicht gewertete{} {V:1}#2#{} Karte,", "Farbe ändert sich jede Runde", - "{C:inactive}(Momentan {X:mult,C:white} X#3# {C:inactive} Mult)", + "{C:inactive}(Aktuell {X:mult,C:white} X#3# {C:inactive} Mult)", + }, + unlock = { + "Spiele eine {C:attention}High Card{}", + "mit {C:attention}4{} Karten", + "{C:attention}derselben Farbe", }, }, j_cry_dubious = { @@ -1012,22 +1631,31 @@ return { "gespielte Hand", "eine {C:attention}#2#{} enthält", }, + unlock = { + "Spiele eine {C:attention}High Card{}", + "mit {C:attention}4{} Karten", + "der {C:attention}gleichen Farbe", + }, }, j_cry_duos = { name = "Die Duos", text = { - "{X:mult,C:white} X#1# {} Mult wenn", + "{X:mult,C:white} X#1# {} Mult, wenn", "gespielte Hand", - "ein {C:attention}#2#{} enthält", + "{C:attention}#2#{} enthält", + }, + unlock = { + "Gewinne einen Durchlauf,", + "ohne {E:1,C:attention}Two Pair{} zu spielen", }, }, j_cry_duplicare = { name = "Duplicare", text = { - "Dieser Joker bekommt {X:mult,C:white} X#2# {} Mult", + "Dieser Joker bekommt {X:mult,C:white} X#2# {} Mult,", "wenn ein {C:attention}Joker{} oder eine", "Spielkarte ausgelöst wird", - "{C:inactive}(Momentan {X:mult,C:white} X#1# {C:inactive} Mult)", + "{C:inactive}(Aktuell {X:mult,C:white} X#1# {C:inactive} Mult)", }, }, j_cry_effarcire = { @@ -1035,7 +1663,7 @@ return { text = { "Zieht {C:green}volles Deck{} zur Hand", "wenn {C:attention}Blind{} ausgewählt wird", - '{C:inactive,s:0.8}"Wenn du mich bei meinem 1x nicht aushälst,', + '{C:inactive,s:0.8}"Wenn du mich bei meinem 1x nicht aushältst,', '{C:inactive,s:0.8}verdienst du much bei meinem 2x nicht"', }, }, @@ -1043,20 +1671,20 @@ return { name = "Energia", text = { "Wenn du einen {C:attention}Tag{} erhälst,", - "erställe {C:attention}#1#{} Kopien", + "erstelle {C:attention}#1#{} Kopie#1#", "und {C:attention}erhöhe{} die Nummer der", "Kopien um {C:attention}#2#", }, }, j_cry_equilib = { - name = "Ass Aequilibrium", + name = "Ass Äquilibrium", text = { "Joker erscheinen in der", - "Reinfolge der {C:attention}Sammlung{}", - "Erstelle {C:attention}#1#{} {C:dark_edition}Negative(n){} Joker", + "Reihenfolge der {C:attention}Sammlung{}", + "Erzeuge {C:attention}#1#{} {C:dark_edition}#1#{} Joker", "wenn eine Hand gespielt wird.", "{C:cry_exotic,s:0.8}Exotische {C:inactive,s:0.8}oder höhere Joker können nicht erscheinen", - "{s:0.8}Letzter erstellter Joker: {C:attention,s:0.8}#2#", + "{s:0.8}Letzter erzeugter Joker: {C:attention,s:0.8}#2#", }, }, j_cry_error = { @@ -1070,87 +1698,146 @@ return { text = { "Dieser Joker bekommt {X:mult,C:white} X#1# {} Mult", "für jede {C:attention}verkaufte{} Karte", - "{C:inactive}(Momentan {X:mult,C:white} X#2# {C:inactive} Mult)", + "mit {C:attention}Verkaufswert{} von mindestens {C:money}$3{}", + "{C:inactive}(Aktuell {X:mult,C:white} X#2# {C:inactive} Mult)", + }, + }, + j_cry_eternalflame2 = { + name = "Ewige Flamme", + text = { + "Dieser Joker bekommt {X:mult,C:white} X#1# {} Mult", + "für jede {C:attention}verkaufte{} Karte", + "{C:inactive}(Aktuell {X:mult,C:white} X#2# {C:inactive} Mult)", }, }, j_cry_exoplanet = { name = "Exoplanet", text = { - "{C:dark_edition}Holographische{} Karten", - "geben {C:mult}+#1#{} Mult", + "Andere {C:dark_edition}Holografische{} Karten", + "geben je {C:mult}+#1#{} Mult", }, }, j_cry_exponentia = { name = "Exponentia", text = { "Dieser Joker bekommt {X:dark_edition,C:white} ^#1# {} Mult", - "wenn {X:red,C:white} XMult {} ausgelöst wird.", - "{C:inactive}(Momentan {X:dark_edition,C:white} ^#2# {C:inactive} Mult)", + "wenn {X:red,C:white} XMult {} ausgelöst wird", + "{C:inactive}(Aktuell {X:dark_edition,C:white} ^#2# {C:inactive} Mult)", + }, + }, + j_cry_exposed = { + name = "Bloßgestellt", + text = { + "Löse alle gewerteten nicht-{C:attention}Bildkarten{}", + "{C:attention}#1#{} #1# aus,", + "alle {C:attention}Bildkarten{} sind geschwächt", + }, + }, + j_cry_eyeofhagane = { + name = "Auge von Hagane", + text = { + "Alle gespielten {C:attention}Bildkarten{}", + "werden {C:attention}Stahl-Karten{}", + "wenn gewertet", + }, + }, + j_cry_highfive = { + name = "High Five", + text = { + "Wenn der höchste {C:attention}gewertete Rang{}", + "{C:attention}5{} ist, wandle {C:attention}alle{} gewerteten", + "Karten in {C:attention}5{} um", + "{s:0.8,C:inactive}Asse werden als 1 angesehen", }, }, j_cry_facile = { name = "Facile", text = { - "{X:dark_edition,C:white}^#1#{} Mult wenn", - "gespielte Karten {C:attention}#2#{}", - "oder weniger mal ausgelöst werden.", + "{X:dark_edition,C:white}^#1#{} Mult, wenn", + "gespielte Karten {C:attention}#2#{} mal", + "oder weniger ausgelöst werden", + }, + }, + j_cry_familiar_currency = { + name = "Vertraute Währung", + text = { + "Erzeuge einen {C:attention}Meme-Joker{}", + "am Ende der Runde", + "für {C:money}$#1#{} {C:inactive}(falls möglich)", + "{C:inactive}(Muss Platz haben)", }, }, j_cry_filler = { name = "Der Füller", text = { - "{X:mult,C:white} X#1# {} Mult wenn", + "{X:mult,C:white} X#1# {} Mult, wenn", "gespielte Hand", "eine {C:attention}#2#{} enthält", }, + unlock = { + "Gewinne einen Durchlauf", + "ohne eine {E:1,C:attention}High Card{} zu spielen", + }, }, j_cry_fractal = { - name = "Fraktal Finger", + name = "Fraktaler Finger", text = { - "{C:attention}+#1#{} Karten auswahl Limit", + "{C:attention}+#1#{} Karten Auswahllimit", + }, + unlock = { + "Spiele ein {C:attention}Straight Flush{}", + "ohne das der {C:attention}Straight", + "ein {C:attention}Flush{} enthält", }, }, j_cry_flip_side = { - name = "Auf der anderen Seite...", + name = "Andererseits...", text = { "{C:dark_edition}Doppelseitige{} Joker nutzen", "ihre Rückseite für Effekte", "statt der Vorderseite", - "{C:attention}Löse{} alle {C:dark_edition}Doppelseitigen{} Joker erneut {C:attention}aus", + "{C:attention}Löse{} alle {C:dark_edition}Doppelseitigen{} Joker {C:attention}erneut aus", }, }, j_cry_foodm = { name = "Fast Food M", text = { "{C:mult}+#1#{} Mult", - "{C:red,E:2}zerstört sich selbst{} in {C:attention}#2#{} Runde(n)", + "{C:red,E:2}Zerstört sich selbst{} in {C:attention}#2#{} Runde(n)", "Erhöht sich um {C:attention}#3#{} Runden wenn", "{C:attention}Lustiger Joker verkauft{} wird", "{C:inactive,s:0.8}2 McDoubles, 2 McChickens{}", - "{C:inactive,s:0.8}Größe Pommes, 20 Stücke & Großer Kuchen{}", + "{C:inactive,s:0.8}Große Pommes, 20 Stück & Großer Kuchen{}", }, }, j_cry_foolhardy = { name = "Tollkühner Joker", text = { - "{C:red}+#1#{} Mult wenn", + "{C:red}+#1#{} Mult, wenn", "gespielte Hand", "ein {C:attention}#2#{} enthält", }, }, + j_cry_undefined = { + name = "Undefinierter Joker", + text = { + "{C:red}+#1#{} Mult, wenn gespielte", + "Hand {C:attention}#2#{} ist", + }, + }, j_cry_formidiulosus = { name = "Formidiulosus", text = { - "Wenn ein {X:cry_cursed,C:white}Verfluchter{} Joker erhalten wird, zerstöre ihn", - "Erstelle {C:attention}#1#{} {C:dark_edition}Negative {C:cry_candy}Süßigkeiten{} am Ende des Shops", - "{X:dark_edition,C:white}+^#2#{} Mult für jeden {C:cry_candy}Süßigkeitenjoker{} den du besitzt", - "{C:inactive}(Momenan {X:dark_edition,C:white}^#3#{C:inactive} Mult)", + "Wenn ein {X:cry_cursed,C:white}Verfluchter{} Joker erhalten wird, zerstöre ihn,", + "Erstelle {C:attention}#1#{} {C:dark_edition}Negative {C:cry_candy}Süßigkeit#1#{} am Ende des Shops,", + "{X:dark_edition,C:white}+^#2#{} Mult für jeden {C:cry_candy}Süßigkeiten-Joker{} den du besitzt", + "{C:inactive}(Aktuell {X:dark_edition,C:white}^#3#{C:inactive} Mult)", }, }, j_cry_foxy = { - name = "Fuchsiger Joker", + name = "Ausgefuchster Joker", text = { - "{C:chips}+#1#{} Chips wenn", + "{C:chips}+#1#{} Chip#1# wenn", "gespielte Hand", "ein {C:attention}#2#{} enthält", }, @@ -1159,15 +1846,15 @@ return { name = "Fidget Spinner", text = { "Dieser Joker bekommt {C:chips}+#2#{} Chips", - "wenn gespielte hand {C:attention}nicht{}", + "wenn gespielte Hand {C:attention}nicht{}", "die meistgespielte {C:attention}Pokerhand{} ist", "{C:inactive}(Momentan {C:chips}+#1#{C:inactive} Chips)", }, }, j_cry_fuckedup = { - name = "Abgefuckter Joker", + name = Cryptid_config.family_mode and "Aufgeräumter Joker" or "Abgefuckter Joker", text = { - "{C:red}+#1#{} Mult wenn", + "{C:red}+#1#{} Mult, wenn", "gespielte Hand", "ein {C:attention}#2#{} enthält", }, @@ -1176,14 +1863,14 @@ return { name = "Garden der Kreuzungen", text = { "Verdiene {C:money}$#1#{} wenn {C:attention}gespielte Hand{}", - "Ein {C:attention}Ass{} und eine {C:attention}7{} enthält", + "ein {C:attention}Ass{} und eine {C:attention}7{} enthält", }, }, j_cry_gemino = { name = "Gemini", text = { "{C:attention}Verdoppelt{} alle Werte", - "des linkesten {C:attention}Jokers", + "des {C:attention}Jokers{} ganz links", "am Ende der Runde", }, }, @@ -1191,38 +1878,42 @@ return { name = "Geist", text = { "Am Ende der Runde:", - "Chance von {C:green}#1# zu #2#{} einen", + "Chance von {C:green}#1# zu #3#{} einen", "zufälligen {C:attention}Joker{} zu {C:attention}besetzen", - "Chance von {C:green}#1# zu #3#{}", + "Chance von {C:green}#2# zu #4#{}", "{E:2,C:red}sich selbst zu zerstören", }, }, j_cry_giggly = { name = "Absurder Joker", text = { - "{C:red}+#1#{} Mult wenn", + "{C:red}+#1#{} Mult, wenn", "gespielte Hand", - "eine {C:attention}#2#{} enthält", + "ein {C:attention}#2#{} enthält", }, }, j_cry_goldjoker = { name = "Gold Joker", text = { - "Verdiene {C:money}#1#%{} des gesammten", - "Geldes am ende der Runde", + "Verdiene {C:money}#1#%{} des gesamten", + "Geldes am Ende der Runde", "Auszahlung erhöht sich um {C:money}#2#%{}", - "wenn eine {C:attention}Gold{}", - "Karte gewertet wird.", + "wenn eine {C:attention}Gold{} Karte gewertet wird", }, }, j_cry_googol_play = { name = "Googol Play Karte", text = { - "Chance von {C:green}#1# zu #2#{} für", - "{X:red,C:white} X#3# {} Mult", + "Chance von {C:green}#1# zu #2#{}", + "für {X:red,C:white} X#3# {} Mult", + }, + unlock = { + "Erziele eine Punktzahl", + "von {C:attention}1.0e100{} Chips", + "mit einer einzelnen Hand", }, }, - j_cry_happy = { + j_cry_happy = { -- :D name = ":D", text = { "Erstelle einen zufälligen {C:attention}Joker{}", @@ -1237,17 +1928,21 @@ return { text = { "{X:dark_edition,C:white}^#1#{} Mult nachdem du", "{C:attention}114{} Hände{} gespielt hast", - "{C:inactive}(Momentan #2#/114){}", - "{C:inactive,s:0.8}Es gibt keinen Platz so schön wie dein Zuhause!{}", + "{C:inactive}(Aktuell #2#/114){}", + "{C:inactive,s:0.8}Es gibt keinen Platz wie dein Zuhause!{}", }, }, j_cry_home = { name = "Das Zuhause", text = { - "{X:mult,C:white} X#1# {} Mult wenn", + "{X:mult,C:white} X#1# {} Mult, wenn", "gespielte Hand", "ein {C:attention}#2#{} enthält", }, + unlock = { + "Gewinne einen Durchlauf", + "ohne ein {E:1,C:attention}Full House{} zu spielen", + }, }, j_cry_hunger = { name = "Consume-able", @@ -1256,13 +1951,21 @@ return { "ein {C:attention}Verbrauchsgegenstand{} benutzt wird", }, }, + j_cry_huntingseason = { + name = "Jagdsaison", + text = { + "Wenn gespielte Hand genau {C:attention}3{} Karten enthält,", + "{C:red}zerstöre{} die Karte {C:attention}in der Mitte{} nach der Wertung", + }, + }, j_cry_iterum = { name = "Iterum", text = { "Löse alle Karten", - "{C:attention}#2#{} mal mehr aus,", + "{C:attention}#2#{} Mal mehr aus,", "jede Karte gibt", - "{X:mult,C:white} X#1# {} Mult wenn sie gewertet wird", + "{X:mult,C:white} X#1# {} Mult wenn gewertet", + "{C:inactive}(Maximal {}{C:attention}#3#{}{C:inactive} mal)", }, }, j_cry_jawbreaker = { @@ -1273,14 +1976,19 @@ return { "{E:2,C:red}Zerstört sich selbst{}", }, }, - j_cry_jimball = { + j_cry_jimball = { -- avery's fav! name = "Jimball", text = { "Dieser Joker bekommt {X:mult,C:white} X#1# {} Mult", - "für jede {C:attention}aufeinenderfolgende{} gespielte Hand", + "für jede {C:attention}aufeinander folgende{} gespielte Hand", "währende du deine", "am meisten gespielte {C:attention}Pokerhand{} spielst", - "{C:inactive}(Momentan {X:mult,C:white} X#2# {C:inactive} Mult)", + "{C:inactive}(Aktuell {X:mult,C:white} X#2# {C:inactive} Mult)", + }, + unlock = { + "Gewinne einen Durchlauf", + "mit {C:attention}einem einzigen Typ{}", + "{C:attention}Pokerhand", }, }, j_cry_jollysus = { @@ -1290,7 +1998,7 @@ return { "Wenn ein Joker {C:attention}verkauft{} wird", "{C:red}Funktioniert einmal pro Runde{}", "{C:inactive}#1#{}", - "{C:inactive,s:0.8}Seems legit...{}", + "{C:inactive,s:0.8}Scheint echt zu sein...{}", }, }, j_cry_jtron = { @@ -1298,23 +2006,30 @@ return { text = { "Dieser Joker bekommt {X:dark_edition,C:white} ^#1# {} Mult", "für jeden Standard {C:attention}Joker{}", - "{C:inactive}(Momentan {X:dark_edition,C:white}^#2#{C:inactive} Mult)", + "{C:inactive}(Aktuell {X:dark_edition,C:white}^#2#{C:inactive} Mult)", }, }, j_cry_kidnap = { name = "Entführung", text = { - "{C:red}Outdated Description{}", - "Verdiene {C:money}$#2#{} am Ende der Runde", - "Erhöhe Auszahlung um {C:money}$#1#{}", - "wenn ein {C:attention}Mult Typ{} oder", - "{C:attention}Chip Typ{} Joker verkauft wird", + "Verdiene {C:money}$#1#{} am Ende der Runde", + "pro verkauften einzigartigen {C:attention}Mult Typ{}", + "oder {C:attention}Chip Typ{} Joker in diesem Durchlauf", + "{C:inactive}(Aktuell {C:money}$#2#{C:inactive})", + }, + }, + j_cry_kittyprinter = { + name = "Katzendrucker", + text = { + "{X:mult,C:white} X#1# {} Mult", + "Alle {C:attention}Überspringen{}-Tags", + "werden {C:attention}Katzen-Tags{}", }, }, j_cry_kooky = { name = "Wahnsinniger Joker", text = { - "{C:red}+#1#{} Mult wenn", + "{C:red}+#1#{} Mult, wenn", "gespielte Hand", "ein {C:attention}#2#{} enthält", }, @@ -1323,29 +2038,36 @@ return { name = "Krusty der Clown", text = { "Dieser Joker bekommt", - "{X:mult,C:white} X#1# {} Mult wenn", + "{X:mult,C:white} X#1# {} Mult, wenn", "jede gespielte {C:attention}Karte{} gewertet wird", - "{C:inactive}(Momenan {X:mult,C:white} X#2# {C:inactive} Mult)", + "{C:inactive}(Aktuell {X:mult,C:white} X#2# {C:inactive} Mult)", }, }, j_cry_kscope = { name = "Kaleidoskop", text = { - "Füge {C:dark_edition}Polychrome{} zu", + "Füge {C:dark_edition}Polychrom{} zu", "einem zufälligen {C:attention}Joker{} hinzu", "wenn {C:attention}Boss Blind{} besiegt wird", }, + unlock = { + "Besiege einen {C:attention}Boss Blind", + "mit mindestens {C:attention}5{}", + "{C:attention}Spielkarten{} oder", + "{C:attention}Joker{} mit {C:attention}Edition{}", + }, }, j_cry_lebaron_james = { name = "LeBaron James", text = { - "Gespeilte und gewertete {C:attention}Könige{} geben", + "Gespielte und gewertete {C:attention}Könige{} geben", "{C:attention}+#1#{} Handgröße für diese Runde", - "und lösen {C:attention}in der Hand{} Effekte aus", + "und lösen Effekte {C:attention}in der Hand{} aus", + "{C:inactive}(Aktuell {}{C:attention}+#2#{}{C:inactive})", }, }, j_cry_lightupthenight = { - name = "Erläuchte die Nacht", + name = "Erleuchte die Nacht", text = { "Jede gespielte {C:attention}7{} oder {C:attention}2{}", "gibt {X:mult,C:white}X#1#{} Mult wenn gewertet", @@ -1357,23 +2079,23 @@ return { "Gib zukünftigen Kopien", "dieses Jokers {X:mult,C:white}X#1#{} Mult", "am Ende der Runde", - "{C:inactive}(Momentan {X:mult,C:white}X#2#{C:inactive} Mult){}", + "{C:inactive}(Aktuell {X:mult,C:white}X#2#{C:inactive} Mult){}", }, }, j_cry_loopy = { name = "Loopy", text = { "{C:attention}Löse{} alle Joker für jeden", - "{C:attention}Jolly Joker{}, der in dieser Runder", - "verkauft wurde erneut {C:attention}aus", - "{C:inactive}(Momentan{}{C:attention:} #1#{}{C:inactive} Auslösung(en)){}", + "{C:attention}Lustigen Joker{}, der in dieser Runder", + "verkauft wurde, {C:attention}erneut aus", + "{C:inactive}(Momentan{}{C:attention:} #1#{}{C:inactive} Auslösung#1#){}", "{C:inactive,s:0.8}Es war nicht genug Platz...{}", }, }, j_cry_lucky_joker = { name = "Glücksjoker", text = { - "Verdiene {C:money}$#1#{} jedes mal wenn eine", + "Verdiene {C:money}$#1#{} wenn eine", "{C:attention}Glückskarte{} {C:green}erfolgreich{}", "ausgelöst wird", }, @@ -1390,7 +2112,7 @@ return { text = { "Dieser Joker bekommt {X:mult,C:white} X#1# {} Mult", "wenn {C:attention}Lustiger Joker{} verkauft wird", - "{C:inactive}(Momentan {X:mult,C:white} X#2# {C:inactive} Mult)", + "{C:inactive}(Aktuell {X:mult,C:white} X#2# {C:inactive} Mult)", }, }, j_cry_M = { @@ -1406,8 +2128,8 @@ return { text = { "Wenn {C:attention}Blind{} ausgewählt wird,", "zerstöre jeden {C:attention}Joker{} außer", - "{C:legendary}M-Joker{} und {C:attention}Lustige Jokers{}", - "und erstelle 1 {C:attention}Lustigen Joker{}", + "{C:legendary}M-Joker{} und {C:attention}Lustige Joker{}", + "und erstelle #1# {C:attention}Lustigen Joker{}", "für jede zerstörte Karte", }, }, @@ -1415,23 +2137,31 @@ return { name = "Kühlschrankmagnet", text = { "Verdiene {C:money}$#1#{} am Ende der Runde", - "Es verdient {X:money,C:white} X#2# {} wenn du", + "Verdiene {X:money,C:white} X#2# {} wenn du", "{C:attention}#3#{} oder weniger {C:attention}Joker{} Karten hast", }, }, j_cry_manic = { name = "Manischer Joker", text = { - "{C:red}+#1#{} Mult wenn", + "{C:red}+#1#{} Mult, wenn", "gespielte Hand", - "einen {C:attention}#2#{} enthält", + "ein {C:attention}#2#{} enthält", }, }, j_cry_mario = { name = "Mario", text = { "Löse alle Joker", - "{C:attention}#1#{} weitere(s) mal aus", + "{C:attention}#1#{} #1# aus", + }, + }, + j_cry_mask = { + name = "Maske", + text = { + "Löse alle gewerteten {C:attention}Bildkarten{}", + "{C:attention}#1#{} #1# aus", + "Alle Nicht-{C:attention}Bildkarten{} sind geschwächt", }, }, j_cry_maximized = { @@ -1442,9 +2172,13 @@ return { "alle {C:attention}Zahlkarten{}", "zählen als {C:attention}10{}", }, + unlock = { + "Spiele ein {C:attention}Flush Five{}", + "aus {C:attention}Königen", + }, }, j_cry_maze = { - name = "Labyrint", + name = "Labyrinth", text = { "Alle Hände zählen als", "{C:attention}erste Hand{} der Runde,", @@ -1452,19 +2186,19 @@ return { "{C:attention}erster Abwurf{} der Runde", }, }, - j_cry_Megg = { + j_cry_megg = { name = "Mei", text = { "Verkaufe diese Karte um", - "{C:attention}#2#{} Lustige #3# zu erstellen, erhöhe", - "um {C:attention}#1#{} am Ende der Runde", + "{C:attention}#2#{} Lustige #3# zu erstellen,", + "erhöhe um {C:attention}#1#{} am Ende der Runde", }, }, j_cry_mellowcreme = { name = "Mellowcreme", text = { "Verkaufe diese Karte um", - "Verkaufswert aller {C:attention}Verbrauchgegenstände{}", + "Verkaufswert aller {C:attention}Verbrauchsgegenstände{}", "mit {C:attention}X#1#{} zu {C:attention}multiplizieren", }, }, @@ -1473,39 +2207,39 @@ return { text = { "{X:mult,C:white}X#1#{} Mult für jedes Mitglied", "im {C:attention}Cryptid Discord{}", - "{C:inactive}(Momentan {X:mult,C:white}X#2#{C:inactive} Mult)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:inactive}(Aktuell {X:mult,C:white}X#2#{C:inactive} Mult)", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_membershipcardtwo = { name = "Alte Mitgliedskarte", --Could probably have a diff Name imo text = { - "{C:chips}+#1#{} Chips für jedes Mitglied", + "{C:chips}+#1#{} Chip#1# für jedes Mitglied", "im {C:attention}Cryptid Discord{}", - "{C:inactive}(Momentan {C:chips}+#2#{C:inactive} Chips)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:inactive}(Aktuell {C:chips}+#2#{C:inactive} Chips)", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_membershipcardtwo_balanced = { name = "Alte Mitgliedskarte", --Could probably have a diff Name imo text = { - "{C:chips}+#1#{} Chip#1# für jedes Mitglied", + "{C:chips}+#1#{} Chip#1# für alle {C:attention}8{} Mitglieder", "im {C:attention}Cryptid Discord{}", "{C:inactive}(Momentan {C:chips}+#2#{C:inactive} Chip#2#)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_meteor = { name = "Meteorschauer", text = { "{C:dark_edition}Foil{} Karten", - "geben {C:chips}+#1#{} Chips", + "geben {C:chips}+#1#{} Chip#1#", }, }, j_cry_mneon = { name = "Neon M", text = { - "Bekomme {C:money}$#2#{} am Ende der Runde", + "Verdiene {C:money}$#2#{} am Ende der Runde", "Erhöhe Auszahlung um", "{C:money}$#1#{} für jeden {C:attention}Lustigen Joker{}", "oder {C:legendary}M Joker{} am", @@ -1518,7 +2252,7 @@ return { "Dieser Joker erhält {X:mult,C:white} X#1# {} Mult", "wenn keine {C:attention}Abwürfe{}", "am Ende der Runde genutzt wurden", - "{C:inactive}(Momentan {X:mult,C:white} X#2# {C:inactive} Mult)", + "{C:inactive}(Aktuell {X:mult,C:white} X#2# {C:inactive} Mult)", }, }, j_cry_monkey_dagger = { @@ -1528,15 +2262,15 @@ return { "wird der linke Joker zerstört", "und {C:attention}10 mal{} der Verkaufswert", "zu den {C:chips}Chips{} hinzugefügt", - "{C:inactive}(Momentan {C:chips}+#1#{C:inactive} Chips)", + "{C:inactive}(Aktuell {C:chips}+#1#{C:inactive} Chip#1#)", }, }, j_cry_monopoly_money = { name = "Monopoly Geld", text = { "Chance von {C:green}#1# zu #2#{} gekaufte", - "Gegenstände zu {C:attention}zerstören{}", - "Halbiert Geld wenn {C:attention}Verkauft", + "Gegenstände zu {C:attention}zerstören{},", + "halbiert Geld wenn {C:attention}verkauft", }, }, j_cry_morse = { @@ -1550,21 +2284,20 @@ return { j_cry_mprime = { name = "Tredecim", text = { - "Erstelle einen {C:legendary}M Joker{} am Ende der Runde", - "Jeder {C:attention}Lustige Joker{} oder {C:legendary}M Joker", - "gibt {X:dark_edition,C:white}^#1#{} Mult", - "Erhöhe anzahl um {X:dark_edition,C:white}^#2#{}", - "wenn {C:attention}Lustiger Joker verkauft{} wird", - "{C:inactive,s:0.8}(Tredecim exkludiert)", + "Erstelle einen {C:legendary}M Joker{} am Ende der Runde,", + "jeder {C:attention}Lustige Joker{} oder {C:legendary}M Joker gibt {X:dark_edition,C:white}^#1#{} Mult,", + "erhöhe Anzahl um {X:dark_edition,C:white}^#2#{}", + "wenn ein {C:attention}Lustiger Joker verkauft{} wird", + "{C:inactive,s:0.8}(Tredecim ausgenommen)", }, }, j_cry_mstack = { name = "M Stapel", text = { "Führe alle gespielten Karten einmal", - "für alle {C:attention}#2#{} {C:inactive}[#3#]{} {C:attention}Lustige Joker{} verkauft", - "erneut aus", - "{C:inactive}(Currently{}{C:attention:} #1#{}{C:inactive} Auslösungen){}", + "für alle {C:attention}#2#{} {C:inactive}[#3#]{} verkauften {C:attention}Lustige{}", + "{C:attention}Joker{} erneut aus", + "{C:inactive}(Aktuell {}{C:attention:}#1#{}{C:inactive} Auslösung#1#){}", }, }, j_cry_multjoker = { @@ -1572,22 +2305,23 @@ return { text = { "Chance von {C:green}#1# zu #2#{} für jede", "gespielte {C:attention}Mult{} Karte eine", - "{C:spectral}Cryptid{} Karte zu erstellen wenn sie Ausgewertet wird", + "{C:spectral}Cryptid{} Karte zu erstellen, wenn gewertet", "{C:inactive}(Muss Platz haben)", }, }, j_cry_necromancer = { name = "Totenbeschwörer", text = { - "Wenn ein Joker für mehr als {C:attention}$0 verkauft{} wird", - "Erhalte einen {C:attention}zufälligen{} Joker der in diesem Durchlauf {C:attention}verkauft{} wurde", - "und setzte seinen {C:attention}Verkaufspreis{} zu {C:attention}$0{}", + "Wenn ein Joker für mehr als {C:attention}#1# verkauft{} wird", + "erhalte einen {C:attention}zufälligen{} Joker, der in diesem Durchlauf", + "{C:attention}verkauft{} wurde und setze", + "seinen {C:attention}Verkaufspreis{} zu {C:attention}$0{}", }, }, j_cry_negative = { name = "Negativer Joker", text = { - "{C:dark_edition}+#1#{C:attention} Joker{} Slots", + "{C:dark_edition}+#1#{C:attention} Joker{} Slot#1#", }, }, j_cry_nice = { @@ -1608,25 +2342,26 @@ return { }, }, j_cry_nosound = { - name = "Kein Geräuch, keine Errinerung", + name = "Kein Geräusch, keine Erinnerung", text = { - "Löse alle {C:attention}7{}", - "{C:attention:}#1#{} weitere(s) mal(e) aus", + "Löse jede {C:attention}7{}", + "{C:attention:}#1#{} #1# aus", }, }, j_cry_notebook = { name = "Notizbuch", text = { - "Chance von {C:green} #1# zu #2#{} um {C:dark_edition}+1{} Joker", - "Slot pro {C:attention}Aktualisierung{} im Shop zu erhalten", - "{C:green}Funktioniert immer{} wenn du", + "Chance von {C:green} #1# zu #2#{} um {C:dark_edition}+#6#{} Joker", + "Slot#1# pro {C:attention}Aktualisierung{} im Shop zu erhalten,", + "{C:green}funktioniert immer{}, wenn du", "{C:attention}#5#{} oder mehr {C:attention}Lustige Joker{} hast", "{C:red}Funktioniert einmal pro Runde{}", - "{C:inactive}(Momentan {C:dark_edition}+#3#{}{C:inactive} and #4#){}", + "{C:inactive}(Aktuell {C:dark_edition}+#3#{}{C:inactive} und #4#){}", + -- TODO localize content of #4# }, }, j_cry_number_blocks = { - name = "Zahlblöcke", + name = "Nummernblöcke", text = { "Verdiene {C:money}$#1#{} am Ende der Runde", "Erhöhe Auszahlung um {C:money}$#2#{}", @@ -1637,24 +2372,28 @@ return { j_cry_nuts = { name = "Die Nuts", text = { - "{X:mult,C:white} X#1# {} Mult wenn", + "{X:mult,C:white} X#1# {} Mult, wenn", "gespielte Hand", - "einen {C:attention}#2#{} enthält", + "ein {C:attention}#2#{} enthält", + }, + unlock = { + "Gewinne einen Durchlauf,", + "ohne ein {E:1,C:attention}Straight Flush{} zu spielen", }, }, j_cry_nutty = { name = "Nutty Joker", text = { - "{C:red}+#1#{} Mult wenn", + "{C:red}+#1#{} Mult, wenn", "gespielte Hand", - "einen {C:attention}#2#{} enthält", + "ein {C:attention}#2#{} enthält", }, }, j_cry_oil_lamp = { - name = "Öl Lampe", + name = "Öllampe", text = { - "Am Ende der Runde", - "werden alle Werte des {C:attention}rechten{} Joker um {C:attention}x#1#{} erhöht", + "Am Ende der Runde werden", + "alle Werte des {C:attention}rechten{} Joker um {C:attention}x#1#{} erhöht", }, }, j_cry_oldblueprint = { @@ -1663,15 +2402,15 @@ return { "Kopiert Fähigkeit des", "rechten {C:attention}Jokers{}", "Chance von {C:green}#1# zu #2#{}, dass diese", - "Karte am Ende der Runde", - "zerstört wird", + "Karte zerstört wird", + "am Ende der Runde", }, }, j_cry_oldcandy = { name = "Nostalgische Süßigkeit", text = { - "Verkaufe diese Karte um", - "permantent {C:attention}+#1#{} Handgröße", + "Verkaufe diese Karte, um", + "dauerhaft {C:attention}+#1#{} Handgröße", "zu bekommen", }, }, @@ -1681,8 +2420,8 @@ return { "{C:attention}Dupliziere{} einen zufälligen", "{C:attention}Joker{} für alle {C:attention}4", "verkauften Joker Karten", - "{s:0.8}Nostalgischer unsichbarer Joker Excludiert{}", - "{C:inactive}(Momentan #1#/4){}", + "{s:0.8}Nostalgischer unsichtbarer Joker ausgenommen{}", + "{C:inactive}(Aktuell #1#/4){}", }, }, j_cry_panopticon = { @@ -1714,15 +2453,23 @@ return { "Wenn {C:attention}Blind{} ausgewählt wird,", "zerstöre rechten Joker", "und füge {C:attention}ein Viertel{} seines", - "Verkaufwertes zu seinem {X:chips,C:white} XChips {} hinzugefügt", - "{C:inactive}(Momentan {X:chips,C:white} X#1# {C:inactive} Chips)", + "Verkaufswerts zu seinem {X:chips,C:white} XChips {} hinzugefügt", + "{C:inactive}(Aktuell {X:chips,C:white} X#1# {C:inactive} Chips)", }, }, - j_cry_pity_prize = { name = "Trostpreis", text = { - "Wenn ein {C:attention}Booster Pack{} übersprungen wird, erhalte einen zufälligen {C:attention}Tag{}", + "Wenn ein {C:attention}Booster Paket{} übersprungen wird,", + "erhalte einen zufälligen {C:attention}Tag{}", + }, + }, + j_cry_pity_prize_modest = { + name = "Trostpreis", + text = { + "Wenn ein {C:attention}Booster Paket{} übersprungen wird,", + "erhalte einen zufälligen {C:attention}Tag{}", + "{C:red,E:2}Zerstört sich selbst{}", }, }, j_cry_pot_of_jokes = { @@ -1732,23 +2479,43 @@ return { "Erhöht sich um", "{C:blue}#2#{} jede Runde", }, + unlock = { + "Erhöhe deine {C:attention}Handgröße", + "auf {C:attention}12", + }, }, j_cry_primus = { name = "Primus", text = { "Dieser Joker erhält {X:dark_edition,C:white} ^#1# {} Mult", - "Wenn alle Karten in der Hand", + "Wenn alle gespielten Karten", "{C:attention}Asse{}, {C:attention}2{}, {C:attention}3{}, {C:attention}5{}, oder {C:attention}7{} sind", - "{C:inactive}(Momentan {X:dark_edition,C:white} ^#2# {C:inactive} Mult)", + "{C:inactive}(Aktuell {X:dark_edition,C:white} ^#2# {C:inactive} Mult)", + }, + }, + j_cry_pumpkin = { + name = "Kürbis", + text = { + "Verhindert Tod wenn gewertete Chips mindestens", + "{C:attention}50%{} der benötigten Chips erreichen", + "{C:attention}Wird zu Geschnitzter Kürbis", + "{C:attention}wenn{} {C:red}zerstört", + }, + }, + j_cry_carved_pumpkin = { + name = "Geschnitzter Kürbis", + text = { + "Die Fähigkeiten #1# nächsten {C:attention}#1#{} Boss Blinds", + "sind {C:attention}deaktiviert", }, }, j_cry_python = { name = "Python", text = { "Dieser Joker erhält", - "{X:mult,C:white} X#1# {} Mult wenn eine", + "{X:mult,C:white} X#1# {} Mult, wenn eine", "{C:cry_code}Code{} Karte benutzt wird", - "{C:inactive}(Momentan {X:mult,C:white} X#2# {C:inactive} Mult)", + "{C:inactive}(Aktuell {X:mult,C:white} X#2# {C:inactive} Mult)", }, }, j_cry_queens_gambit = { @@ -1763,15 +2530,19 @@ return { j_cry_quintet = { name = "Das Quintett", text = { - "{X:mult,C:white} X#1# {} Mult wenn", + "{X:mult,C:white} X#1# {} Mult, wenn", "gespielte Hand", - "einen {C:attention}#2#{} enthält", + "ein {C:attention}#2#{} enthält", + }, + unlock = { + "Gewinne einen Durchlauf", + "mit {E:1,C:attention}Five of a Kind{} als letzte Hand", }, }, j_cry_redbloon = { name = "Roter Ballon", text = { - "Verdiene {C:money}$#1#{} in {C:attention}#2#{} Runde(n)", + "Verdiene {C:money}$#1#{} in {C:attention}#2#{} Runde#2#", "{C:red,E:2}zerstört sich selbst{}", }, }, @@ -1781,8 +2552,8 @@ return { "{C:attention}-#1#{} Ante wenn", "{C:money}$#2#{} {C:inactive}($#3#){} ausgegeben wurde", "{s:0.8}Bedingung erhöht sich", - "{C:attention,s:0.8}expotentiel{s:0.8} für jede benutzung", - "{C:money,s:0.8}Nächste erhöhung: {s:1,c:money}$#4#", + "{C:attention,s:0.8}exponentiell{s:0.8} für jede Benutzung", + "{C:money,s:0.8}Nächste Erhöhung: {s:1,c:money}$#4#", }, }, j_cry_rescribere = { @@ -1790,32 +2561,38 @@ return { text = { "Wenn ein {C:attention}Joker{} verkauft wird,", "füge seinen Effekt", - "zu jeden anderen Joker hinzu", - "{C:inactive,s:0.8}Hat keinen effekt auf andere Rescribere{}", + "zu jedem anderen Joker hinzu", + "{C:inactive,s:0.8}Hat keinen Effekt auf andere Rescribere{}", }, }, j_cry_reverse = { name = "Reverse Card", text = { - "Fülle alle Joker slots {C:inactive}(Max 100){}", - "mit {C:dark_edition}Holographischen{} {C:attention}Lustigen Jokers{} wenn", - "{C:attention}Abgewurfene Pokerhand{} ein {C:attention}#1#{} ist", + "Fülle alle Joker Slots {C:inactive}(Max 100){}", + "mit {C:dark_edition}holografischen{} {C:attention}Lustigen Jokers{} wenn", + "{C:attention}Abgeworfene Pokerhand{} ein {C:attention}#1#{} ist", "{C:red,E:2}zerstört sich selbst{}", - "{C:inactive,s:0.8}Das ULTIMATIVE comeback{}", + "{C:inactive,s:0.8}Das ULTIMATIVE Comeback{}", }, }, j_cry_rnjoker = { name = "RNJoker", text = { - "Zufälliger effekt jede {C:attention}Ante{}", + "Zufälliger Effekt jede {C:attention}Ante{}", + --TODO this joker still pulls some english text from somewhere :( + }, + unlock = { + "Chance von {C:green}1 zu 20{},", + "diese Karte freizuschalten", + "beim {C:attention}Game Over", }, }, j_cry_sacrifice = { name = "Opfer", text = { - "Erstelle einen {C:green}Ungewönlichen{} Joker", - "und 3 {C:attention}Lustige Jokers{} wenn", - "eine {C:spectral}Geisterkarte{} benutzt wird", + "Erstelle #3# {C:green}Ungewöhnlich#3#{} Joker", + "und #2# {C:attention}Lustig#2# Joker{} wenn", + "eine {C:spectral}Geister{}-Karte benutzt wird", "{C:red}Funktioniert einmal pro Runde{}", "{C:inactive}#1#{}", }, @@ -1823,17 +2600,16 @@ return { j_cry_sapling = { name = "Setzling", text = { - "Nachdem {C:attention}#2#{} {C:inactive}[#1#]{} Verstärkte", - "Karten gewertet wurden, verkaufe diese Karte um", - "einen {C:cry_epic}Epischen{} {C:attention}Joker{} zu erstellen", - "{C:inactive,s:0.8}Erstellt einen {C:red,s:0.8}Seltenen{} {C:attention,s:0.8}Joker{}", - "{C:inactive,s:0.8}wenn {C:cry_epic,s:0.8}Epische{} {C:inactive,s:0.8}Joker deaktiviert sind{}", + "Nachdem {C:attention}#2#{} {C:inactive}[#1#]{} Verstärkte Karten", + "gewertet wurden, verkaufe diese Karte,", + "um einen {C:cry_epic}Epischen{} {C:attention}Joker{} zu erzeugen", + --TODO some weird variable stuff is happening here, see en-us.lua }, }, j_cry_savvy = { - name = "Versierter Joker", + name = "Ausgebuffter Joker", text = { - "{C:chips}+#1#{} Chips wenn", + "{C:chips}+#1#{} Chip#1# wenn", "gespielte Hand", "einen {C:attention}#2#{} enthält", }, @@ -1843,9 +2619,10 @@ return { text = { "Steigende {C:attention}Joker{} steigen", "als ein Grad-{C:attention}#1#{} Polynom", - "erhöhe Grad um {C:attention}#2#{}", + "Erhöhe Grad um {C:attention}#2#{}", "am Ende der Runde", - "{C:inactive,s:0.8}({C:attention,s:0.8}Scalae{C:inactive,s:0.8} exkludiert)", + "{C:inactive,s:0.8}({C:attention,s:0.8}Scalae{C:inactive,s:0.8} ausgenommen)", + "{C:inactive,s:0.8}(z.B. +1, +#3#, +#4#, +#5#)", }, }, j_cry_scrabble = { @@ -1853,28 +2630,28 @@ return { text = { "Chance von {C:green}#1# zu #2#{} um einen", "{C:dark_edition}Lustigen {C:green}Ungewöhnlichen{} Joker", - "zu erstellen wenn eine Hand gespielt wird", + "zu erzeugen, wenn eine Hand gespielt wird", }, }, j_cry_seal_the_deal = { name = "Seal the Deal", text = { - "Füge ein {C:attention}zufälliges Siegel{} zu jeder Karte,", + "Füge ein {C:attention}zufälliges Siegel{} zu jeder Karte hinzu,", "die in der {C:attention}letzten Hand{} der Runde gewertet wird", }, }, j_cry_shrewd = { name = "Kluger Joker", text = { - "{C:chips}+#1#{} Chips wenn", + "{C:chips}+#1#{} Chip#1# wenn", "gespielte Hand", - "einen {C:attention}#2#{} enthält", + "ein {C:attention}#2#{} enthält", }, }, j_cry_silly = { name = "Doofer Joker", text = { - "{C:red}+#1#{} Mult wenn", + "{C:red}+#1#{} Mult, wenn", "gespielte Hand", "ein {C:attention}#2#{} enthält", }, @@ -1883,29 +2660,34 @@ return { name = "Winzig", text = { "Erstelle ein {C:cry_jolly}Doppel M", - "Tag wenn {C:attention}Poker Hand{}", + "Tag wenn {C:attention}Pokerhand{}", "ein {C:attention}#1#{} ist", - "{C:inactive,s:0.8}ok, also im wesentlichen bin ich richtig klen", + "{C:inactive,s:0.8}ok also im wesentlichen bin ich sehr klein", }, }, j_cry_soccer = { name = "Einer für Alle", --changed the name from latin because this isn't exotic text = { - "{C:attention}+#1#{} Joker Slot", - "{C:attention}+#1#{} Booster Packer Slot", + "{C:attention}+#1#{} Joker Slot#1#", + "{C:attention}+#1#{} Booster Packet Slot#1#", "{C:attention}+#1#{} Handgröße", - "{C:attention}+#1#{} Verbrauchsgegenstand Slot", - "{C:attention}+#1#{} Karte im Shop", + "{C:attention}+#1#{} Verbrauchsgegenstand Slot#1#", + "{C:attention}+#1#{} Karte#1# im Shop", + "{C:attention}+#1#{} Gutschein Slot#1#", + }, + unlock = { + "Gewinne einen Durchlauf", + "mit nur {C:attention}High Card", }, }, j_cry_soccer_balanced = { name = "Einer für Alle", --changed the name from latin because this isn't exotic text = { - "{C:attention}+#1#{} Joker Slot#1#", "{C:attention}+#1#{} Booster Packer Slot#1#", "{C:attention}+#1#{} Handgröße", "{C:attention}+#1#{} Verbrauchsgegenstand Slot#1#", "{C:attention}+#1#{} Karte#1# im Shop", + "{C.attention}+#1#{} Gutschein Slot#1#", }, unlock = { "Gewinne einen Durchlauf", @@ -1913,29 +2695,107 @@ return { }, }, j_cry_fleshpanopticon = { - name = "Fleischpanoptikum", + name = "Fleisch-Panoptikum", text = { - "{C:red}X#1#{} {C:attention}Boss Blind{} größe", - "Wenn eine {C:attention}Boss Blind{} besiegt wurde,", + "{C:red}X#1#{} {C:attention}Boss Blind{} Größe", + "Wenn ein {C:attention}Boss Blind{} besiegt wurde,", "{C:red}zerstört sich selbst{}, und erstellt", "eine {C:dark_edition}Negative{} {C:spectral}Portal{} Karte", - '{C:inactive,s:0.8}"Ein Gefängnis... zum halten von... mir?"', + '{C:inactive,s:0.8}"Ein Gefängnis... zum Halten von... mir?"', + }, + }, + -- TN: This Joker's name and effect is based on 'Sock and Buskin', which was + -- translated to 'Komödie und Tragödie'. (https://en.wikipedia.org/wiki/Sock_and_buskin) + -- Therefore, translating this to 'Socke und Socke' doesn't really make sense, + -- and neither does 'Komödie und Komödie'. So, 'Komische Socke' it is. + -- Also, look at this Joker's art. It's perfect. ~Avery + j_cry_sock_and_sock = { + name = "Komische Socke", + text = { + "Löse alle gespielten", + "{C:attention}Abstrakten{} Karten {C:attention}#1#{} #1# aus", + }, + }, + j_cry_brokenhome = { + name = "Zerstörtes Zuhause", + text = { + "{X:mult,C:white} X#1# {} Mult", + "Chance von {C:green}#2# zu #3#{}", + "diese Karte am Ende der Runde", + "zu zerstören", + }, + }, + j_cry_yarnball = { + name = "Wollknäuel", + text = { + "Füge das Level des {C:attention}Katzen-Tag{} mit dem höchsten Level", + "zu allen {C:green}aufgeführten Wahrscheinlichkeiten{} hinzu", + }, + }, + j_cry_pizza = { + name = "Pizza", + text = { + "Nach {C:attention}#1#{} {C:inactive}[#2#]{} Runde#1#", + "verkaufe diesen Joker, um", + "{C:attention}#3#{} Pizzastücke zu erzeugen", + }, + }, + j_cry_pizza_slice = { + name = "Pizzastück", + text = { + "Dieser Joker erhält {X:mult,C:white}X#1#{} Mult", + "wenn ein {C:attention}Pizzastück{} verkauft wird", + "{C:inactive}(Aktuell{} {X:mult,C:white}X#2#{}{C:inactive} Mult){}", + }, + }, + j_cry_paved_joker = { + name = "Gepflasteter Joker", + text = { + "Steinkarten könen Lücken", --TODO: Steinkarten oder Stein-Karten? + "von {C:attention}#1#{} in", + "{C:attention}Straights{} and {C:attention}Flushes{} auffüllen", + }, + }, + j_cry_fading_joker = { + name = "Verschwindender Joker", + text = { + "Diese Joker erhält", + "{X:mult,C:white}X#1#{} Mult wenn", + "eine {C:attention}Verderbliche{} Karte geschwächt wird", + "{C:inactive}(Aktuell{} {X:mult,C:white}X#2#{} {C:inactive}Mult){}", + }, + }, + j_cry_poor_joker = { + name = "Armer Joker", + text = { + "Diese Joker erhält", + "{C:mult}+#1#{} Mult wenn", + "eine {C:attention}Gemietete{} Karte Geld nimmt", + "{C:inactive}(Aktuell{} {C:mult}+#2#{} {C:inactive}Mult){}", }, }, j_cry_spaceglobe = { name = "Himmelsglobus", text = { "Dieser Joker bekommt {X:chips,C:white}X#2#{} Chips", - "wenn {C:attention}poker hand #3#{} ist,", + "wenn {C:attention}Pokerhand{} ein {C:attention}#3#{} ist,", "Hand ändert sich jede Runde", - "{C:inactive}(Momentan{} {X:chips,C:white}X#1#{} {C:inactive}Chips){}", + "{C:inactive}(Aktuell{} {X:chips,C:white}X#1#{} {C:inactive}Chips){}", + }, + }, + j_cry_spectrogram = { + name = "Spektrogramm", + text = { + "Löst den Joker ganz rechts {C:attention}erneut aus{},", + "einmal für jede {C:attention}Echo-Karte", + "die gespielt und gewertet wird", }, }, j_cry_speculo = { name = "Speculo", text = { "Erstellt eine {C:dark_edition}Negative{} Kopie", - "Eines Zufälligen {C:attention}Jokers{}", + "eines zufälligen {C:attention}Jokers{}", "am Ende des {C:attention}Shops", "{C:inactive,s:0.8}Kopiert keine anderen Speculo{}", }, @@ -1943,12 +2803,12 @@ return { j_cry_spy = { name = "Spion", text = { - "{X:mult,C:white} X#2# {} Mult, {C:dark_edition}+1{C:attention} Joker{} slot", + "{X:mult,C:white} X#2# {} Mult, {C:dark_edition}+1{C:attention} Joker{} Slot", "{C:inactive}Dieser #1# ist ein Spion!", }, }, j_cry_stardust = { - name = "Sternstaub", + name = "Sternenstaub", text = { "{C:dark_edition}Polychrome{} Karten", "geben {X:mult,C:white}X#1#{} Mult", @@ -1959,18 +2819,22 @@ return { text = { "Dieser Joker zerstört eine", "zufällige {C:planet}Planeten{} Karte", - "und erhält {X:dark_edition,C:white} ^#1# {} Mult", + "um {X:dark_edition,C:white} ^#1# {} Mult zu erhalten", "am Ende das {C:attention}Shops{}", - "{C:inactive}(Momentan {X:dark_edition,C:white} ^#2# {C:inactive} Mult)", + "{C:inactive}(Aktuell {X:dark_edition,C:white} ^#2# {C:inactive} Mult)", }, }, j_cry_stronghold = { name = "Die Festung", text = { - "{X:mult,C:white} X#1# {} Mult wenn", + "{X:mult,C:white} X#1# {} Mult, wenn", "gespielte Hand", "ein {C:attention}#2#{} enthält", }, + unlock = { + "Gewinne einen Durchlauf mit", + "{E:1,C:attention}Bollwerk{} als letzte Hand", + }, }, j_cry_subtle = { name = "Subtiler Joker", @@ -1983,7 +2847,7 @@ return { j_cry_supercell = { name = "Supercell", text = { - "{C:chips}+#1#{} Chips, {C:mult}+#1#{} Mult,", + "{C:chips}+#1#{} Chip#1#, {C:mult}+#1#{} Mult,", "{X:chips,C:white}X#2#{} Chips, {X:mult,C:white}X#2#{} Mult", "Verdiene {C:money}$#3#{} am", "Ende der Runde", @@ -2001,7 +2865,7 @@ return { name = "SUS", text = { "Am Ende der Runde, erstelle", - "eine {C:attention}Kopie{} einer Zufälligen", + "eine {C:attention}Kopie{} einer zufälligen", "Karte {C:attention}in der Hand{},", "zerstöre alle anderen", "{C:attention,s:0.8}Könige{s:0.8} von {C:hearts,s:0.8}Herz{s:0.8} sind priorisiert", @@ -2010,10 +2874,14 @@ return { j_cry_swarm = { name = "Der Schwarm", text = { - "{X:mult,C:white} X#1# {} Mult wenn", + "{X:mult,C:white} X#1# {} Mult, wenn", "gespielte Hand", "ein {C:attention}#2#{} enthält", }, + unlock = { + "Gewinne einen Durchlauf mit", + "{E:1,C:attention}Flush Five{} als letzte Hand", + }, }, j_cry_sync_catalyst = { name = "Sync Katalysator", @@ -2025,14 +2893,14 @@ return { j_cry_tax_fraud = { name = "Steuerbetrug", text = { - "Am Ende der Runde", "Erhalte {C:attention}$#1#{} für jeden {C:attention}Gemieteten Joker", + "am Ende der Runde", }, }, j_cry_tenebris = { name = "Tenebris", text = { - "{C:dark_edition}+#1#{C:attention} Joker{} Slots", + "{C:dark_edition}+#1#{C:attention} Joker{} Slot#1#", "Verdiene {C:money}$#2#{} am Ende der Runde", }, }, @@ -2048,42 +2916,98 @@ return { j_cry_treacherous = { name = "Tückischer Joker", text = { - "{C:chips}+#1#{} Chips wenn", + "{C:chips}+#1#{} Chip#1# wenn", "gespielte Hand", "ein {C:attention}#2#{} enthält", }, }, + j_cry_nebulous = { + name = "Nebelhafter Joker", + text = { + "{C:chips}+#1#{} Chip#1# wenn gespielte", + "Hand {C:attention}#2#{} ist", + }, + }, + j_cry_words_cant_even = { + name = "Worte Können Nicht Einmal Beginnen, Diesen Joker Zu Beschreiben", + text = { + "{X:mult,C:white}X#1#{} Mult, wenn", + "gespielte Hand", + "{C:attention}#2#{} enthält", + }, + }, + j_cry_many_lost_minds = { + name = "Viele Haben Den Verstand Verloren, Um Diesen Joker Zu Verstehen", + text = { + "{C:chips}+#1#{} Chips wenn", + "gespielte Hand", + "{C:attention}#2#{} enthält", + }, + }, + j_cry_annihalation = { + name = "Die Vollständige Und Totale Vernichtung Von Allem Was Balatro Ausmacht", + text = { + "{X:dark_edition,C:white}^#1#{} Mult, wenn", + "gespielte Hand ein", + "{C:attention}#2#{} enthält", + }, + unlock = { + "Gewinne einen Durchlauf mit", + "{E:1,C:attention}#1#{} als letzte Hand", + }, + }, j_cry_trick_or_treat = { name = "Süßes oder Saures", text = { "Wenn {C:attention}verkauft{}:", - "Chance von {C:green}#1# zu #2#{} {C:attention}2{} {C:cry_candy}Süßigkeiten{} zu erstellen", + "Chance von {C:green}#1# zu #2#{} {C:attention}#3#{} {C:cry_candy}Süßigkeiten{} zu erstellen", "Sonst erstelle einen {X:cry_cursed,C:white}Verfluchten{} Joker", - "{C:inactive}(Kann überfießen)", + "{C:inactive}(Kann überfließen)", }, }, j_cry_tricksy = { name = "Tricksy Joker", text = { - "{C:chips}+#1#{} Chips wenn", + "{C:chips}+#1#{} Chip#1# wenn", "gespielte Hand", - "einen {C:attention}#2#{} enthält", + "ein {C:attention}#2#{} enthält", }, }, j_cry_triplet_rhythm = { name = "Triolenrhythmus", text = { - "{X:mult,C:white} X#1# {} Mult wenn gewertete Hand", + "{X:mult,C:white} X#1# {} Mult, wenn gewertete Hand", "{C:attention}exakt{} drei {C:attention}3{} enthält", }, }, + j_cry_tropical_smoothie = { + name = "Tropischer Smoothie", + text = { + "Verkaufe diese Karte,", + "um den Wert der anderen Joker", + "mit {C:attention}X#1#{} zu {C:attention}multiplizieren{}", + }, + }, j_cry_unity = { name = "The Einigkeit", text = { - "{X:mult,C:white} X#1# {} Mult wenn", + "{X:mult,C:white} X#1# {} Mult, wenn", "gespielte Hand", "ein {C:attention}#2#{} enthält", }, + unlock = { + "Gewinne einen Durchlauf", + "mit {E:1,C:attention}Flush House", + "als letzter Hand", + }, + }, + -- TN: both 'Universe' and 'Universum' translate to 'Universum', so i had to find a different word + j_cry_universe = { + name = "Kosmos", + text = { + "Andere {C:dark_edition}Astral{}-Karten", + "geben je {X:dark_edition,C:white}^#1#{} Mult", + }, }, j_cry_universum = { name = "Universum", @@ -2099,26 +3023,26 @@ return { "Wenn {C:attention}Blind{} ausgewählt wird,", "zerstöre linken Joker", "und füge {C:attention}ein Fünftel{} des", - "Verkaufwertes als {X:mult,C:white} XMult {} hinzu", - "{C:inactive}(Momentan {X:mult,C:white} X#1# {C:inactive} Mult)", + "Verkaufswerts als {X:mult,C:white} XMult {} hinzu", + "{C:inactive}(Aktuell {X:mult,C:white} X#1# {C:inactive} Mult)", }, }, j_cry_verisimile = { name = "Non Verisimile", text = { - "Wenn eine Warscheinlichkeit", + "Wenn eine Wahrscheinlichkeit", "{C:green}erfolgreich{} auslöst,", - "erhällt dieser Joker {X:red,C:white}XMult{}", - "gleich der {C:attention}Warscheinlichkeit", - "{C:inactive}(Momentan {X:mult,C:white} X#1# {C:inactive} Mult)", + "erhält dieser Joker {X:red,C:white}XMult{}", + "gleich der angegeben {C:attention}Wahrscheinlichkeit", + "{C:inactive}(Aktuell {X:mult,C:white} X#1# {C:inactive} Mult)", }, }, j_cry_virgo = { name = "Virgo", text = { "Dieser Joker erhält {C:money}$#1#{} {C:attention}Verkaufswert{}", - "wenn {C:attention}Pokerhand{} ein {C:attention}#2#{} enthält", - "Verkaufe diese Karte um einen", + "wenn {C:attention}Pokerhand{} ein {C:attention}#2#{} enthält,", + "verkaufe diese Karte, um einen", "{C:dark_edition}Polychrome{} {C:attention}Lustigen Joker{} für", "alle {C:money}$4{} {C:attention}Verkaufswert{} zu erstellen {C:inactive}(Min 1){}", }, @@ -2126,7 +3050,7 @@ return { j_cry_wacky = { name = "Spinner Joker", text = { - "{C:red}+#1#{} Mult wenn", + "{C:red}+#1#{} Mult, wenn", "gespielte Hand", "ein {C:attention}#2#{} enthält", }, @@ -2146,13 +3070,13 @@ return { }, }, j_cry_wee_fib = { - name = "Weebonacci", + name = "Weebonacci", -- gotta be my fav name text = { "Dieser Joker bekommt", - "{C:mult}+#2#{} Mult wenn ein", + "{C:mult}+#2#{} Mult, wenn ein", "{C:attention}Ass{}, {C:attention}2{}, {C:attention}3{}, {C:attention}5{}, oder {C:attention}8{}", "gewertet wird", - "{C:inactive}(Momentan {C:mult}+#1#{C:inactive} Mult)", + "{C:inactive}(Aktuell {C:mult}+#1#{C:inactive} Mult)", }, }, j_cry_weegaming = { @@ -2167,38 +3091,145 @@ return { name = "Rad der Hoffnung", text = { "Dieser Joker erhält", - "{X:mult,C:white} X#1# {} Mult wenn ein", - "{C:attention}Rad des Schicksals{} nicht erfolgreich auslöst", - "{C:inactive}(Momentan {X:mult,C:white} X#2# {C:inactive} Mult)", + "{X:mult,C:white} X#1# {} Mult, wenn ein", + "{C:attention}Rad des Schicksals{}", + "nicht erfolgreich auslöst", + "{C:inactive}(Aktuell {X:mult,C:white} X#2# {C:inactive} Mult)", }, }, j_cry_whip = { - name = "Die PEITCHE", + name = "Die PEITSCHE", text = { "Dieser Joker erhält {X:mult,C:white} X#1# {} Mult", - "wenn die {C:attention}Poker hand{} eine", + "wenn die {C:attention}Pokerhand{} eine", "{C:attention}2{} und {C:attention}7{} unterschiedlicher Farben enthält", - "{C:inactive}(Momentan {X:mult,C:white} X#2# {C:inactive} Mult)", + "{C:inactive}(Aktuell {X:mult,C:white} X#2# {C:inactive} Mult)", + }, + }, + j_cry_wonka_bar = { + name = "Wonka Bar", + text = { + "Verkaufe diese Karte um", + "dauerhaft {C:attention}+#1#{} Karte#1#", + "Auswahllimit zu erhalten", }, }, j_cry_wrapped = { name = "Eingewickelte Süßigkeit", text = { - "Erstelle einen zufälligen {C:attention}Essen Joker{}", - "in {C:attention}#1#{} Runde(n)", + "Erstelle einen zufälligen", + "{C:attention}Essen-Joker{} in {C:attention}#1#{} Runde#1#", "{C:red,E:2}Zerstört sich selbst{}", }, }, j_cry_wtf = { - name = "Die Hölle!?", + name = Cryptid_config.family_mode and "Das Cluster" or "Zur Hölle!?", text = { - "{X:mult,C:white} X#1# {} Mult wenn", + "{X:mult,C:white} X#1# {} Mult, wenn", "gespielte Hand", "ein {C:attention}#2#{} enthält", }, + unlock = { + "Gewinne einen Durchlauf mit", + "{E:1,C:attention}#1#{} als letzte Hand", + }, + }, + j_cry_zooble = { + name = "Zooble", + text = { + "Wenn gespielte Hand", + "{C:attention}kein Straight{} enthält,", + "erhält dieser Joker {C:mult}+#2#{} Mult für jeden", + "{C:attention}einzigartigen Rang{} in gewerteter Hand", + "{C:inactive}(Aktuell {C:mult}+#1#{C:inactive} Mult)", + }, }, }, Planet = { + c_cry_asteroidbelt = { + name = "Asteroidengürtel", + text = { + "{S:0.8}({S:0.8,V:1}lvl.#1#{S:0.8}){} Aufwertung für", + "{C:attention}#2#", + "{C:mult}+#3#{} Mult and", + "{C:chips}+#4#{} Chip#4#", + }, + }, + c_cry_void = { + name = "Leere", + text = { + "{S:0.8}({S:0.8,V:1}lvl.#1#{S:0.8}){} Aufwertung für", + "{C:attention}#2#", + "{C:mult}+#3#{} Mult and", + "{C:chips}+#4#{} Chip#4#", + }, + }, + c_cry_marsmoons = { + name = "Phobos & Deimos", + text = { + "{S:0.8}({S:0.8,V:1}lvl.#1#{S:0.8}){} Aufwertung für", + "{C:attention}#2#", + "{C:mult}+#3#{} Mult and", + "{C:chips}+#4#{} Chip#4#", + }, + }, + -- Reserved Spot For None Hand Planet + c_cry_nibiru = { + name = "Nibiru", + text = { + "{S:0.8}({S:0.8,V:1}lvl.#1#{S:0.8}){} Aufwertung für", + "{C:attention}#2#", + "{C:mult}+#3#{} Mult and", + "{C:chips}+#4#{} Chip#4#", + }, + }, + c_cry_universe = { + name = Cryptid_config.family_mode and "Universum" or "Das Universum In Seiner Verfickten Gesamtheit", + text = { + "{S:0.8}({S:0.8,V:1}lvl.#1#{S:0.8}){} Aufwertung für", + "{C:attention}#2#", + "{C:mult}+#3#{} Mult and", + "{C:chips}+#4#{} Chip#4#", + }, + }, + c_cry_planetlua = { + name = "Planet.lua", + text = { + "Chance von {C:green}#1# zu #2#{}", + "Jede {C:legendary,E:1}Pokerhand{}", + "um {C:attention}1{} Level aufzuwerten", + }, + }, + c_cry_nstar = { + name = "Neutronenstern", + text = { + "Verbessere eine zufällige", + "Pokerhand um", + "{C:attention}1{} Level für jeden", + "{C:attention}Neutronenstern{}", + "der in diesem Durchlauf", + "genutzt wurde", + "{C:inactive}(Aktuell {C:attention}#1#{C:inactive}){}", + }, + }, + c_cry_sunplanet = { + name = "Sol", + text = { + "{S:0.8}({S:0.8,V:1}lvl.#1#{S:0.8}){} Erhöhe Stärke von", + "{C:attention}Aufgestiegenen{} Händen um {X:gold,C:white}#2#{}", + "{C:inactive}(Aktuell {X:gold,C:white}X(#3#^asc){C:inactive})", + }, + }, + c_cry_Timantii = { + name = "Ruutu", + text = { + "({V:1}lvl.#4#{})({V:2}lvl.#5#{})({V:3}lvl.#6#{})", + "Aufwertung für", + "{C:attention}#1#{},", + "{C:attention}#2#{},", + "und {C:attention}#3#{}", + }, + }, c_cry_Klubi = { name = "Klubi", text = { @@ -2209,6 +3240,16 @@ return { "und {C:attention}#3#{}", }, }, + c_cry_Sydan = { + name = "Hertta", + text = { + "({V:1}lvl.#4#{})({V:2}lvl.#5#{})({V:3}lvl.#6#{})", + "Aufwertung für", + "{C:attention}#1#{},", + "{C:attention}#2#{},", + "und {C:attention}#3#{}", + }, + }, c_cry_Lapio = { name = "Lapio", text = { @@ -2229,28 +3270,8 @@ return { "und {C:attention}#3#{}", }, }, - c_cry_nstar = { - name = "Neutronenstern", - text = { - "Verbessere eine zufällige", - "Pokerhand um", - "{C:attention}1{} level für jeden", - "{C:attention}Neutronenstern{}", - "der in diesem Durchlauf", - "genutzt wurde", - "{C:inactive}(Momentan{C:attention} #1#{C:inactive}){}", - }, - }, - c_cry_planetlua = { - name = "Planet.lua", - text = { - "Chance von {C:green}#1# zu #2#{} jede", - "{C:legendary,E:1}Pokerhand{}", - "um {C:attention}1{} Level aufzuwerten", - }, - }, - c_cry_Sydan = { - name = "Sydan", + c_cry_voxel = { + name = "Voxel", text = { "({V:1}lvl.#4#{})({V:2}lvl.#5#{})({V:3}lvl.#6#{})", "Aufwertung für", @@ -2259,52 +3280,6 @@ return { "und {C:attention}#3#{}", }, }, - c_cry_Timantti = { - name = "Timantti", - text = { - "({V:1}lvl.#4#{})({V:2}lvl.#5#{})({V:3}lvl.#6#{})", - "Aufwertung für", - "{C:attention}#1#{},", - "{C:attention}#2#{},", - "und {C:attention}#3#{}", - }, - }, - c_cry_marsmoons = { - name = "Phobos & Deimos", - text = { - "{S:0.8}({S:0.8,V:1}lvl.#1#{S:0.8}){} Aufwertung für", - "{C:attention}#2#", - "{C:mult}+#3#{} Mult und", - "{C:chips}+#4#{} chips", - }, - }, - c_cry_void = { - name = "Leere", - text = { - "{S:0.8}({S:0.8,V:1}lvl.#1#{S:0.8}){} Aufwertung für", - "{C:attention}#2#", - "{C:mult}+#3#{} Mult und", - "{C:chips}+#4#{} chips", - }, - }, - c_cry_asteroidbelt = { - name = "Asteroidengürtel", - text = { - "{S:0.8}({S:0.8,V:1}lvl.#1#{S:0.8}){} Aufwertung für", - "{C:attention}#2#", - "{C:mult}+#3#{} Mult und", - "{C:chips}+#4#{} chips", - }, - }, - c_cry_universe = { - name = "Das Universum in seiner verfickten Gesamtheit.", - text = { - "{S:0.8}({S:0.8,V:1}lvl.#1#{S:0.8}){} Aufwertung für", - "{C:attention}#2#", - "{C:mult}+#3#{} Mult und", - "{C:chips}+#4#{} chips", - }, - }, }, Sleeve = { sleeve_cry_beige_sleeve = { @@ -2324,14 +3299,14 @@ return { sleeve_cry_beta_sleeve = { name = "Nostalgische Hülle", text = { - "{C:attention}Joker{} und {C:attention}Verbrauchgegenstände{}", + "{C:attention}Joker{} und {C:attention}Verbrauchsgegenstände{}", "Slots sind {C:attention}zusammengefasst", "{C:attention}Nostalgische{} Blinds ersetzen", "ihre neuen Versionen.", }, }, sleeve_cry_bountiful_sleeve = { - name = "Größzügige Hülle", + name = "Großzügige Hülle", text = { "Ziehe immer 5 Karten nach", "{C:attention}Gespielter Hand{} oder {C:attention}Abwurf{}", @@ -2345,12 +3320,12 @@ return { }, }, sleeve_cry_conveyor_sleeve = { - name = "Fließbandhülle", + name = "Fließband-Hülle", text = { "Joker können {C:attention}nicht{} bewegt werden", "Am Anfang der Runde,", - "{C:attention}dupliziere{} den rechtesten Joker", - "und {C:attention}zerstöre{} den linkesten Joker", + "{C:attention}dupliziere{} den Joker ganz rechts", + "und {C:attention}zerstöre{} den Joker ganz links", }, }, sleeve_cry_critical_sleeve = { @@ -2366,7 +3341,7 @@ return { text = { "Starte mit einem {C:cry_code,T:j_cry_CodeJoker}Code Joker{}", "und einem {C:cry_code,T:j_cry_copypaste}Copy/Paste{}", - "Nur {C:cry_code}Code Karten{} erscheinen im Shop", + "Im Shop erscheinen nur {C:cry_code}Code Karten", }, }, sleeve_cry_equilibrium_sleeve = { @@ -2429,10 +3404,10 @@ return { }, }, sleeve_cry_wormhole_sleeve = { - name = "Wurmlochhülle", + name = "Wurmloch-Hülle", text = { "Beginne mit einem {C:cry_exotic}Exotischen{C:attention} Joker", - "Joker sind {C:attention}20X{} warscheinlicher", + "Joker sind {C:attention}20X{} wahrscheinlicher", "{C:dark_edition}Negativ{} zu sein", "{C:attention}-2{} Joker-Slots", }, @@ -2441,12 +3416,41 @@ return { name = "Legendäre Hülle", text = { "Beginne mit einem {C:legendary}Legendären{C:legendary} Joker", - "Chance von {C:green}1 in 5{} einen weiteren zu erstellen", - "wenn Boss Blind besiegt wurde {C:inactive}(Muss Platz haben){}", + "Chance von {C:green}1 in 5{} einen Weiteren zu erstellen", + "wenn Boss Blind besiegt wurde", + "{C:inactive}(Muss Platz haben){}", + }, + }, + sleeve_cry_antimatter_sleeve = { + name = "Antimaterie-Hülle", + text = { + "Übernimmt die {C:attention}Effekte{}", + "und {C:attention}Spezialeffekte{}", + "aller Deckhüllen", + "{C:red}WIP", + }, + }, + sleeve_cry_antimatter_sleeve_balanced = { + name = "Antimaterie-Hülle", + text = { + "Übernimmt die {C:attention}Effekte{}", + "und {C:attention}Spezialeffekt{}", + "{C:attention}aller{} Deckhüllen", + "auf denen ein Durchlauf auf", + "{C:gold}Goldener Einsatz{} gewonnen wurde", + "{C:red}WIP", }, }, }, Spectral = { + c_cry_adversary = { + name = "Widersacher", + text = { + "{C:red}Alle{} deine {C:attention}Joker{} werden {C:dark_edition}Negativ{},", + "{C:red}alle{} {C:attention}Joker{} im Shop kosten", + "{C:red}doppelt{} für den Rest des Durchlaufs", + }, + }, c_cry_analog = { name = "Analog", text = { @@ -2455,6 +3459,22 @@ return { "alle anderen Joker, {C:attention}+#2#{} Ante", }, }, + c_cry_chambered = { + name = "Eingekammert", + text = { + "Erzeuge {C:attention}#1#{} {C:dark_edition}Negative{}", + "Kopie#1# eines {C:attention}zufälligen{}", + "Verbrauchsgegenstands in deinem Besitz", + "{C:inactive,s:0.8}Kopiert nicht Eingekammert{}", + }, + }, + c_cry_conduit = { + name = "Leitung", + text = { + "Tausche die {C:attention}Editionen{} von", + "{C:attention}2{} gewählten Spielkarten oder {C:attention}Joker{}", + }, + }, c_cry_gateway = { name = "Portal", text = { @@ -2467,7 +3487,7 @@ return { name = "Hammerspace", text = { "Füge einen zufälligen {C:attention}Verbrauchsgegenstand{}", - "als währen sie {C:dark_edition}Verstärkungen{}", + "als wären sie {C:dark_edition}Verstärkungen{}", "zu allen Karten in der Hand hinzu", }, }, @@ -2485,7 +3505,7 @@ return { text = { "Erstelle eine Karte", "{C:cry_code}deiner Wahl", - "{C:inactive,s:0.8}(Exotische Joker exkludiert)", + "{C:inactive,s:0.8}(Exotische Joker ausgenommen)", }, }, c_cry_replica = { @@ -2497,6 +3517,14 @@ return { "Karte in der Hand", }, }, + c_cry_ritual = { + name = "Ritual", + text = { + "Füge {C:dark_edition}Negativ{}, {C:dark_edition}Mosaik{},", + "oder {C:dark_edition}Astral{} zu {C:attention}#1#{}", + "gewählten Karte#1# in der Hand hinzu", + }, + }, c_cry_source = { name = "Quelle", text = { @@ -2520,6 +3548,14 @@ return { "bekomme {C:attention}2{} zufällige Gutscheine", }, }, + c_cry_meld = { + name = "Verschmelzen", + text = { + "Wähle einen {C:attention}Joker{} oder eine", + "{C:attention}Spielkarte{}, welche", + "{C:dark_edition}Doppelseitig{} wird", + }, + }, c_cry_typhoon = { name = "Taifun", text = { @@ -2538,6 +3574,14 @@ return { }, }, c_cry_white_hole = { + name = "Weißes Loch", + text = { + "Verbessere {C:legendary,E:1}meistgespielte{}", + "Pokerhand um {C:attention}4{}", + "{C:attention}Entferne{} alle anderen Handlevel", + }, + }, + c_cry_white_hole2 = { name = "Weißes Loch", text = { "{C:attention}Entferne{} alle Handlevel,", @@ -2547,6 +3591,7 @@ return { }, }, Stake = { + -- TODO translate colours... stake_cry_pink = { name = "Pinker Einsatz", colour = "Pink", --this is used for auto-generated sticker localization @@ -2557,7 +3602,7 @@ return { }, stake_cry_brown = { name = "Brauner Einsatz", - colour = "Brown", + colour = "Braun", text = { "Alle {C:attention}Sticker{} sind", "gegenseitig Kompatibel", @@ -2565,7 +3610,7 @@ return { }, stake_cry_yellow = { name = "Gelber Einsatz", - colour = "Yellow", + colour = "Gelb", text = { "{C:attention}Sticker{} können auf", "allen kaufbaren Gegenständen erscheinen", @@ -2575,7 +3620,7 @@ return { name = "Jade Einsatz", colour = "Jade", text = { - "Karten können mit {C:attention}Gesicht unten{} gezogen werden", + "Karten können mit {C:attention}Gesicht nach unten{} gezogen werden", }, }, stake_cry_cyan = { @@ -2588,30 +3633,30 @@ return { }, stake_cry_gray = { name = "Grauer Einsatz", - colour = "Gray", + colour = "Grau", text = { "Aktualisierungen erhöhen sich um {C:attention}$2{}", }, }, stake_cry_crimson = { name = "Karmesin Einsatz", - colour = "Crimson", + colour = "Karmesin", text = { "Gutscheine füllen sich auf allen {C:attention}geraden{} Antes auf", }, }, stake_cry_diamond = { name = "Diamant Einsatz", - colour = "Diamond", + colour = "Diamant", text = { - "Zum gewinnen must du Ante {C:attention}10{} besiegen", + "Zum Gewinnen must du Ante {C:attention}10{} besiegen", }, }, stake_cry_amber = { name = "Bernstein Einsatz", - colour = "Amber", + colour = "Bernstein", text = { - "{C:attention}-1{} Booster Packet Slots", + "{C:attention}-1{} Booster Paket Slots", }, }, stake_cry_bronze = { @@ -2631,7 +3676,7 @@ return { }, stake_cry_ruby = { name = "Rubin Einsatz", - colour = "Ruby", + colour = "Rubin", text = { "{C:attention}Big{} Blinds können", "{C:attention}Boss{} Blinds werden", @@ -2641,12 +3686,12 @@ return { name = "Glass Einsatz", colour = "Glass", text = { - "Karten können {C:attention}zerbrechen{} wenn sie gewertet werden", + "Karten können {C:attention}zerbrechen{} wenn gewertet", }, }, stake_cry_sapphire = { name = "Saphir Einsatz", - colour = "Sapphire", + colour = "Saphir", text = { "Verliere {C:attention}25%{} deines momentanen Geldes", "am Ende der Ante", @@ -2655,31 +3700,31 @@ return { }, stake_cry_emerald = { name = "Smaragd Einsatz", - colour = "Emerald", + colour = "Smaragd", text = { - "Karten, Packete und Gutscheine", - "können mit {C:attention}Gesicht unten{} sein", + "Karten, Pakete und Gutscheine", + "können mit {C:attention}Gesicht nach unten{} sein", "{s:0.8,C:inactive}(Nicht sichtbar bis gekauft){}", }, }, stake_cry_platinum = { name = "Platin Einsatz", - colour = "Platinum", + colour = "Platin", text = { "Small Blinds sind {C:attention}entfernt{}", }, }, stake_cry_twilight = { name = "Zwielichtiger Einsatz", - colour = "Twilight", + colour = "Zwielichtig", text = { "Karten können {C:attention}Banane{} sein", "{s:0.8,C:inactive}(Chance von 1 zu 10, dass die Karte am Ende der Runde zerstört wird){}", }, }, stake_cry_verdant = { - name = "Grassgrüner Einsatz", - colour = "Verdant", + name = "Grasgrüner Einsatz", + colour = "Grasgrüner", text = { "Benötigte Punktzahl skaliert", "schneller für jede {C:attention}Ante", @@ -2687,31 +3732,31 @@ return { }, stake_cry_ember = { name = "Glühender Einsatz", - colour = "Ember", + colour = "Glühend", text = { - "Alle Gegenstände geben beim verkaufen kein Geld", + "Alle Gegenstände geben beim Verkaufen kein Geld", }, }, stake_cry_dawn = { name = "Dämmernder Einsatz", - colour = "Dawn", + colour = "Dämmernd", text = { - "Tarot- und Geisterkarten beinflussen {C:attention}1", - "Karte weniger", + "Tarot- und Geister-Karten beeinflussen", + "{C:attention}1{} Karte weniger", "{s:0.8,C:inactive}(Minimal 1){}", }, }, stake_cry_horizon = { name = "Horizont Einsatz", - colour = "Horizon", + colour = "Horizont", text = { - "Wenn Blind asgewählt ist, füge eine", + "Wenn Blind ausgewählt ist, füge eine", "{C:attention}zufällige Karte{} zum Deck hinzu", }, }, stake_cry_blossom = { name = "Blühender Einsatz", - colour = "Blossom", + colour = "Blühend", text = { "{C:attention}Letzte{} Boss Blinds können nun", "in {C:attention}allen{} Antes auftauchen", @@ -2719,7 +3764,7 @@ return { }, stake_cry_azure = { name = "Azurblauer Einsatz", - colour = "Azure", + colour = "Azurblauer", text = { "Werte auf Jokern sind", "um {C:attention}20%{} reduziert", @@ -2727,7 +3772,7 @@ return { }, stake_cry_ascendant = { name = "Aufgestiegener Einsatz", - colour = "Ascendant", + colour = "Aufgestiegen", text = { "{C:attention}-1{} Shop Slots", }, @@ -2758,7 +3803,7 @@ return { }, }, tag_cry_better_voucher = { - name = "Golder Gutschein-Tag", + name = "Goldener Gutschein-Tag", text = { "Fügt einen Level {C:attention}#1#{} Gutschein", "zum Shop hinzu", @@ -2775,9 +3820,9 @@ return { tag_cry_booster = { name = "Booster-Tag", text = { - "Nächstes {C:cry_code}Booster Packet{} hat", + "Nächstes {C:cry_code}Booster Paket{} hat", "{C:attention}doppelt so viele{} Karten und", - "{C:attention}doppelt so viele{} Auswahlen", + "{C:attention}doppelt so viele{} Auswahlmöglichkeiten", }, }, tag_cry_bundle = { @@ -2789,13 +3834,16 @@ return { }, tag_cry_cat = { name = "Katzen-Tag", - text = { "Meow.", "{C:inactive}Level {C:dark_edition}#1#" }, + text = { + "Miau.", + "{C:inactive}Level {C:dark_edition}#1#", + }, }, tag_cry_console = { name = "Konsolen-Tag", text = { "Gibt ein kostenloses", - "{C:cry_code}Program Packet", + "{C:cry_code}Programm Paket", }, }, tag_cry_double_m = { @@ -2808,7 +3856,7 @@ return { tag_cry_empowered = { name = "Ermächtigter Tag", text = { - "Gibt ein kostenloses {C:spectral}Geisterpacket", + "Gibt ein kostenloses {C:spectral}Geister-Paket", "mit {C:legendary,E:1}Die Seele{} und {C:cry_exotic,E:1}Portal{}", }, }, @@ -2854,14 +3902,14 @@ return { name = "Vielfraß Tag", text = { "Shop hat einen Kostenlosen", - "{C:attention}Essen Joker", + "{C:attention}Essen-Joker", }, }, tag_cry_loss = { name = "Loss", text = { "Gibt ein Kostenloses", - "{C:cry_ascendant}Meme Packet", + "{C:cry_ascendant}Meme Paket", }, }, tag_cry_m = { @@ -2873,12 +3921,12 @@ return { }, }, tag_cry_memory = { - name = "Erinnerungs Tag", + name = "Erinnerungs-Tag", text = { "Erstelle {C:attention}#1#{} Kopien des", - "als letztes genutzen {C:attention}Tag{}", + "als letztes genutzten {C:attention}Tag{}", "in diesem Durchlauf", - "{s:0.8,C:inactive}Kopierende Tags exkludiert", + "{s:0.8,C:inactive}Kopierende Tags ausgenommen", "{s:0.8,C:inactive}Momentan: {s:0.8,C:attention}#2#", }, }, @@ -2903,7 +3951,7 @@ return { text = { "Gibt {C:attention}#1#{} Kopien des", "als nächstes erhaltenen {C:attention}Tags", - "{s:0.8,C:inactive}Kopierende Tags exkludiert", + "{s:0.8,C:inactive}Kopierende Tags ausgeschlossen", }, }, tag_cry_quintuple = { @@ -2911,7 +3959,7 @@ return { text = { "Gibt {C:attention}#1#{} Kopien des", "als nächstes erhaltenen {C:attention}Tags", - "{s:0.8,C:inactive}Kopierende Tags exkludiert", + "{s:0.8,C:inactive}Kopierende Tags ausgeschlossen", }, }, tag_cry_rework = { @@ -2940,7 +3988,31 @@ return { text = { "Gibt {C:attention}#1#{} Kopien des", "als nächstes erhaltenen {C:attention}Tags", - "{s:0.8,C:inactive}Kopierende Tags exkludiert", + "{s:0.8,C:inactive}Kopierende Tags ausgenommen", + }, + }, + tag_cry_clone = { + name = "Klon-Tag", + text = { + "Gegenstände im Shop kosten {C:attention}X#1#{}", + "so viel, Erhalte eine {C:attention}Kopie{}", + "der als nächstes gekauften Karte", + }, + }, + tag_cry_lens = { + name = "Linsen-Tag", + text = { + "Füge {C:dark_edition}Negativ{}", + "zu {C:attention}#1#{} zufälligen", + "Verbrauchsgegen#1# hinzu", + }, + }, + tag_cry_palette_cleanser = { --beautiful phrase that unfortunately doesnt have a german equivalent :( + name = "Reinigungs-Tag", + text = { + "Entfernt einen {C:attention}zufälligen{}", + "Sticker von einem {C:attention}zufälligen{}", + "Joker oder Spielkarte", }, }, }, @@ -2954,28 +4026,34 @@ return { }, }, c_cry_eclipse = { - name = "Die Finsterniss", + name = "Die Finsternis", text = { "Verstärkt {C:attention}#1#{} gewählte Karte", "in eine {C:attention}Echo Karte", }, }, - c_cry_meld = { - name = "Verschmelzen", + c_cry_instability = { + name = "Instabilität", text = { - "Wähle einen {C:attention}Joker{} oder eine", - "{C:attention}Spielkarte{} welche", - "{C:dark_edition}Doppelseitig{} wird", + "Verstärkt {C:attention}#1#{} gewählte Karte#1#", + "zu {C:attention}Abstrakte#1# Karte#1#", }, }, c_cry_theblessing = { name = "Der Segen", text = { "Erstellt {C:attention}1{}", - "zufälligen {C:attention}Verbrauchsgegenstand{}", + "zufällig#1# {C:attention}Verbrauchsgegen#1#{}", "{C:inactive}(Muss Platz haben){}", }, }, + c_cry_seraph = { + name = "Der Seraph", + text = { + "Verstärkt {C:attention}#1#{} gewählte Karte#1#", + "zu {C:attention}Licht-Karten", + }, + }, }, Voucher = { v_cry_asteroglyph = { @@ -2983,12 +4061,19 @@ return { text = { "Setzt Ante zu {C:attention}#1#{}", }, + unlock = { + "Erreiche Ante {C:attention}36", + }, }, v_cry_blankcanvas = { - name = "Lehre Leinwand", + name = "Leere Leinwand", text = { "{C:attention}+#1#{} Handgröße", }, + unlock = { + "Reduziere deine {C:attention}Handgröße", + "auf {C:attention}0", + }, }, v_cry_clone_machine = { name = "Klonmaschine", @@ -3001,9 +4086,8 @@ return { v_cry_command_prompt = { name = "Eingabeaufforderung", text = { - "{C:cry_code}Code{} Karten", - "können im", - "{C:attention}shop{} auftauchen", + "{C:cry_code}Code{} Karten können", + "{im C:attention}Shop{} auftauchen", }, }, v_cry_copies = { @@ -3021,19 +4105,44 @@ return { "erscheinen mit", "einer {C:dark_edition}Edition{}", }, + unlock = { + "Entdecke", + "alle {C:attention}Editionen", + }, }, + -- RESERVATION FOR CRYSTAL BALL T3 + -- RESERVATION FOR TELESCOPE T3 + -- v_cry_scope = { + -- name = "Galaktischer Horizont", + -- text = { + -- "Erzeuge die {C:planet}Planeten{}-", + -- "Karte für gespielte", + -- "{C:attention}Pokerhand{}", + -- "{C:inactive}(Muss Platz haben){}", + -- }, + -- unlock = { + -- "Nutze {C:attention}50{} {C:planet}Planeten{}-", + -- "Karten aus", + -- "{C:attention}Booster Paketen{}", + -- "in einem Durchlauf", + -- }, + -- }, v_cry_dexterity = { name = "Geschicklichkeit", text = { - "Bekomme permanent", - "{C:blue}+#1#{} Hand/Hände", + "Bekomme dauerhaft", + "{C:blue}+#1#{} #1#", "pro Runde", }, + unlock = { + "Spiele insgesamt {C:attention}5000{}", + "{C:attention}Spielkarten{}", + }, }, v_cry_double_down = { name = "Double Down", text = { - "Nach jeder runde,", + "Nach jeder Runde,", "{X:dark_edition,C:white} X1.5 {} zu allen Werten", "auf der Rückseite von", "{C:dark_edition}Doppelseitigen{} Karten", @@ -3044,28 +4153,36 @@ return { text = { "{C:attention}Verschmelzen{} kann im", "Shop und in", - "Arkana Packeten auftauchen", + "Arkana-Paketen auftauchen", }, }, v_cry_double_vision = { name = "Doppelsicht", text = { - "{C:dark_edition}Doppelseitige{} Karten erscheinen", - "{C:attention}4X{} öfter", + "{C:dark_edition}Doppelseitige{} Karten", + "erscheinen {C:attention}4X{} öfter", }, }, v_cry_fabric = { - name = "Universal Fabric", + name = "Universalgewebe", text = { "{C:dark_edition}+#1#{} Joker Slot(s)", }, + unlock = { + "Löse {C:dark_edition}Antimaterie", + "{C:attention}10{} Mal ein", + }, }, v_cry_massproduct = { name = "Massenproduktion", text = { - "Alle Karten und Parkete", + "Alle Karten und Pakete", "im Shop kosten {C:attention}$1{}", }, + unlock = { + "Löse {C:attention}25 Gutscheine", + "in einem Durchlauf ein", + }, }, v_cry_moneybean = { name = "Geld Bohnenranke", @@ -3074,24 +4191,37 @@ return { "für Zinsen", "zu {C:money}$#1#{}", }, + unlock = { + "Maximiere die", + "{C:attention}Zinseinnahmen{}", + "für den {C:attention}gesamten Durchlauf", + }, }, v_cry_overstock_multi = { name = "Multibestand", text = { - "{C:attention}+#1#{} Karten Slot(s) und", - "{C:attention}+#1#{} Booster Packet Slot(s)", + "{C:attention}+#1#{} Karten Slot#1# und", + "{C:attention}+#1#{} Booster Paket Slot#1#", "im Shop", }, + unlock = { + "Gib {C:attention}1000$", + "im Shop aus", + "in einem Durchlauf", + }, }, v_cry_pacclimator = { name = "Planetenakklimatisierung", text = { "{C:planet}Planet{} Karten erscheinen", - "{C:attention}X#1#{} öfter", - "im Shop.", + "{C:attention}X#1#{} öfter im Shop.", "Alle zukünftigen {C:planet}Planeten{}", "Karten sind {C:green}kostenlos{}", }, + unlock = { + "Kaufe insgesamt {C:attention}100{}", + "{C:planet}Planeten{}-Karten im Shop", + }, }, v_cry_pairamount_plus = { name = "Pairamount Plus", @@ -3119,7 +4249,7 @@ return { v_cry_repair_man = { name = "Reparaturmann", text = { - "{C:attention}Löse{} alle M Joker {C:attention}erneut aus", + "{C:attention}Löse{} alle M Joker {C:attention}erneut aus,", "wenn gespielte Hand ein {C:attention}Paar{} enthält", }, }, @@ -3129,12 +4259,17 @@ return { "Alle Aktualisierungen", "kosten {C:attention}$2{}", }, + unlock = { + "{C:attention}Aktualisiere{} den Shop", + "insgesamt {C:attention}250 Mal{}", + "in einem Durchlauf", + }, }, v_cry_satellite_uplink = { - name = "Satelitenverbindung", + name = "Satellitenverbindung", text = { "{C:cry_code}Code{} Karten können", - "in allen {C:attention}Himmelpacketen{}", + "in allen {C:attention}Himmel{}-Paketen", "erscheinen", }, }, @@ -3151,11 +4286,14 @@ return { name = "Tarotakklimatisierung", text = { "{C:tarot}Tarot{} Karten erscheinen", - "{C:attention}X#1#{} öfter", - "im Shop.", + "{C:attention}X#1#{} öfter im Shop.", "Alle zukünftigen {C:tarot}Tarot{}", "Karten sind {C:green}kostenlos{}", }, + unlock = { + "Kaufe insgesamt {C:attention}100{}", + "{C:tarot}Tarot{}-Karten im Shop", + }, }, v_cry_tag_printer = { name = "Tag Drucker", @@ -3168,36 +4306,75 @@ return { v_cry_threers = { name = "Die 3 Rs", text = { - "Bekomme permanent", - "{C:red}+#1#{} Abwurf/Abwürfe", + "Bekomme dauerhaft", + "{C:red}+#1#{} #1#", "pro Runde", }, + unlock = { + "Wirf insgesamt {C:attention}5000{}", + "{C:attention}Spielkarten{} ab", + }, }, v_cry_stickyhand = { name = "Klebrige Hand", text = { - "{C:attention}+#1#{} Karten auswahl limit", + "{C:attention}+#1#{} Karte#1# Auswahllimit", }, }, v_cry_grapplinghook = { name = "Enterhaken", text = { - "{C:attention}+#1#{} Karten auswahl limit", - "{C:inactive,s:0.7}NOTE: Hiermit kannst du mehr{}", + "{C:attention}+#1#{} Karten Auswahllimit", + "{C:inactive,s:0.7}Hiermit kannst du viel mehr{}", "{C:inactive,s:0.7}machen als du denkst{}", }, }, v_cry_hyperspacetether = { name = "Hyperraum-Halteleine", text = { - "{C:attention}+#1#{} Karten", - "auswahl limit", - "{C:inactive,s:0.7}NOTE: Bekommt später noch{}", - "{C:inactive,s:0.7}mehr funktionen{}", + "{C:attention}+#1#{} Karte#1# Auswahllimit", + "Alle gewählten Karten tragen zu", + "{C:attention}Aufgestiegenen Händen{} bei", }, }, }, Other = { + alt_wheel_of_fortune = { + name = "Das Rad des Schicksals", + text = { + "{C:green}#1#-zu-#2#{}-Chance, die", + "{C:dark_edition}Foil{}, {C:dark_edition}holographische{} oder", + "{C:dark_edition}Polychrom{}-Edition", + "zu einem zufälligen {C:attention}Joker{} hinzuzufügen", + }, + }, + disabled = { + name = "Deaktiviert", + text = { + "Erscheint nicht mehr", + "in Durchläufen", + }, + }, + disabled_card_dependency = { + name = "Deaktiviert", + text = { + "Benötigt {C:attention}#1#", + }, + }, + disabled_mod_dependency = { + name = "Deaktiviert", + text = { + "Benötigt Mod:", + "{C:attention}#1#", + }, + }, + disabled_mod_conflict = { + name = "Deaktiviert", + text = { + "Nicht kompatibel mit Mod:", + "{C:attention}#1#", + }, + }, banana = { name = "Banane", text = { @@ -3205,20 +4382,36 @@ return { "zerstört zu werden", }, }, + cry_absolute = { + name = "Absolut", + text = { + "Kann nicht verkauft", + "oder zerstört werden", + "{C:attention}Nicht entfernbar{}", + }, + }, cry_rigged = { name = "Manipuliert", text = { - "Alle {C:cry_code}aufgelisteten{} Warscheinlichkeiten", + "Alle {C:cry_code}gelisteten{} Wahrscheinlichkeiten", "sind {C:cry_code}garantiert", }, }, cry_hooked = { - name = "Verhackt", + name = "Verhakt", text = { "Wenn dieser Joker {C:cry_code}ausgelöst{} wird,", "löse {C:cry_code}#1#{} aus", }, }, + cry_global_sticker = { + name = "Global", + text = { + "Ziehe diese Karte", + "{C:cry_code}vor anderen Karten{},", + "falls möglich", + }, + }, cry_flickering = { name = "Flackernd", text = { @@ -3234,6 +4427,21 @@ return { "{C:attention}#1#{} Auslösungen", }, }, + cry_function_sticker = { + name = "Function://", + text = { + "Erzeugt {C:cry_code}#1#{}", + "bei Nutzung", + }, + }, + cry_function_sticker_desc = { --for function:// card + name = "Function://", + text = { + "Erzeugt den nächsten", + "{C:cry_code}Function://{} Verbrauchsgegenstand", + "{C:inactive}Aktuell #1#, #2# und #3#{}", + }, + }, cry_possessed = { name = "Besessen", text = { @@ -3244,29 +4452,29 @@ return { }, --todo? add candy jokers to list food_jokers = { - name = "Essen Joker", + name = "Essen-Joker", text = { "{s:0.8}Gros Michel, Ei, Eiscreme, Cavendish,", "{s:0.8}Schwarze Bohne, Diät-Cola, Popcorn, Ramen,", - "{s:0.8}Selters, Saure Gurke, Chilischote, Karamel,", + "{s:0.8}Selters, Saure Gurke, Chilischote, Karamell,", "{s:0.8}Nostalgische Süßigkeit, Fast Food M, etc.", }, }, - v_cry_choco0 = { - name = "", + ev_cry_choco0 = { + name = "Mögliche Events", text = { - "Details eines aktiven", - "{C:cry_ascendant,E:1}Events{} werden hier erscheinen", + "{T:ev_cry_choco1}1{} {T:ev_cry_choco2}2{} {T:ev_cry_choco3}3{} {T:ev_cry_choco4}4{} {T:ev_cry_choco5}5{}", + "{T:ev_cry_choco6}6{} {T:ev_cry_choco7}7{} {T:ev_cry_choco8}8{} {T:ev_cry_choco9}9{} {T:ev_cry_choco10}10{}", }, }, ev_cry_choco1 = { - name = "1: Bessetzung", + name = "1: Besetzung", text = { "{C:attention}Joker{} und Spielkarten haben eine", "Chance von {C:green}1 zu 3{} Flackernd zu bekommen", "Erstelle einen {C:attention}Geist", "{C:inactive,s:0.7}Du wurdest von einem Geist besessen und dein", - "{C:inactive,s:0.7}Bewustsein flackert ein und aus.", + "{C:inactive,s:0.7}Bewusstsein flackert ein und aus.", }, }, ev_cry_choco2 = { @@ -3283,11 +4491,11 @@ return { name = "3: Hexengebräu", text = { "Erstelle 3 {C:attention}Tränke", - "Benutze einen am Ende der {C:attention}Small Blind{},", + "Benutze Einen am Ende der {C:attention}Small Blind{},", "oder {C:attention}alle{} werden diese {C:attention}Ante{} angewendet", - "{C:inactive,s:0.7}Du wurderst von einer Hexe entführt!", + "{C:inactive,s:0.7}Du wurdest von einer Hexe entführt!", "{C:inactive,s:0.7}Sie bietet dir drei Tränke an und beobachtet dich genau.", - "{C:inactive,s:0.7}Wähle einen oder sie macht die Entscheidung für dich.", + "{C:inactive,s:0.7}Wähle einen oder sie trifft die Entscheidung für dich.", }, }, ev_cry_choco4 = { @@ -3295,7 +4503,7 @@ return { text = { "Gespielte Karten haben eine Chance von {C:green}1 zu 4{}", "sich in eine zufällige {C:club}Kreuz{} Bildkarte zu verwandeln", - "Dividiere {C:attention}Mult{} durch die Ankahl gespielter Bildkarten", + "Dividiere {C:attention}Mult{} durch die Anzahl gespielter Bildkarten", "{C:inactive,s:0.7}Selbst ein Mann reines Herzes", "{C:inactive,s:0.7}der Nachts immer betet...", }, @@ -3314,9 +4522,9 @@ return { name = "6: Bitte nimm eins", text = { "Am {C:attention}Ende der Runde{}, öffne ein", - "zufälliges {C:attention}Booster{} Packet", + "zufälliges {C:attention}Booster{} Paket", "{C:inactive,s:0.7}Als du die Straße hinunter läufst, siehst du eine", - "{C:inactive,s:0.7}Box mit vielen Booster Packeten. Warum nicht eins nehmen?", + "{C:inactive,s:0.7}Box mit vielen Booster Paketen. Warum nicht eins nehmen?", }, }, ev_cry_choco7 = { @@ -3326,35 +4534,35 @@ return { "Shops haben jede Runde ein {C:attention}Süßes oder Saures{}", "{C:cry_candy}Süßigkeiten{} geben {C:money}$3{} wenn erhalten", "{C:inactive,s:0.7}Die ganze Nachbarschaft ist gruselig dekoriert,", - "{C:inactive,s:0.7}komm und hab Spaß in der Festlichen Atmosphäre!", + "{C:inactive,s:0.7}komm und hab Spaß in der festlichen Atmosphäre!", }, }, ev_cry_choco8 = { - name = "8: Candy Rain", + name = "8: Süßigkeitenregen", text = { - "When {C:attention}Blind{} defeated, obtain 1 {C:cry_candy}Candy{}", - "per hand remaining; Obtain a {C:attention}Food Joker{}", - "when a {C:cry_candy}Candy{} is generated", - "{C:inactive,s:0.7}Candies rain from the sky! Quick,", - "{C:inactive,s:0.7,E:1}grab as much as you can!", + "Wenn {C:attention}Blind{} besiegt wird, erhalte 1 {C:cry_candy}Candy{}", + "pro übriger Hand; Erhalte einen {C:attention}Essen-Joker{}", + "wenn eine {C:cry_candy}Süßigkeit{} erzeugt wird", + "{C:inactive,s:0.7}Süßigkeiten regnen vom Himmel! Schnell,", + "{C:inactive,s:0.7,E:1}sammel so viel du kannst!", }, }, ev_cry_choco9 = { - name = "9: Süßigkeitenregen", + name = "9: Gespenstische Reichtümer", text = { "Erhalte {C:money}$20", "Alles verdiente {C:money}Geld{} ist {C:attention}verdoppelt", - "{C:inactive,s:0.7}Der Geist eines lang verstörbenen Verwanten", + "{C:inactive,s:0.7}Der Geist eines lang verstörbenen Verwandten", "{C:inactive,s:0.7}besucht dich in der Mitte der Nacht!", "{C:inactive,s:0.7}Ohne ein Wort gibt er dir ein einen Sack voll Geld,", - "{C:inactive,s:0.7}gibt dir ein freundliches Lächeln, und winkt als er wieder verschwindet.", + "{C:inactive,s:0.7}gibt dir ein freundliches Lächeln, und winkt, als er wieder verschwindet.", }, }, ev_cry_choco10 = { name = "10: Verehrte Antiquität", text = { "Ein {C:legendary}Legendärer{} {C:attention}Joker{} erscheint", - "in dem {C:attention}Gutschein{} slot für {C:money}$50", + "in dem {C:attention}Gutschein{} Slot für {C:money}$50", "Nur kaufbar als {C:attention}letzter{} Gegenstand im Shop", "{C:inactive,s:0.7}Du hast die Aufmerksamkeit des Geistes eines Relikts,", "{C:inactive,s:0.7}bekommen, aber er wird nicht leicht zu bändigen sein.", @@ -3363,7 +4571,7 @@ return { cry_https_disabled = { name = "M", text = { - "{C:attention,s:0.7}Updating{s:0.7} ist von den standard ({C:attention,s:0.7}HTTPS Modul{s:0.7} deaktiviert)", + "{C:attention,s:0.7}Updating{s:0.7} ist von den Standard ({C:attention,s:0.7}HTTPS Modul{s:0.7} deaktiviert)", }, }, --i am so sorry for this @@ -3371,35 +4579,35 @@ return { cry_eternal_booster = { name = "Ewig", text = { - "Alle Karten im Packet", + "Alle Karten im Paket", "sind {C:attention}Ewig{}", }, }, cry_perishable_booster = { name = "Verderblich", text = { - "Alle Karten im Packet", + "Alle Karten im Paket", "sind {C:attention}Verderblich{}", }, }, cry_rental_booster = { name = "Gemietet", text = { - "Alle Karten im Packet", + "Alle Karten im Paket", "sind {C:attention}Gemietet{}", }, }, cry_pinned_booster = { name = "Angeheftet", text = { - "Alle Karten im Packet", + "Alle Karten im Paket", "sind {C:attention}Angeheftet{}", }, }, cry_banana_booster = { name = "Banane", text = { - "Alle Karten im Packet", + "Alle Karten im Paket", "sind {C:attention}Banane{}", }, }, @@ -3455,72 +4663,81 @@ return { cry_pinned_consumeable = { name = "Angeheftet", text = { - "Du kannst keine", - "nicht-{C:attention}Angeheftetn{} Verbrauchsgegenstände nutzen", + "{C:inactive}Macht nichts...", + "{C:inactive}erstmal", }, }, cry_banana_consumeable = { - name = "Banana", + name = "Banane", text = { - "Chance von {C:green}#1# zu #2#{} beim nutzen", - "nichts zu tuhen", + "Chance von {C:green}#1# zu #2#{} bei Benutzung", + "nichts zu tun", }, }, p_cry_code_normal_1 = { - name = "Program Packet", + name = "Programm Paket", text = { "Wähle {C:attention}#1#{} aus bis zu", - "{C:attention}#2#{C:cry_code} Code{} Karten", + "{C:attention}#2#{C:cry_code} Code{}-Karte#2#", }, }, p_cry_code_normal_2 = { - name = "Program Packet", + name = "Programm Paket", text = { "Wähle {C:attention}#1#{} aus bis zu", - "{C:attention}#2#{C:cry_code} Code{} Karten", + "{C:attention}#2#{C:cry_code} Code{}-Karte#2#", }, }, p_cry_code_jumbo_1 = { - name = "Jumbo Program Packet", + name = "Jumbo Programm Paket", text = { "Wähle {C:attention}#1#{} aus bis zu", - "{C:attention}#2#{C:cry_code} Code{} Karten", + "{C:attention}#2#{C:cry_code} Code{}-Karte#2#", }, }, p_cry_code_mega_1 = { - name = "Mega Program Packet", + name = "Mega Programm Paket", text = { "Wähle {C:attention}#1#{} aus bis zu", - "{C:attention}#2#{C:cry_code} Code{} Karten", + "{C:attention}#2#{C:cry_code} Code{}-Karte#2#", }, }, p_cry_empowered = { - name = "Geister Packet [Ermächtigter Tag]", + name = "Ermächtigtes Paket", text = { "Wähle {C:attention}#1#{} von bis zu", - "{C:attention}#2#{C:spectral} Geister{} Karten", - "{s:0.8,C:inactive}(Erstellt von Ermächtigten Tag)", + "{C:attention}#2#{C:spectral} Geister{}-Karte#2#", + "{s:0.8,C:inactive}(Erstellt von Ermächtigter Tag)", }, }, p_cry_meme_1 = { - name = "Meme Packet", + name = "Meme Paket", text = { "Wähle {C:attention}#1#{} von bis zu", - "{C:attention}#2# Meme Jokern{}", + "{C:attention}#2# Meme Joker#2#{}", }, }, p_cry_meme_two = { - name = "Meme Packet", + name = "Meme Paket", text = { "Wähle {C:attention}#1#{} von bis zu", - "{C:attention}#2# Meme Jokern{}", + "{C:attention}#2# Meme Joker#2#{}", }, }, p_cry_meme_three = { - name = "Meme Packet", + name = "Meme Paket", text = { "Wähle {C:attention}#1#{} von bis zu", - "{C:attention}#2# Meme Jokern{}", + "{C:attention}#2# Meme Joker#2#{}", + }, + }, + p_cry_baneful_1 = { + name = "Unheilvolles Clownspaket", + text = { + "Wähle {C:attention}#1#{} von", + "bis zu {C:attention}#2# {X:cry_cursed,C:white}Verfluchten{} Joker#2#{}", + "{C:attention}Überspringen{} {C:red}verbannt{}", + "den Joker {C:attention}ganz rechts{} im Besitz", }, }, undiscovered_code = { @@ -3528,8 +4745,8 @@ return { text = { "Kaufe oder nutze", "diese Karte in einem", - "Durchlauf ohne Code", - "um zu lernen was es tuht", + "Durchlauf ohne Seed", + "um zu lernen, was sie tut", }, }, undiscovered_unique = { @@ -3537,15 +4754,15 @@ return { text = { "Kaufe oder nutze", "diese Karte in einem", - "Durchlauf ohne Code", - "um zu lernen was es tuht", + "Durchlauf ohne Seed", + "um zu lernen, was sie tut", }, }, cry_green_seal = { - name = "Grünen Siegel", + name = "Grünes Siegel", text = { "Erstellt eine {C:cry_code}Code{} Karte", - "wenn gespielt aber nicht gewertet", + "wenn gespielt, aber nicht gewertet", "{C:inactive}(Muss Platz haben)", }, }, @@ -3558,14 +4775,26 @@ return { "{C:red}zerstöre{} diese Karte", }, }, - Unique = { - c_cry_potion = { - name = "Trank", - text = { - "Gibt einen unbekannten", - "{C:attention}Fluch{} wenn genutz", - "{C:inactive,s:0.7}Von Schokoladenwürfel erhalten", - }, + blurred_sdm0 = { + name = "a", + text = { + '{C:inactive,s:0.8}"Ich hasse diese Karte" - SDM_0, 2024{}', + }, + }, + cry_multiuse = { + name = "m", + text = { + "{C:inactive}Mehrmals: ({C:cry_code}#1#{C:inactive} übrig)", + }, + }, + }, + Unique = { + c_cry_potion = { + name = "Trank", + text = { + "Gibt einen unbekannten", + "{C:attention}Fluch{} wenn genutzt", + "{C:inactive,s:0.7}Von Schokoladenwürfel erhalten", }, }, }, @@ -3574,27 +4803,27 @@ return { tutorial = { cry_intro_1 = { "Hallo, ich bin {C:attention}Joseph J. Joker{}!", - "Wilkommen zu {C:cry_exotic,E:1}Cryptid{}!", + "Willkommen zu {C:cry_exotic,E:1}Cryptid{}!", }, cry_intro_2 = { - "Sieht aus als hättest du auf diesem Profil", + "Sieht aus, als hättest du auf diesem Profil", "noch nie {C:cry_exotic,E:1}Cryptid{} genutzt.", "Lass mich dir zeigen wie es funktioniert!", }, cry_intro_3 = { - "*wächst hände*", + "*wächst Hände*", }, cry_intro_4 = { - "Es ist schwer dieses Mod in nur", - "einigen Sätzen zu beschreiben, aber was ich sagen kann", - "ist, dass es jetzt {C:cry_exotic,E:1}wild{} wird!", - "Das ist nicht das selbe {C:attention}Joker Poker{} das du kennst...", + "Es ist schwer, diesen Mod in nur", + "einigen Sätzen zu beschreiben, aber ich kann sagen,", + "dass es jetzt {C:cry_exotic,E:1}wild{} wird!", + "Das ist nicht dasselbe {C:attention}Joker Poker{} das du kennst...", }, cry_intro_5 = { "Wie du von diesen {C:cry_ascendant}Gamesets{}", "sehen kannst, mag ich den Buchstaben {C:attention}M{}.", - "Wähle ein Gameset das ich erklähren soll...", - "{s:0.8}Achtung: An Gamesets wird immernoch gearbeitet.", + "Wähle ein Gameset, das ich erklären soll...", + "{s:0.8}Achtung: An Gamesets wird immer noch gearbeitet.", "{s:0.8}Erwarte regelmäßige Änderungen!", }, cry_modest_1 = { @@ -3607,17 +4836,17 @@ return { "was du in der nächsten Runde findest...", }, cry_mainline_1 = { - "Willst du das Spiel gerne {E:1,C:attention}zerstören{}? Gute Nachichten!", - "Du kannst es machen ohne komplett durchzudrehen.", + "Willst du das Spiel gerne {E:1,C:attention}zerstören{}? Gute Nachrichten!", + "Du kannst das tun, ohne komplett durchzudrehen.", }, cry_mainline_2 = { - "Hier ist es immernoch verrückt, aber du hast die", - "Chance das {C:cry_ascendant}Fortschrittsystem{} zu", - "erfahren. Aber werde nicht zu gemütlich...", + "Hier ist es immer noch verrückt, aber du hast die", + "Chance, das {C:cry_ascendant}Aufstiegssystem{} zu", + "erfahren. Aber mach es dir nicht zu bequem...", }, cry_mainline_3 = { "Weil du stärker sein wirst,", - "habe ich einige {E:1,C:dark_edition}Bosse{} die", + "habe ich einige {E:1,C:dark_edition}Bosse{}, die", "dich deine Wahl bereuen lassen könnten.", }, cry_madness_1 = { @@ -3627,40 +4856,54 @@ return { }, cry_madness_2 = { "Ich habe viele schlaflose Wochen, {C:green}Mountain Dew{}-angetriebene", - "Nächte verbracht um sicherzustellen, dass dieses Gameset für dich", + "Nächte verbracht, um sicherzustellen, dass dieses Gameset für dich", "{C:cry_ascendant}PERFEKT BALANCIERT{} ist!", }, cry_madness_3 = { - "Du beginnst mit allem freigeschaltet, also", + "Du beginnst mit Allem freigeschaltet, also", "kannst du die {C:red,E:1}volle Macht{} von Cryptid sofort nutzen!", "Sei nur vorsichtig, dass das Spiel nicht {C:attention,E:1}abstürzt{},", - "da das Warscheinlich passiert bevor du verlierst...", + "da das wahrscheinlich passiert, bevor du verlierst...", }, }, poker_hands = { ["cry_Bulwark"] = "Bollwerk", - ["cry_Clusterfuck"] = "Clusterfuck", + ["cry_Clusterfuck"] = Cryptid_config.family_mode and "Cluster" or "Clusterfuck", ["cry_UltPair"] = "Ultimatives Paar", - ["cry_WholeDeck"] = "Das ganze verfickte Deck", + ["cry_WholeDeck"] = Cryptid_config.family_mode and "Das Ganze Deck" or "Das Ganze Verfickte Deck", + ["cry-Cluster Bulwark"] = "Clusterwark", + ["cry_None"] = "Nichts", + + ["cry_Declare0"] = { "Wird immer als Straight gewertet" }, + ["cry_Declare1"] = { "Wird immer als Flush gewertet" }, + ["cry_Declare2"] = { "Wird immer als Full House gewertet" }, + + ["cry_Declare0_suitless"] = { "Wird immer als Straight gewertet", "Hand benötigt keine bestimmten Farben" }, + ["cry_Declare1_suitless"] = { "Wird immer als Flush gewertet", "Hand benötigt keine bestimmten Farben" }, + ["cry_Declare2_suitless"] = { + "Wird immer als Full House gewertet", + "Hand benötigt keine bestimmten Farben", + }, }, poker_hand_descriptions = { ["cry_Bulwark"] = { - "5 ranglose, farbenlose Karten zusammen gespielt", + "5 ranglose, farblose Karten", }, ["cry_Clusterfuck"] = { - "Mindestens 8 Karten, welche nicht", - "Paar, Flush oder Straße enthalten", + "Mindestens 8 Karten, welche kein", + "Paar, Flush oder Straight enthalten", }, ["cry_UltPair"] = { - "Zwei zwei Paare, bei denen jedes", + "Zwei Zwei Paare, bei denen Jedes", "von ihnen von einer Farbe ist,", - "was insgesammt 2 Farben ergibt.", + "was insgesamt 2 Farben ergibt.", }, ["cry_WholeDeck"] = { "Eine Hand, die jede Karte in", - "in einem 52-Karten Deck enthält.", + "einem 52-Karten Deck enthält.", "Bist du verrückt?", }, + ["cry_None"] = { "Eine Hand bestehend aus 0 Karten" }, }, achievement_names = { ach_cry_ace_in_crash = "Pocket ACE", @@ -3682,34 +4925,50 @@ return { ach_cry_traffic_jam = "Stau", ach_cry_ult_full_skip = "Ultimativer Full Skip", ach_cry_used_crash = "Wir haben dich gewarnt", - ach_cry_what_have_you_done = "WAS HAST DU GETAHN?!", + ach_cry_what_have_you_done = "WAS HAST DU GETAN?!", + ach_cry_pin = "Stecknadel der Schande", + ach_cry_technically_positive = "Technisch gesehen Positiv", + ach_cry_youre_fucking_kidding = Cryptid_config.family_mode and "Ist das dein Ernst?" + or "Ist das dein verfickter Ernst?", + ach_cry_stoned = "Stoned", + ach_cry_fucked = Cryptid_config.family_mode and "Clustered" or "Fucked", + ach_cry_despaired = "Verzweifelt", + ach_cry_decked = "Decked", }, achievement_descriptions = { - ach_cry_ace_in_crash = 'check_for_unlock({type = "ace_in_crash"})', - ach_cry_blurred_blurred_joker = "Bekomme einen verschwommen Verschwommen Joker", + ach_cry_ace_in_crash = 'check_for_unlock({type = "ace_in_crash"})', --? + ach_cry_blurred_blurred_joker = "Bekomme einen Verschwommen Verschwommener Joker", ach_cry_bullet_hell = "Habe 15 AP Joker", ach_cry_break_infinity = "Bekomme 1.79e308 Chips in einer einzigen Hand", ach_cry_cryptid_the_cryptid = "Benutze Cryptid auf Cryptid", ach_cry_exodia = "Habe 5 Exotische Joker", ach_cry_freak_house = "Spiele ein Flush House aus 6 und 9 von Herz während du Nice hast", ach_cry_googol_play_pass = "Manipuliere eine Googol Play Karte", - ach_cry_haxxor = "Benutze einen cheat code", + ach_cry_haxxor = "Benutze einen Cheat Code", ach_cry_home_realtor = "Aktiviere Fröhliches Haus vor Ante 8 (ohne DoE/Antimaterie)", - ach_cry_jokes_on_you = "Löse den Effect von dem Witz in Ante 1 aus und gewinne den Durchlauf trotzdem.", + ach_cry_jokes_on_you = "Löse den Effect von Der Witz in Ante 1 aus und gewinne den Durchlauf", ach_cry_niw_uoy = "Erreiche Ante -8", ach_cry_now_the_fun_begins = "Bekomme Leinwand", - ach_cry_patience_virtue = "Warte bei der Lavendelschleife für 2 minuten bevor du sie besiegst", + ach_cry_patience_virtue = "Warte bei der Lavendelschleife für 2 Minuten bevor du sie besiegst", ach_cry_perfectly_balanced = "Besiege das Sehr Faire Deck auf Aufgestiegenen Einsatz", - ach_cry_pull_request = "Lass ://COMMIT den Joker erstellen den es zerstört hat.", + ach_cry_pull_request = "Lass ://COMMIT den Joker erstellen, den es zerstört hat.", ach_cry_traffic_jam = "Besiege alle Rush Hour Herausforderungen", ach_cry_ult_full_skip = "Gewinne in einer Runde", ach_cry_used_crash = "Benutze ://CRASH", ach_cry_what_have_you_done = "Lösche oder opfere einen Exotischen Joker", + ach_cry_pin = "Verliere einen Durchlauf gegen Die Stecknadel", + ach_cry_technically_positive = "Erhalte einen Negativen Negativer Joker", + ach_cry_youre_fucking_kidding = "Werfe " .. localize("cry_WholeDeck", "poker_hands") .. " ab", + ach_cry_stoned = "Stufe " .. localize("cry_Bulwark", "poker_hands") .. " auf Level 420 hoch", + ach_cry_fucked = "Stufe " .. localize("cry_Clusterfuck", "poker_hands") .. " auf Level 69 hoch", + ach_cry_stoned = "Stufe " .. localize("cry_UltPair", "poker_hands") .. " auf Level 2222 hoch", + ach_cry_stoned = "Stufe " .. localize("cry_WholeDeck", "poker_hands") .. " auf Level 5252 hoch", }, challenge_names = { c_cry_ballin = "Ballin'", c_cry_boss_rush = "Enter the Gungeon", c_cry_dagger_war = "Dolchkrieg", + c_cry_joker_poker = "Joker Poker", c_cry_onlycard = "Solo Karte", c_cry_rng = "RNG", c_cry_rush_hour = "Rush Hour I", @@ -3722,27 +4981,27 @@ return { --Settings Menu cry_set_features = "Features", cry_set_music = "Musik", - cry_set_enable_features = "Wähle features zum Aktivieren (wird beim Neustart angewendet):", + cry_set_enable_features = "Aktiviere oder Deaktiviere ganze Thematische Sets", cry_feat_achievements = "Erfolge", - ["cry_feat_antimatter deck"] = "Antimaterie Deck", + ["cry_feat_antimatter deck"] = "Antimaterie-Deck", cry_feat_blinds = "Blinds", cry_feat_challenges = "Herausforderungen", ["cry_feat_code cards"] = "Code Karten", ["cry_feat_misc. decks"] = "Verschiedene Decks", ["cry_feat_https module"] = "HTTPS Module", - ["cry_feat_timer mechanics"] = "Timer Mechaniken", + ["cry_feat_timer mechanics"] = "Timer Mechanismen", ["cry_feat_enhanced decks"] = "Verstärkte Karten", ["cry_feat_epic jokers"] = "Epische Joker", ["cry_feat_exotic jokers"] = "Exotische Joker", ["cry_feat_m jokers"] = "M Joker", - cry_feat_menu = "Eigene Main Menu", + cry_feat_menu = "Eigenes Main Menu", ["cry_feat_misc."] = "Verschiedenes", ["cry_feat_misc. jokers"] = "Verschiedene Joker", cry_feat_planets = "Planeten", cry_feat_jokerdisplay = "JokerDisplay (Macht nichts)", cry_feat_tags = "Tags", cry_feat_sleeves = "Hüllen", - cry_feat_spectrals = "Geisterkarten", + cry_feat_spectrals = "Geister-Karten", cry_feat_spooky = "Gruseliges Update", ["cry_feat_more stakes"] = "Einsätze", cry_feat_vouchers = "Gutscheine", @@ -3750,12 +5009,18 @@ return { cry_mus_code = "Code Cards (://LETS_BREAK_THE_GAME by HexaCryonic)", cry_mus_exotic = "Exotic Jokers (Joker in Latin by AlexZGreat)", cry_mus_high_score = "High Score (Final Boss [For Your Computer] by AlexZGreat)", + cry_mus_alt_bg = "Background Music (by MathIsFun_)", + cry_force_tooltips = "Erzwinge Tooltips", + cry_family = "Familienfreundlicher Modus", + cry_experimental = "Experimenteller Modus", - k_cry_program_pack = "Program Packet", - k_cry_meme_pack = "Meme Packet", + k_cry_program_pack = "Programm Paket", + k_cry_meme_pack = "Meme Paket", cry_critical_hit_ex = "Kritischer Treffer!", cry_critical_miss_ex = "Kritisch verfehlt!", + k_cry_baneful_pack = "Unheilvolles Clownspaket", + cry_baneful_warning = "Überspringen verbannt den Joker ganz rechts", cry_potion1 = "-1 zu allen Handleveln", cry_potion2 = "X1.15 Blindgröße", @@ -3763,18 +5028,32 @@ return { cry_debuff_oldhouse = "Keine Full Houses", cry_debuff_oldarm = "Must 4 oder weniger Karten spielen", - cry_debuff_oldpillar = "Keine Straßen", + cry_debuff_oldpillar = "Keine Straights", cry_debuff_oldflint = "Keine Flushes", - cry_debuff_oldmark = "Keine Hände die ein Paar enthalten", + cry_debuff_oldmark = "Keine Hände, die ein Paar enthalten", cry_debuff_obsidian_orb = "Hat die Fähigkeiten aller besiegten Bosse", + cry_blind_baneful_pack = "Öffne ein Unheilvolles Clownspaket am Ende der Runde", k_code = "Code", + k_chips = "Chips", + k_content_set = "Thematisches Set", + b_content_sets = "Thematische Sets", + --Why aren't these in vanilla? + b_tag = "Tag", + b_blind = "Blind", + rush_hour_reminder = "Aktiviere Die Uhr und Lavendelschleife, um Rush Hour zu spielen", + + b_tarot_rate = "Tarot Rate", + b_planet_rate = "Planet Rate", + k_unique = "Einzigartig", b_code_cards = "Code Karten", b_unique_cards = "Einzigartige Karten", b_pull = "PULL", + b_playing_cards = "Spielkarten", cry_hooked_ex = "Verhackt!", k_end_blind = "Beende Blind", + k_cry_shiny = "Shiny", cry_code_rank = "RANG EINGEBEN", cry_code_enh = "VERSTÄRKUNG EINGEBEN", @@ -3785,35 +5064,53 @@ return { cry_code_exploit = "HACKEN", cry_code_exploit_previous = "VORHERIGES HACKEN", cry_code_create = "ERSTELLEN", - cry_code_create_previous = "VERHERIGES ERSTELLEN", + cry_code_create_previous = "VORHERIGES ERSTELLEN", cry_code_execute = "AUSFÜHREN", cry_code_cancel = "ABBRECHEN", + cry_code_enter_hand = "NAME DER POKERHAND EINGEBEN", + cry_code_with_suits = "INKLUSIVE FARBE", + cry_code_without_suits = "IGNORIERE FARBE", + cry_code_suitless = "Hand benötigt keine bestimmte Farbe", + cry_code_empty = "[Declare Hand]", --TODO context? + cry_code_exit = "SCHLIESSEN", + cry_code_antevoucher = "Nächster Boss Blind and Gutschein", + cry_code_nextjokers = "Nächste Joker im Shop", + cry_code_nextcards = "Nächste Spielkarten", b_flip = "UMDREHEN", b_merge = "KOMBINIEREN", + b_store = "VERSTAUEN", cry_hand_bulwark = "Bollwerk", cry_hand_clusterfuck = "Clusterfuck", cry_hand_ultpair = "Ultimatives Paar", + cry_asc_hands = "Auf. Hände", + cry_p_star = "Stern", + cry_again_q = "Nochmal?", cry_curse = "Verflucht", cry_curse_ex = "Verflucht!", + cry_demicolon = "Demitrigger!", cry_sobbing = "Hilf mir...", cry_gaming = "Gaming", cry_gaming_ex = "Gaming!", cry_good_luck_ex = "Viel Glück!", cry_sus_ex = "Verräter!", cry_jolly_ex = "Jolly Up!", + cry_highfive_ex = "High Five!", cry_m_minus = "m", cry_m = "M", cry_m_ex = "M!", cry_minus_round = "-1 Runde", cry_plus_cryptid = "+1 Cryptid", + cry_plus_card = "+1 Karte", + cry_plus_code = "+1 Code", cry_no_triggers = "Keine Auslösungen übrig!", - cry_unredeemed = "Einlöung aufgehoben...", + cry_unredeemed = "Einlösung aufgehoben...", cry_active = "Aktiv", cry_inactive = "Inaktiv", + cry_divorced = "Geschieden!", k_disable_music = "Musik deaktivieren", @@ -3822,6 +5119,13 @@ return { cry_candy = "Süßigkeit", cry_cursed = "Verflucht", + k_downgraded_ex = "Downgraded!", + + k_planet_disc = "Kreisstellare Scheibe", + k_planet_satellite = "Natürliche Satelliten", + k_planet_universe = Cryptid_config.family_mode and "Universum" or "Das Tatsächliche Verfickte Universum", + k_planet_nibiru = "Nichts", + cry_notif_jimball_1 = "Jimball", cry_notif_jimball_2 = "Copyright Anmerkung", cry_notif_jimball_d1 = 'Jimball spielt den Song "Funkytown",', @@ -3829,7 +5133,7 @@ return { cry_notif_jimball_d3 = "für Streams und Videos genutzt werden kann.", cry_gameset_explanation = { - "Wähle eine Gameset Konfiguartion", + "Wähle eine Gameset Konfiguration", "für diese Karte.", }, cry_gameset_disabled = "Deaktiviert", @@ -3837,26 +5141,35 @@ return { cry_gameset_mainline = "Mainline", cry_gameset_madness = "Madness", cry_gameset_custom = "Modifiziert", - cry_gameset_exp = "Experimentel", - cry_gameset_exp_modest = "Experimentel (Modest)", - cry_gameset_exp_mainline = "Experimentel (Mainline)", - cry_gameset_exp_madness = "Experimentel (Madness)", + cry_gameset_exp = "Experimentell", + cry_gameset_exp_modest = "Experimentell (Modest)", + cry_gameset_exp_mainline = "Experimentell (Mainline)", + cry_gameset_exp_madness = "Experimentell (Madness)", - cry_view_set_contents = "Siehe Gegenstände im set", + cry_view_set_contents = "Siehe Gegenstände im Set", - b_reset_gameset_modest = "Setzt Gameset Konfiguaration zurück (Modest)", - b_reset_gameset_mainline = "Setzt Gameset Konfiguaration zurück (Mainline)", - b_reset_gameset_madness = "Setzt Gameset Konfiguaration zurück (Madness)", + -- TODO what are those? do they need translating? + cry_sapling_an = "an", + cry_sapling_a = "a", + + b_reset_gameset_modest = "Setzt Gameset Konfiguration zurück (Modest)", + b_reset_gameset_mainline = "Setzt Gameset Konfiguration zurück (Mainline)", + b_reset_gameset_madness = "Setzt Gameset Konfiguration zurück (Madness)", + + cry_circus_generic = "{V:#1#}#2#{} Joker geben je {X:mult,C:white} X#3# {} Mult", }, labels = { - food_jokers = "Essen Joker", + food_jokers = "Essen-Joker", banana = "Banane", + pinned = "Angeheftet", + cry_absolute = "Absolut", code = "Code", unique = "Einzigartig", cry_rigged = "Manipuliert", cry_hooked = "Verhackt", + cry_global_sticker = "Global", cry_flickering = "Flackernd", - cry_possessed = "Besezt", + cry_possessed = "Besessen", cry_green_seal = "Grünes Siegel", cry_azure_seal = "Azurblaues Siegel", @@ -3869,7 +5182,7 @@ return { cry_gold = "Golden", cry_m = "Lustig", cry_mosaic = "Mosaik", - cry_noisy = "Geräuchvoll", + cry_noisy = "Geräuschvoll", cry_oversat = "Übersättigt", cry_epic = "Episch", @@ -3880,11 +5193,11 @@ return { rnj_loc_txts = { stats = { plus_mult = { "{C:red}+#2#{} Mult" }, - plus_chips = { "{C:blue}+#2#{} Chips" }, + plus_chips = { "{C:blue}+#2#{} Chip(s)" }, x_mult = { "{X:red,C:white} X#2#{} Mult" }, x_chips = { "{X:blue,C:white} X#2#{} Chips" }, - h_size = { "{C:attention}+#2#{} Hand Size" }, - money = { "{C:money}+$#2#{} at payout" }, + h_size = { "{C:attention}+#2#{} Handgröße" }, + money = { "{C:money}+$#2#{} beim Auszahlen" }, }, stats_inactive = { plus_mult = { "{C:inactive}(Momentan {C:red}+#1#{C:inactive} Mult)" }, @@ -3896,10 +5209,10 @@ return { }, actions = { make_joker = { "Erstelle {C:attention}#2# Joker{}" }, - make_tarot = { "Erstelle {C:attention}#2#{C:tarot} Tarot{} Karte" }, - make_planet = { "Erstelle {C:attention}#2#{C:planet} Planet{} Karte" }, - make_spectral = { "Erstelle {C:attention}#2#{C:spectral} Spectral{} Karte" }, - add_dollars = { "Earn {C:money}$#2#{}" }, + make_tarot = { "Erstelle {C:attention}#2#{C:tarot} Tarot{}-Karte" }, + make_planet = { "Erstelle {C:attention}#2#{C:planet} Planeten{}-Karte" }, + make_spectral = { "Erstelle {C:attention}#2#{C:spectral} Geister{}-Karte" }, + add_dollars = { "Verdiene {C:money}$#2#{}" }, }, contexts = { open_booster = { "wenn ein {C:attention}Booster{} geöffnet wird" }, @@ -3909,7 +5222,7 @@ return { reroll_shop = { "beim Aktualisieren" }, ending_shop = { "am Ende des {C:attention}Shops{}" }, skip_blind = { "wenn ein {C:attention}Blind{} übersprungen wird" }, - skipping_booster = { "wenn ein {C:attention}Booster Packet{} übersprungen wird" }, + skipping_booster = { "wenn ein {C:attention}Booster Paket{} übersprungen wird" }, playing_card_added = { "wenn eine {C:attention}Spielkarte{} zum Deck hinzugefügt wird" }, first_hand_drawn = { "wenn die Runde beginnt" }, setting_blind = { "wenn {C:attention}Blind{} ausgewählt wird" }, @@ -3917,7 +5230,7 @@ return { using_consumeable = { "wenn ein {C:attention}Verbrauchsgegenstand{} genutzt wird" }, debuffed_hand = { "wenn gespielte {C:attention}Hand{} nicht erlaubt ist" }, pre_discard = { "vor jedem Abwurf" }, - discard = { "für jede Abgewurfene Karte" }, + discard = { "für jede abgeworfene Karte" }, end_of_round = { "am Ende der {C:attention}Runde{}" }, individual_play = { "für jede gewertete Karte" }, individual_hand_score = { "für jede Karte in der Hand während der Auswertung" }, @@ -3932,20 +5245,20 @@ return { conds = { buy_common = { "wenn dies ein {C:blue}Gewöhnlicher{} {C:attention}Joker{} ist" }, buy_uncommon = { "wenn dies ein {C:green}Ungewöhnlicher{} {C:attention}Joker{} ist" }, - tarot = { "wenn die Karte eine {C:tarot}Tarot{} Karte ist" }, - planet = { "wenn die Karte eine {C:planet}Planeten{} Karte" }, - spectral = { "wenn die Karte eine {C:spectral}Geisterkarte{} ist" }, + tarot = { "wenn die Karte eine {C:tarot}Tarot{}-Karte ist" }, + planet = { "wenn die Karte eine {C:planet}Planet{}-Karte{} ist" }, + spectral = { "wenn die Karte eine {C:spectral}Geister{}-Karte ist" }, joker = { "wenn die Karte ein {C:attention}Joker{} ist" }, - suit = { "wenn die Karte ein {V:1}#3#{} ist" }, + suit = { "wenn die Karte ein(e) {V:1}#3#{} ist" }, rank = { "wenn die Karte ein {C:attention}#3#{} ist" }, face = { "wenn die Karte eine {C:attention}Bildkarte{} ist" }, - boss = { "wenn {C:attention}Blind{} eine {C:attention}Boss {C:attention}Blind{} ist" }, - non_boss = { "wenn {C:attention}Blind{} eine {C:attention}Nicht-Boss {C:attention}Blind{} ist" }, - small = { "wenn {C:attention}Blind{} eine {C:attention}Small {C:attention}Blind{} ist" }, - big = { "wenn {C:attention}Blind{} eine {C:attention}Big {C:attention}Blind{} ist" }, + boss = { "wenn {C:attention}Blind{} ein {C:attention}Boss {C:attention}Blind{} ist" }, + non_boss = { "wenn {C:attention}Blind{} ein {C:attention}Nicht-Boss {C:attention}Blind{} ist" }, + small = { "wenn {C:attention}Blind{} ein {C:attention}Small {C:attention}Blind{} ist" }, + big = { "wenn {C:attention}Blind{} ein {C:attention}Big {C:attention}Blind{} ist" }, first = { "wenn dies die {C:attention}erste {C:attention}Hand{} ist" }, last = { "wenn dies die {C:attention}letzte {C:attention}Hand{} ist" }, - common = { "wenn es ein {C:blue}Gewöhnicher{} {C:attention}Joker{} ist" }, + common = { "wenn es ein {C:blue}Gewöhnlicher{} {C:attention}Joker{} ist" }, uncommon = { "wenn es ein {C:green}Ungewöhnlicher{} {C:attention}Joker{} ist" }, rare = { "wenn es ein {C:red}Seltener{} {C:attention}Joker{} ist" }, poker_hand = { "wenn Hand ein {C:attention}#3#{} is" }, @@ -3979,7 +5292,7 @@ return { cry_sticker_desc = { "Nutze diesen Joker", "um auf #2##1#", - "#2#Einsatz#3# Schwieringkeit tu gewinnen", + "#2#Einsatz#3# Schwierigkeit zu gewinnen", }, cry_art = { "Bild: #1#" }, @@ -3999,6 +5312,10 @@ return { "{C:attention}Die Uhr{} und {C:attention}Lavendelschleife{} steigen {C:attention}doppelt{} so schnell", }, ch_c_cry_no_tags = { "Überspringen ist {C:attention}deaktiviert{}" }, + ch_c_cry_no_vouchers = { "Im Shop erscheinen keine {C:attention}Gutscheine{} mehr" }, + ch_c_cry_no_boosters = { "Im Shop erscheinen keine {C:attention}Booster Pakete{} mehr" }, + ch_c_cry_no_rerolls = { "Aktualisieren ist {C:attention}deaktiviert{}" }, + ch_c_cry_no_consumables = { "Es erscheinen keine {C:attention}Verbrauchsgegenstände{} mehr" }, }, -- Thanks to many members of the community for contributing to all of these quips! -- There's too many to credit so just go here: https://discord.com/channels/1116389027176787968/1209506360987877408/1237971471146553406 @@ -4012,14 +5329,14 @@ return { { "OOPS!", "KEINE GUTSCHEINE", "" }, { "DU NARR,", "WARUM GUCKST ÜBERHAUPT", "HIER HER? LOL" }, { "DER GUTSCHEIN", "IST IN EINEM", "ANDEREN SCHLOSS" }, - { "$0", "LEER", "(HASTE GECHEKT?)" }, + { "$0", "LEER", "(HASTE GECHECKT?)" }, { "ERROR", "CANNOT DO ARITHMETIC ON A NIL VALUE", "(tier4vouchers.lua)" }, { "ALLE GUTSCHEINE", "100% REDUZIERT", "(JEMAND HAT SIE SCHON GEKAUFT)" }, { "VERSUCHST SPÄTER NOCHMAL", "HINWEIS: DU WIRST NICHT", "GENUG GELD HABEN" }, { "HÄ?", '"GUTSCHEINE"?', "DAS IST NICHTMAL EIN WORT..." }, { 'HALTE "R"', "UM ALLE GUTSCHEINE", "NACHZUFÜLLEN" }, { "WUSSTEST DU?", "ALT+F4 DRÜCKEN", "GIBT KOSTENLOSE GUTSCHEINE!" }, - { "TUHT MIR LEID,", "ES GIBT KEINE GUTSCHEINE", "WEGEN BUDGETVERKÜRZUNGEN" }, + { "TUT MIR LEID,", "ES GIBT KEINE GUTSCHEINE", "WEGEN BUDGETVERKÜRZUNGEN" }, { "RUFE 1-600-JIMBO AN", "UM DEINE ERFAHRUNG MIT", "GUTSCHEINEN ZU BEWERTEN" }, { "BESIEGE", "ANTE 39 BOSS BLIND", "ZUM NACHFÜLLEN" }, { "ZAUBERTRICK", "ICH HABE DIESEN GUTSCHEIN", "VERSCHWINDEN LASSEN" }, @@ -4032,13 +5349,13 @@ return { { "WARUM NENNEN SIE ES GUTSCHEIN", "WENN ER NICHTMAL GUT GENUG IT", "ZU ERSCHEINEN" }, { "LEIDER WURDE", "DAS GUTSCHEIN NACHFÜLL", "UPDATE ABGEBROCHEN" }, { "BESIEGE DIE", "BOSS BLIND", "UM NICHTS ZU ÄNDERN" }, - { "DIE VÖGEL ZWITCHERN", "DIE BLUMEN BLÜHEN", "KINDER WIE DU..." }, - { "ES TUHT UNS LEID ZU SAGEN", "ALLE GUTSCHEINE WURDEN ZURÜCKGEZOGEN", "WEGEN EINEN SALMONELLENBEFALL" }, + { "DIE VÖGEL ZWITSCHERN", "DIE BLUMEN BLÜHEN", "KINDER WIE DU..." }, + { "ES TUT UNS LEID ZU SAGEN", "ALLE GUTSCHEINE WURDEN ZURÜCKGEZOGEN", "WEGEN EINEN SALMONELLENBEFALL" }, { "GUTSCHEINE KONNTEN NICHT ANKOMMEN", "WEIL DER SHOP", "200% ÜBER DEM BUDGET IST" }, { "DU MAGST", "GUTSCHEINE KAUFEN, NICHT WAHR?", "DU BIST EIN GUTSCHEINKÄUFER" }, { "GUTSCHEINE", "!E", "GUTSCHEIN POOL" }, { "ES", "GIBT KEINE", "GUTSCHEINE" }, - { "ES GIBT KEINEN", "WEINACHTSMANN", "UND AUCH KEINE GUTSCHEINE" }, + { "ES GIBT KEINEN", "WEIHNACHTSMANN", "UND AUCH KEINE GUTSCHEINE" }, { "", "GUTNEIN", "" }, { "DU", "HAST GERADE", "DAS SPIEL VERLOREN" }, { "KANN ICH DIR IN DIESEN", "IN DIESEN SCHWEREN ZEITEN", "EIN SCHÖNES EI ANBIETEN?" }, @@ -4049,7 +5366,7 @@ return { { "", "keine gutscheine?", "" }, { "siehst du diese werbung?", - "wenn ja, dann funkioniert sie", + "wenn ja, dann funktioniert sie", "und du könntest sie nun für dich selbst haben", }, { "DU VERPASST HIER", "MINDESTENS 5 GUTSCHEINE", "tonktonktonktonktonk" }, @@ -4062,7 +5379,7 @@ return { "HEISSE GUTSCHEINE IN DEINER GEGEND!", "BEKOMME SCHNELL GUTSCHEINE MIT DIESEM LEICHTEN TRICK", }, - { "JETZT STELLE ICH DIE", "ERSTEN LEVEL 0 GUTSCHEINE VOR!", "(kommt bald in Crypid 1.0)" }, + { "JETZT STELLE ICH DIE", "ERSTEN LEVEL 0 GUTSCHEINE VOR!", "(kommt bald in Cryptid 1.0)" }, { "EIN GUTSCHEIN!", "ES IST NUT EINE VORSTELLUNG", "WIR HABEN UNS VORGESTELLT, DASS DU IHN WILLST" }, { "MACH DEINEN ADBLOCKER AUS!", "WIE SOLLEN WIR OHNE WERBUNG", "GUTSCHEINE VERKAUFEN" }, { "WENN DU EIN", "PROBLEM HIERMIT HAST", "SIND WIR UNTER NORESPONSE@JMAIL.COM ERREICHBAR" }, @@ -4076,13 +5393,13 @@ return { "..-. ..-- .-. / . .. -. . -. / --. ..- - ... -.-. .... . .. -.", }, { "DURCHLAUF > NEU", "STARRE INS NICHTS", "FÜR EINE ODER ZWEI STUNDEN" }, - { "TUHT UNS LEID", "DER LETZTE TYP HAT", "IN DER PANIK ALLE GUTSCHEINE GEKAUFT" }, + { "TUT UNS LEID", "DER LETZTE TYP HAT", "IN DER PANIK ALLE GUTSCHEINE GEKAUFT" }, { "WIE FÜHLT ES SICH AN", "KEINE GUTSCHEINE", "ZU KAUFEN" }, { "JIMBO WAR WÜTEND", "UND HAT ALLE GUTSCHEINE", "WEGGEWORFEN" }, { "VERSUCHE INDEX IN", "FELD 'GUTSCHEIN' ZU FINDEN", "(EIN NIL WERT)" }, { "HAST DU WIRKLICH ERWARTET, DASS ALL DIESE TEXT ZU LESEN DIR MÖGLICHERWEISE GUTSCHEINE BRINGEN KÖNNTE", - "TUHT MIR LEID DIR DAS MITTEILEN ZU MÜSSEN, ABER IN DIESEM DECK EXISTIEREN GUTSCHEINE NUNMAL NICHT", + "TUT MIR LEID DIR DAS MITTEILEN ZU MÜSSEN, ABER IN DIESEM DECK EXISTIEREN GUTSCHEINE NUNMAL NICHT", "AUSSERDEM IST DIESER ABNORMAL LANGE TEXT NOCH EXTRA DAFÜR DA DEINE ZEIT BEIM LESEN ZU VERSCHWENDEN", }, { "GEH ZU", "https://youtu.be/p7YXXieghto", "FÜR KOSTENLOSE GUTSCHEINE" }, diff --git a/Cryptid/localization/en-us.lua b/Cryptid/localization/en-us.lua index 366ca9e..43fe226 100644 --- a/Cryptid/localization/en-us.lua +++ b/Cryptid/localization/en-us.lua @@ -89,8 +89,8 @@ return { name = "Critical Deck", text = { "After each hand played,", - "{C:green}#1# in 4{} chance for {X:dark_edition,C:white} ^2 {} Mult", - "{C:green}#1# in 8{} chance for {X:dark_edition,C:white} ^0.5 {} Mult", + "{C:green}#1# in #2#{} chance for {X:dark_edition,C:white} ^2 {} Mult", + "{C:green}#1# in #3#{} chance for {X:dark_edition,C:white} ^0.5 {} Mult", }, unlock = { "Obtain a {C:attention}Rigged Joker", @@ -263,7 +263,7 @@ return { name = "Legendary Deck", text = { "Start with a {C:legendary}Legendary{C:legendary} Joker", - "{C:green}1 in 5{} chance to create another", + "{C:green}#1# in #2#{} chance to create another", "when Boss Blind is defeated {C:inactive}(must have room){}", }, unlock = { @@ -284,7 +284,8 @@ return { name = "The Clock", text = { "+0.1X blind requirements every", - "12 seconds spent this ante", + "12 seconds spent this ante,", + "multiplied by game speed", }, }, bl_cry_hammer = { @@ -312,7 +313,8 @@ return { name = "Lavender Loop", text = { "1.25X blind requirements every", - "6 seconds spent this round", + "6 seconds spent this round,", + "multiplied by game speed", }, }, bl_cry_obsidian_orb = { @@ -396,6 +398,37 @@ return { "discarded cards", }, }, + bl_cry_greed = { + name = "The Greed", + text = { + "+#2# blind requirement", + "per $#1# when selected", + }, + }, + bl_cry_repulsor = { + name = "The Repulsor", + text = { + "Retrigger rightmost and", + "leftmost Jokers, all other", + "Jokers do not trigger", + }, + }, + bl_cry_chromatic = { + name = "The Chromatic", + text = { + "Hand score is", + "subtracted on", + "odd numbered hands", + }, + }, + bl_cry_landlord = { + name = "The Landlord", + text = { + "Apply rental to", + "a random Joker", + "when hand is played", + }, + }, bl_cry_pinkbow = { name = "Pink Bow", text = { @@ -466,116 +499,28 @@ return { "are debuffed", }, }, + bl_cry_decision = { + name = "The Decision", + text = { + "Fasten Jokers on play or discard", + "Open a Baneful Buffoon", + "Pack after round", + }, + }, }, Code = { - c_cry_alttab = { - name = "://ALTTAB", - text = { - "Create the {C:cry_code}current{}", - "blind's skip tag", - "{C:inactive}(Current: {C:cry_code}#1#{C:inactive})", - }, - }, - c_cry_class = { - name = "://CLASS", - text = { - "Convert {C:cry_code}#1#{} selected card#1#", - "to a {C:cry_code}chosen{} enhancement", - }, - }, - c_cry_commit = { - name = "://COMMIT", - text = { - "Destroy a {C:cry_code}selected{} Joker,", - "create a {C:cry_code}new{} Joker", - "of the {C:cry_code}same rarity", - }, - }, c_cry_crash = { name = "://CRASH", text = { "{C:cry_code,E:1}Don't.", }, }, - c_cry_ctrl_v = { - name = "://CTRL+V", + c_cry_keygen = { + name = "://KEYGEN", text = { - "Create a {C:cry_code}copy{} of a selected", - "playing card or consumable", - }, - }, - c_cry_delete = { - name = "://DELETE", - text = { - "{C:cry_code}Banish{} any {C:cry_code}selected{}", - "shop item, it will no longer", - "appear normally this run", - "{C:inactive}Multiuse: ({C:cry_code}#1#{C:inactive} remaining)", - }, - }, - c_cry_divide = { - name = "://DIVIDE", - text = { - "{C:cry_code}Halve{} all listed prices", - "in current shop", - }, - }, - c_cry_exploit = { - name = "://EXPLOIT", - text = { - "{C:cry_code}Choose{} a {C:cry_code}currently visible{} poker hand,", - "next hand is {C:cry_code}calculated{} as that hand,", - "and gains {C:cry_code}one{} temp {C:cry_code}Ascension Power{}", - "{C:inactive}Multiuse: ({C:cry_code}#1#{C:inactive} remaining)", - }, - }, - c_cry_hook = { - name = "HOOK://", - text = { - "Select two Jokers to become {C:cry_code}Hooked", - "{C:inactive,s:0.8}Only works properly if Jokers trigger in the same context,", - "{C:inactive,s:0.8}such as Joker and The Duo (both post-scoring)", - }, - }, - c_cry_inst = { - name = "://INSTANTIATE", - text = { - "Draw a card with selected card's {C:cry_code}rank{}", - "and one with selected card's {C:cry_code}suit{}", - "{C:inactive}(if possible){}", - }, - }, - c_cry_machinecode = { - name = "://MACHINECODE", - text = { - "", - }, - }, - c_cry_malware = { - name = "://MALWARE", - text = { "Add {C:dark_edition}Glitched{} to all", "cards {C:cry_code}held in hand" }, - }, - c_cry_merge = { - name = "://MERGE", - text = { - "Merge a selected {C:cry_code}consumable", - "with a selected {C:cry_code}playing card", - }, - }, - c_cry_multiply = { - name = "://MULTIPLY", - text = { - "{C:cry_code}Double{} all values of", - "a selected {C:cry_code}Joker{} until", - "end of round", - }, - }, - c_cry_patch = { - name = "://PATCH", - text = { - "Remove all {C:cry_code}debuffs", - "from currently visible items", - "{C:cry_code}Resets{} shop state", + "Create a random {C:cry_code}Perishable Banana{}", + "voucher, {C:cry_code}destroy{} previously created", + "voucher created this way.", }, }, c_cry_payload = { @@ -585,28 +530,26 @@ return { "gives {C:cry_code}X#1#{} interest", }, }, - c_cry_oboe = { - name = "://OFFBYONE", + c_cry_exploit = { + name = "://EXPLOIT", text = { - "Next {C:cry_code}Booster Pack{} has", - "{C:cry_code}#1#{} extra card#1# and", - "{C:cry_code}#1#{} extra choice#1#", - "{C:inactive}(Currently {C:cry_code}+#2#{C:inactive})", + "{C:cry_code}Choose{} a {C:cry_code}currently visible{} poker hand,", + "next hand is {C:cry_code}calculated{} as that hand,", + "and gains {C:cry_code}one{} temp {C:cry_code}Ascension Power{}", }, }, - c_cry_reboot = { - name = "://REBOOT", + c_cry_malware = { + name = "://MALWARE", text = { - "Replenish {C:blue}Hands{} and {C:red}Discards{},", - "return {C:cry_code}all{} cards to deck", - "and draw a {C:cry_code}new{} hand", + "Add {C:dark_edition}Glitched{} to all", + "cards {C:cry_code}held in hand", }, }, - c_cry_revert = { - name = "://REVERT", + c_cry_nperror = { + name = "://NPERROR", text = { - "Set {C:cry_code}game state{} to", - "start of {C:cry_code}this Ante{}", + "Returns the {C:cry_code}last played hand{}", + "to your hand", }, }, c_cry_rework = { @@ -618,11 +561,32 @@ return { "{C:inactive,s:0.8}Upgrades using order in the Collection", }, }, - c_cry_run = { - name = "://RUN", + c_cry_merge = { + name = "://MERGE", text = { - "Visit a {C:cry_code}shop", - "during a {C:cry_code}Blind", + "Merge a selected {C:cry_code}consumable", + "with a selected {C:cry_code}playing card", + }, + }, + c_cry_commit = { + name = "://COMMIT", + text = { + "Destroy a {C:cry_code}selected{} Joker,", + "create a {C:cry_code}new{} Joker", + "of the {C:cry_code}same rarity", + }, + }, + c_cry_machinecode = { + name = "://MACHINECODE", + text = { + "", + }, + }, + c_cry_spaghetti = { + name = "://SPAGHETTI", + text = { + "Create a {C:cry_code}Glitched", + "Food Joker", }, }, c_cry_seed = { @@ -633,15 +597,87 @@ return { "to become {C:cry_code}Rigged", }, }, - c_cry_semicolon = { - name = ";//", - text = { "Ends current non-Boss {C:cry_code}Blind{}", "{C:cry_code}without{} cashing out" }, - }, - c_cry_spaghetti = { - name = "://SPAGHETTI", + c_cry_patch = { + name = "://PATCH", text = { - "Create a {C:cry_code}Glitched", - "Food Joker", + "Remove all {C:cry_code}debuffs", + "from currently visible items", + "{C:cry_code}Resets{} shop state", + }, + }, + c_cry_cryupdate = { + name = "://UPDATE", + text = { + "To Be {C:cry_code}Determined{}", + "in a future {C:cry_code}update{}", + }, + }, + c_cry_hook = { + name = "HOOK://", + text = { + "Apply {C:cry_code}Hooked{} to", + "2 selected Jokers", + }, + }, + c_cry_oboe = { + name = "://OFFBYONE", + text = { + "Next {C:cry_code}Booster Pack{} has", + "{C:cry_code}#1#{} extra card#1# and", + "{C:cry_code}#1#{} extra choice#1#", + "{C:inactive}(Currently {C:cry_code}+#2#{C:inactive})", + }, + }, + c_cry_assemble = { + name = "://ASSEMBLE", + text = { + "Add {C:cry_code}Mult{} to the", + "{C:cry_code}selected hand{} equal to", + "how many Jokers are owned", + }, + }, + c_cry_inst = { + name = "://INSTANTIATE", + text = { + "Draw a card with selected card's {C:cry_code}rank{}", + "and one with selected card's {C:cry_code}suit{}", + "{C:inactive}(if possible){}", + }, + }, + c_cry_revert = { + name = "://REVERT", + text = { + "Set {C:cry_code}game state{} to", + "start of {C:cry_code}this Ante{}", + }, + }, + c_cry_cryfunction = { + name = "FUNCTION://", + text = { + "Saves the {C:cry_code}Last Three{} consumables used,", + "using this card again creates a copy of", + "the first with a {C:cry_code}Function://{} sticker", + }, + }, + c_cry_run = { + name = "://RUN", + text = { + "Visit a {C:cry_code}shop", + "during a {C:cry_code}Blind", + }, + }, + c_cry_class = { + name = "://CLASS", + text = { + "Convert {C:cry_code}#1#{} selected card#1#", + "to a {C:cry_code}chosen{} enhancement", + }, + }, + c_cry_global = { + name = "://GLOBAL", + text = { + "Select a playing card", + "to become {C:cry_code}Global{}", }, }, c_cry_variable = { @@ -651,6 +687,86 @@ return { "to a {C:cry_code}chosen{} rank", }, }, + c_cry_log = { + name = "://LOG", + text = { + "Show a {C:cry_code}readout{} of either: ", + "{C:attention}next{} antes {C:attention}Boss-Blind{} and {C:attention}Voucher{},", + "the next {C:attention}5{} {C:attention}Jokers{} from the shop, or", + "the next {C:attention}10{} playing cards to be {C:attention}drawn{}", + "{C:inactive}(If in a Blind){}", + }, + }, + c_cry_quantify = { + name = "://QUANTIFY", + text = { + "Transfer {C:attention}#1#{} selected", + "{C:attention}Card#1#{}, or {C:attention}Booster#1#{}", + "to the {C:attention}Jokers{} tray", + }, + }, + c_cry_divide = { + name = "://DIVIDE", + text = { + "{C:cry_code}Halve{} all listed prices", + "in current shop", + }, + }, + c_cry_multiply = { + name = "://MULTIPLY", + text = { + "{C:cry_code}Double{} all values of", + "a selected {C:cry_code}Joker{} until", + "end of round", + }, + }, + c_cry_delete = { + name = "://DELETE", + text = { + "{C:cry_code}Banish{} any {C:cry_code}selected{}", + "shop item, it will no longer", + "appear normally this run", + }, + }, + c_cry_alttab = { + name = "://ALTTAB", + text = { + "Create the {C:cry_code}current{}", + "blind's skip tag", + "{C:inactive}(Current: {C:cry_code}#1#{C:inactive})", + }, + }, + c_cry_ctrl_v = { + name = "://CTRL+V", + text = { + "Create a {C:cry_code}copy{} of a selected", + "playing card or consumable", + }, + }, + c_cry_reboot = { + name = "://REBOOT", + text = { + "Replenish {C:blue}Hands{} and {C:red}Discards{},", + "return {C:cry_code}all{} cards to deck", + "and draw a {C:cry_code}new{} hand", + }, + }, + c_cry_semicolon = { + name = ";//", + text = { + "Ends current non-Boss {C:cry_code}Blind{}", + "{C:cry_code}without{} cashing out", + }, + }, + c_cry_declare = { + name = "://DECLARE", + text = { + "Your {C:attention}currently{} selected cards", + "become a {C:cry_code}new{} Poker hand which is", + "considered to contain a {C:attention}#1#{}", + "You may create up to {C:attention}3{} {C:inactive}[#2#]{} Hands", + }, + }, }, ["Content Set"] = { set_cry_blind = { @@ -704,6 +820,13 @@ return { "and {C:attention}Jolly Joker", }, }, + set_cry_meme = { + name = "Meme", + text = { + "Things related to", + "multiple references", + }, + }, set_cry_misc = { name = "Misc.", text = { @@ -730,7 +853,7 @@ return { set_cry_poker_hand_stuff = { name = "Poker Hand Stuff", text = { - "Add 4 new {C:attention}poker hands", + "Add 5 new {C:attention}poker hands", "and enable {C:attention}Ascended hands", }, }, @@ -812,6 +935,7 @@ return { "{C:green}#1# in #2#{} chance this", "card isn't {C:red}destroyed", "when triggered", + "{C:inactive}Unriggable{}", }, }, e_cry_glitched = { @@ -879,6 +1003,16 @@ return { "{C:inactive}(Currently {X:mult,C:white}X#2#{C:inactive} Mult)", }, }, + m_cry_abstract = { + name = "Abstract Card", + text = { + "{X:dark_edition,C:white}^#1#{} Mult,", + "Counts as its {C:attention}own{} rank and suit", + "{C:green}#4# in #5#{} chance to", + "{C:red,E:2}destroy{} card when held at", + "{C:attention}round end{} or {C:attention}hand played{}", + }, + }, }, Joker = { j_cry_test_modest = { @@ -922,6 +1056,7 @@ return { "Sell this card to create", "{C:attention}#1#{} cop#1# of the leftmost {C:attention}Joker{}", "{C:inactive,s:0.8}Does not copy Nostalgic Googol Play Cards{}", + "{C:inactive}(Must have room){}", }, }, j_cry_altgoogol_balanced = { @@ -1004,6 +1139,16 @@ return { "{C:inactive,s:0.8}Rank does not change", }, }, + j_cry_rotten_egg = { + name = "Rotten Egg", + text = { + "When obtained, set sell value of", + "all current and future Jokers to {C:attention}$#1#{}", + "Reduce sell value of all {C:attention}Jokers{} by {C:attention}$#2#{}", + "At end of round, after gaining {C:attention}$#3#{} {C:inactive}[#4#]{}", + "from selling {C:attention}Jokers{}, {C:red}Self-destruct{}", + }, + }, j_cry_blender = { name = "Blender", text = { @@ -1095,12 +1240,20 @@ return { "for {C:mult}-#2#{} Mult", }, }, + j_cry_buttercup = { + name = "Buttercup", + text = { + "Can store {C:attention}#1#{} selected shop item#1#", + "When sold: Add the stored item#1#", + "to the next shop", + }, + }, j_cry_candy_basket = { name = "Candy Basket", text = { "Sell this card to create {C:attention}#1#{} {C:cry_candy}Cand#1#", - "{C:attention}+#2#{} {C:cry_candy}Cand#2#{} every {C:attention}2{} Blinds defeated", - "{C:attention}+#3#{} {C:cry_candy}Cand#3#{} when {C:attention}Boss Blind{} defeated", + "{C:attention}+#2#{} {C:cry_candy}Cand#2#{} every {C:attention}#3#{} Blinds defeated", + "{C:attention}+#3#{} {C:cry_candy}Cand#4#{} when {C:attention}Boss Blind{} defeated", }, }, j_cry_candy_buttons = { @@ -1212,12 +1365,7 @@ return { }, j_cry_circus = { name = "Circus", - text = { - "{C:red}Rare{} Jokers each give {X:mult,C:white} X#1# {} Mult", - "{C:cry_epic}Epic{} Jokers each give {X:mult,C:white} X#2# {} Mult", - "{C:legendary}Legendary{} Jokers each give {X:mult,C:white} X#3# {} Mult", - "{C:cry_exotic}Exotic{} Jokers each give {X:mult,C:white} X#4# {} Mult", - }, + text = Cryptid.get_circus_description(), --for translaters: this is automatically localized you can copy it over as long as cry_circus_generic is translated too unlock = { "Obtain a {C:red}Rare{},", "{C:cry_epic}Epic{} and {C:legendary}Legendary{}", @@ -1237,6 +1385,18 @@ return { "an {E:1,C:attention}Ultimate Pair", }, }, + j_cry_the = { + name = "The", + text = { + "{X:mult,C:white} X#1# {} Mult if played", + "hand is {C:attention}#2#", + }, + unlock = { + "Win a run with", + "your final hand being", + "a {E:1,C:attention}None", + }, + }, j_cry_clicked_cookie = { name = "Clicked Cookie", text = { @@ -1330,7 +1490,7 @@ return { j_cry_crustulum = { name = "Crustulum", text = { - "This Joker gains {C:chips}+#2#{} Chip#1#", + "This Joker gains {C:chips}+#2#{} Chip#2#", "per {C:attention}reroll{} in the shop", "{C:green}All rerolls are free{}", "{C:inactive}(Currently {C:chips}+#1#{C:inactive} chip#1#)", @@ -1376,7 +1536,7 @@ return { text = { "This Joker destroys", "a random {C:cry_code}Code{} card", - "and gains {X:mult,C:white} X#1# {} Mult", + "to gain {X:mult,C:white} X#1# {} Mult", "at the end of the {C:attention}shop{}", "{C:inactive}(Currently {X:mult,C:white} X#2# {C:inactive} Mult)", }, @@ -1389,6 +1549,21 @@ return { "a {C:attention}#2#", }, }, + j_cry_demicolon = { + name = "Demicolon", + text = { + "{C:attention}Force-trigger{} the Joker", + "to the right", + }, + }, + j_cry_starfruit = { + name = "Starfruit", + text = { + "{X:dark_edition,C:white}^#1#{} Mult,", + "loses {X:dark_edition,C:white}^#2#{} Mult per", + "{C:attention}reroll{} in the shop", + }, + }, j_cry_digitalhallucinations = { name = "Digital Hallucinations", text = { @@ -1576,6 +1751,15 @@ return { "{C:attention}#2#{} or fewer times", }, }, + j_cry_familiar_currency = { + name = "Familiar Currency", + text = { + "Create a {C:attention}Meme Joker{}", + "at the end of round", + "for {C:money}$#1#{} {C:inactive}(if possible)", + "{C:inactive}(Must have room)", + }, + }, j_cry_filler = { name = "The Filler", text = { @@ -1628,6 +1812,13 @@ return { "an {C:attention}#2#", }, }, + j_cry_undefined = { + name = "Undefined Joker", + text = { + "{C:red}+#1#{} Mult if played", + "hand is {C:attention}#2#", + }, + }, j_cry_formidiulosus = { name = "Formidiulosus", text = { @@ -1681,9 +1872,9 @@ return { name = "Ghost", text = { "At end of round:", - "{C:green}#1# in #2#{} chance to", - "{C:attention}possess{} a random {C:attention}Joker", "{C:green}#1# in #3#{} chance to", + "{C:attention}possess{} a random {C:attention}Joker", + "{C:green}#2# in #4#{} chance to", "{E:2,C:red}self destruct", }, }, @@ -1730,8 +1921,8 @@ return { name = "Happy House", text = { "{X:dark_edition,C:white}^#1#{} Mult only after", - "playing {C:attention}114{} hands{}", - "{C:inactive}(Currently #2#/114){}", + "playing {C:attention}#3#{} hands{}", + "{C:inactive}(Currently #2#/#3#){}", "{C:inactive,s:0.8}There is no place like home!{}", }, }, @@ -1769,6 +1960,7 @@ return { "{C:attention}#2#{} time#2#,", "each played card gives", "{X:mult,C:white} X#1# {} Mult when scored", + "{C:inactive}(Max {}{C:attention}#3#{}{C:inactive} retriggers)", }, }, j_cry_jawbreaker = { @@ -1867,6 +2059,7 @@ return { "Played and scoring {C:attention}Kings{} give", "{C:attention}+#1#{} hand size for the round", "and trigger {C:attention}held in hand{} effects", + "{C:inactive}(Currently {}{C:attention}+#2#{}{C:inactive})", }, }, j_cry_lightupthenight = { @@ -1989,7 +2182,7 @@ return { "{C:attention}first discard{} of each round", }, }, - j_cry_Megg = { + j_cry_megg = { name = "Megg", text = { "Sell this card to create", @@ -2011,7 +2204,7 @@ return { "{X:mult,C:white}X#1#{} Mult for each member", "in the {C:attention}Cryptid Discord{}", "{C:inactive}(Currently {X:mult,C:white}X#2#{C:inactive} Mult)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_membershipcardtwo = { @@ -2020,7 +2213,7 @@ return { "{C:chips}+#1#{} Chip#1# for each member", "in the {C:attention}Cryptid Discord{}", "{C:inactive}(Currently {C:chips}+#2#{C:inactive} Chip#2#)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_membershipcardtwo_balanced = { @@ -2029,7 +2222,7 @@ return { "{C:chips}+#1#{} Chip#1# for every {C:attention}8{} members", "in the {C:attention}Cryptid Discord{}", "{C:inactive}(Currently {C:chips}+#2#{C:inactive} Chip#2#)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_meteor = { @@ -2116,9 +2309,9 @@ return { j_cry_necromancer = { name = "Necromancer", text = { - "When a Joker is {C:attention}sold{} for more than {C:attention}$0{},", + "When a Joker is {C:attention}sold{} for more than {C:attention}#1#{},", "gain a {C:attention}random{} Joker {C:attention}sold{} this run", - "with {C:money}$0{} sell value", + "with {C:money}#1#{} sell value", }, }, j_cry_negative = { @@ -2267,6 +2460,14 @@ return { "gain a random {C:attention}Tag{}", }, }, + j_cry_pity_prize_modest = { + name = "Pity Prize", + text = { + "On skipping a {C:attention}Booster Pack{},", + "gain a random {C:attention}Tag{}", + "{C:red,E:2}Self destructs{}", + }, + }, j_cry_pot_of_jokes = { name = "Pot of Jokes", text = { @@ -2500,6 +2701,71 @@ return { '{C:inactive,s:0.8}"This prison... to hold... me?"', }, }, + j_cry_sock_and_sock = { + name = "Sock and Sock", + text = { + "Retrigger all played", + "{C:attention}Abstract{} cards {C:attention}#1#{} time#1#", + }, + }, + j_cry_brokenhome = { + name = "Broken Home", + text = { + "{X:mult,C:white} X#1# {} Mult", + "{C:green}#2# in #3#{} chance this", + "card is destroyed", + "at end of round", + }, + }, + j_cry_yarnball = { + name = "Yarn Ball", + text = { + "Add the level of the highest level {C:attention}Cat Tag{}", + "to all {C:green}listed probabilities", + }, + }, + j_cry_pizza = { + name = "Pizza", + text = { + "After {C:attention}#1#{} {C:inactive}[#2#]{} round#1#", + "sell this Joker to create", + "{C:attention}#3#{} Pizza Slices", + }, + }, + j_cry_pizza_slice = { + name = "Pizza Slice", + text = { + "This Joker gains {X:mult,C:white}X#1#{} Mult", + "when a {C:attention}Pizza Slice{} is sold", + "{C:inactive}(Currently{} {X:mult,C:white}X#2#{}{C:inactive} Mult){}", + }, + }, + j_cry_paved_joker = { + name = "Paved Joker", + text = { + "Stone Cards may fill", + "gaps of {C:attention}#1#{} in", + "{C:attention}Straights{} and {C:attention}Flushes{}", + }, + }, + j_cry_fading_joker = { + name = "Fading Joker", + text = { + "This Joker Gains", + "{X:mult,C:white}X#1#{} Mult whenever", + "a {C:attention}Perishable{} card is debuffed", + "{C:inactive}(Currently{} {X:mult,C:white}X#2#{} {C:inactive}Mult){}", + }, + }, + j_cry_poor_joker = { + name = "Poor Joker", + text = { + "This Joker gains", + "{C:mult}+#1#{} Mult whenever", + "a {C:attention}Rental{} card takes money", + "{C:inactive}(Currently{} {C:mult}+#2#{} {C:inactive}Mult){}", + }, + }, j_cry_spaceglobe = { name = "Celestial Globe", text = { @@ -2545,7 +2811,7 @@ return { text = { "This Joker destroys a", "random {C:planet}Planet{} card", - "and gains {X:dark_edition,C:white} ^#1# {} Mult", + "to gain {X:dark_edition,C:white} ^#1# {} Mult", "at the end of the {C:attention}shop{}", "{C:inactive}(Currently {X:dark_edition,C:white} ^#2# {C:inactive} Mult)", }, @@ -2649,11 +2915,48 @@ return { "an {C:attention}#2#", }, }, + j_cry_nebulous = { + name = "Nebulous Joker", + text = { + "{C:chips}+#1#{} Chip#1# if played", + "hand is {C:attention}#2#", + }, + }, + j_cry_words_cant_even = { + name = "Words Can’t Even Begin to Describe This Joker", + text = { + "{X:mult,C:white}X#1#{} Mult if played", + "hand contains", + "a {C:attention}#2#", + }, + }, + j_cry_many_lost_minds = { + name = "Many Have Lost Their Minds Comprehending This Joker", + text = { + "{C:chips}+#1#{} Chips if played", + "hand contains", + "{C:attention}#2#", + }, + }, + -- i wanted to correct this typo, but its not even used anywhere?? (well, except other localizations lol) + j_cry_annihalation = { + name = "The Complete and Utter Annihilation of Everything That Makes Balatro Sacred", + text = { + "{X:dark_edition,C:white}^#1#{} Mult if played", + "hand contains", + "a {C:attention}#2#", + }, + unlock = { + "Win a run with", + "your final hand being", + "a {E:1,C:attention}#1#", + }, + }, j_cry_trick_or_treat = { name = "Trick-or-Treat", text = { "When {C:attention}sold{}:", - "{C:green}#1# in #2#{} chance to create {C:attention}2{} {C:cry_candy}Candies", + "{C:green}#1# in #2#{} chance to create {C:attention}#3#{} {C:cry_candy}Candies", "Otherwise, create a {X:cry_cursed,C:white}Cursed{} Joker", "{C:inactive}(Can overflow)", }, @@ -2678,7 +2981,7 @@ return { text = { "Sell this card", "to {C:attention}multiply{} values", - "of owned jokers by {C:attention}X#1#{}", + "of owned Jokers by {C:attention}X#1#{}", }, }, j_cry_unity = { @@ -2823,7 +3126,7 @@ return { unlock = { "Win a run with", "your final hand being", - "a {E:1,C:attention}Clusterfuck", + "a {E:1,C:attention}#1#", }, }, j_cry_zooble = { @@ -2838,6 +3141,101 @@ return { }, }, Planet = { + c_cry_asteroidbelt = { + name = "Asteroid Belt", + text = { + "{S:0.8}({S:0.8,V:1}lvl.#1#{S:0.8}){} Level up", + "{C:attention}#2#", + "{C:mult}+#3#{} Mult and", + "{C:chips}+#4#{} chip#4#", + }, + }, + c_cry_void = { + name = "Void", + text = { + "{S:0.8}({S:0.8,V:1}lvl.#1#{S:0.8}){} Level up", + "{C:attention}#2#", + "{C:mult}+#3#{} Mult and", + "{C:chips}+#4#{} chip#4#", + }, + }, + c_cry_marsmoons = { + name = "Phobos & Deimos", + text = { + "{S:0.8}({S:0.8,V:1}lvl.#1#{S:0.8}){} Level up", + "{C:attention}#2#", + "{C:mult}+#3#{} Mult and", + "{C:chips}+#4#{} chip#4#", + }, + }, + c_cry_nibiru = { + name = "Nibiru", + text = { + "{S:0.8}({S:0.8,V:1}lvl.#1#{S:0.8}){} Level up", + "{C:attention}#2#", + "{C:mult}+#3#{} Mult and", + "{C:chips}+#4#{} chip#4#", + }, + }, + c_cry_universe = { + name = Cryptid_config.family_mode and "Universe" or "The Universe In Its Fucking Entirety", + text = { + "{S:0.8}({S:0.8,V:1}lvl.#1#{S:0.8}){} Level up", + "{C:attention}#2#", + "{C:mult}+#3#{} Mult and", + "{C:chips}+#4#{} chip#4#", + }, + }, + c_cry_planetlua = { + name = "Planet.lua", + text = { + "{C:green}#1# in #2#{} chance to", + "upgrade every", + "{C:legendary,E:1}poker hand{}", + "by {C:attention}1{} level", + }, + }, + c_cry_nstar = { + name = "Neutron Star", + text = { + "Upgrade a random", + "poker hand by", + "{C:attention}1{} level for each", + "{C:attention}Neutron Star{} used", + "in this run", + "{C:inactive}(Currently{C:attention} #1#{C:inactive}){}", + }, + }, + c_cry_sunplanet = { + name = "Sol", + text = { + "{S:0.8}({S:0.8,V:1}lvl.#1#{S:0.8}){}", + "Increase Ascension Factor of", + "{C:attention}Ascended{} hands by {X:gold,C:white}#2#{}", + "{C:inactive}(Currently {X:gold,C:white}X#3#{C:inactive} {C:chips}C{}+{C:mult}M{C:inactive} Multiplier", + "{C:inactive}Per {C:attention}1{C:inactive} Ascension power)", + }, + }, + c_cry_sunplanet2 = { + name = "Sol", + text = { + "{S:0.8}({S:0.8,V:1}lvl.#1#{S:0.8}){}", + "Increase Ascension Factor of", + "{C:attention}Ascended{} hands by {X:gold,C:white}#2#{}", + "{C:inactive}(Currently {X:gold,C:white}+#3#{C:inactive} {C:chips}C{}+{C:mult}M{C:inactive} Multiplier", + "{C:inactive}Per {C:attention}1{C:inactive} Ascension power)", + }, + }, + c_cry_Timantii = { + name = "Ruutu", + text = { + "({V:1}lvl.#4#{})({V:2}lvl.#5#{})({V:3}lvl.#6#{})", + "Level up", + "{C:attention}#1#{},", + "{C:attention}#2#{},", + "and {C:attention}#3#{}", + }, + }, c_cry_Klubi = { name = "Risti", text = { @@ -2848,6 +3246,16 @@ return { "and {C:attention}#3#{}", }, }, + c_cry_Sydan = { + name = "Hertta", + text = { + "({V:1}lvl.#4#{})({V:2}lvl.#5#{})({V:3}lvl.#6#{})", + "Level up", + "{C:attention}#1#{},", + "{C:attention}#2#{},", + "and {C:attention}#3#{}", + }, + }, c_cry_Lapio = { name = "Pata", text = { @@ -2868,28 +3276,8 @@ return { "and {C:attention}#3#{}", }, }, - c_cry_nstar = { - name = "Neutron Star", - text = { - "Upgrade a random", - "poker hand by", - "{C:attention}1{} level for each", - "{C:attention}Neutron Star{} used", - "in this run", - "{C:inactive}(Currently{C:attention} #1#{C:inactive}){}", - }, - }, - c_cry_planetlua = { - name = "Planet.lua", - text = { - "{C:green}#1# in #2#{} chance to", - "upgrade every", - "{C:legendary,E:1}poker hand{}", - "by {C:attention}1{} level", - }, - }, - c_cry_Sydan = { - name = "Hertta", + c_cry_voxel = { + name = "Voxel", text = { "({V:1}lvl.#4#{})({V:2}lvl.#5#{})({V:3}lvl.#6#{})", "Level up", @@ -2898,61 +3286,6 @@ return { "and {C:attention}#3#{}", }, }, - c_cry_Timantti = { - name = "Ruutu", - text = { - "({V:1}lvl.#4#{})({V:2}lvl.#5#{})({V:3}lvl.#6#{})", - "Level up", - "{C:attention}#1#{},", - "{C:attention}#2#{},", - "and {C:attention}#3#{}", - }, - }, - c_cry_marsmoons = { - name = "Phobos & Deimos", - text = { - "{S:0.8}({S:0.8,V:1}lvl.#1#{S:0.8}){} Level up", - "{C:attention}#2#", - "{C:mult}+#3#{} Mult and", - "{C:chips}+#4#{} chip#4#", - }, - }, - c_cry_void = { - name = "Void", - text = { - "{S:0.8}({S:0.8,V:1}lvl.#1#{S:0.8}){} Level up", - "{C:attention}#2#", - "{C:mult}+#3#{} Mult and", - "{C:chips}+#4#{} chip#4#", - }, - }, - c_cry_asteroidbelt = { - name = "Asteroid Belt", - text = { - "{S:0.8}({S:0.8,V:1}lvl.#1#{S:0.8}){} Level up", - "{C:attention}#2#", - "{C:mult}+#3#{} Mult and", - "{C:chips}+#4#{} chip#4#", - }, - }, - c_cry_universe = { - name = Cryptid_config.family_mode and "Universe" or "The Universe In Its Fucking Entirety", - text = { - "{S:0.8}({S:0.8,V:1}lvl.#1#{S:0.8}){} Level up", - "{C:attention}#2#", - "{C:mult}+#3#{} Mult and", - "{C:chips}+#4#{} chip#4#", - }, - }, - c_cry_sunplanet = { - name = "Sol", - text = { - "{S:0.8}({S:0.8,V:1}lvl.#1#{S:0.8}){}", - "Increase power of", - "{C:attention}Ascended{} hands by {X:gold,C:white}#2#{}", - "{C:inactive}(Currently {X:gold,C:white}X(#3#^asc){C:inactive})", - }, - }, }, Sleeve = { sleeve_cry_beige_sleeve = { @@ -3101,6 +3434,16 @@ return { "{C:red}WIP", }, }, + sleeve_cry_antimatter_sleeve_balanced = { + name = "Antimatter Sleeve", + text = { + "applies the {C:attention}effects{}", + "and {C:attention}special effects{}", + "of {C:attention}every{} sleeve won", + "with {C:gold}Gold Stake{}", + "{C:red}WIP", + }, + }, }, Spectral = { c_cry_adversary = { @@ -3166,7 +3509,7 @@ return { text = { "Create a card", "of {C:cry_code}your choice", - "{C:inactive,s:0.8}(Exotic Jokers #1#excluded)", + "{C:inactive,s:0.8}(Exotic Jokers excluded)", }, }, c_cry_replica = { @@ -3217,6 +3560,14 @@ return { "card#1# in your hand", }, }, + c_cry_meld = { + name = "Meld", + text = { + "Select a {C:attention}Joker{} or", + "{C:attention}playing card{} to", + "become {C:dark_edition}Double-Sided", + }, + }, c_cry_vacuum = { name = "Vacuum", text = { @@ -3640,6 +3991,30 @@ return { "{s:0.8,C:inactive}Copying Tags excluded", }, }, + tag_cry_clone = { + name = "Clone Tag", + text = { + "Shop Items cost {C:attention}X#1#{}", + "as much, obtain a {C:attention}Copy{}", + "of the next bought card", + }, + }, + tag_cry_lens = { + name = "Lens Tag", + text = { + "Apply {C:dark_edition}Negative{}", + "to {C:attention}#1#{} random", + "consumable#1#", + }, + }, + tag_cry_palette_cleanser = { + name = "Palette Cleanser Tag", + text = { + "Remove a {C:attention}random{}", + "sticker from a {C:attention}random{}", + "Joker or playing card", + }, + }, }, Tarot = { c_cry_automaton = { @@ -3657,12 +4032,11 @@ return { "into an {C:attention}Echo Card", }, }, - c_cry_meld = { - name = "Meld", + c_cry_instability = { + name = "Instability", text = { - "Select a {C:attention}Joker{} or", - "{C:attention}playing card{} to", - "become {C:dark_edition}Double-Sided", + "Enhances {C:attention}#1#{} selected card#1#", + "into an {C:attention}Abstract Card", }, }, c_cry_theblessing = { @@ -3677,36 +4051,67 @@ return { name = "The Seraph", text = { "Enhances {C:attention}#1#{} selected card#1#", - "into a {C:attention}Light Card", + "into {C:attention}Light Cards", }, }, }, Voucher = { - v_cry_asteroglyph = { - name = "Asteroglyph", - text = { - "Set Ante to {C:attention}#1#{}", - }, - unlock = { - "Reach Ante {C:attention}36", - }, - }, - v_cry_blankcanvas = { - name = "Blank Canvas", - text = { - "{C:attention}+#1#{} hand size", - }, - unlock = { - "Reduce your {C:attention}handsize", - "to {C:attention}0", - }, - }, - v_cry_clone_machine = { - name = "Clone Machine", + -- Standard Vouchers + v_cry_copies = { + name = "Copies", text = { "Double Tags become", - "{C:attention}Quintuple Tags{} and", - "are {C:attention}4X{} as common", + "{C:attention}Triple Tags{} and are", + "{C:attention}2X{} as common", + }, + }, + v_cry_tag_printer = { + name = "Tag Printer", + text = { + "Double Tags become", + "{C:attention}Quadruple Tags{} and", + "are {C:attention}3X{} as common", + }, + }, + v_cry_pairing = { + name = "Pairing", + text = { + "{C:attention}Retrigger{} all M Jokers", + "if played hand is a {C:attention}Pair", + }, + }, + v_cry_repair_man = { + name = "Repair Man", + text = { + "{C:attention}Retrigger{} all M Jokers", + "if played hand contains a {C:attention}Pair", + }, + }, + v_cry_double_vision = { + name = "Double Vision", + text = { + "{C:dark_edition}Double-Sided{} cards appear", + "{C:attention}4X{} more frequently", + }, + }, + v_cry_double_slit = { + name = "Double Slit", + text = { + "{C:attention}Meld{} can appear", + "in {C:spectral}Spectral{} Packs", + }, + }, + v_cry_stickyhand = { + name = "Sticky Hand", + text = { + "{C:attention}+#1#{} card selection limit", + }, + }, + v_cry_grapplinghook = { + name = "Grappling Hook", + text = { + "{C:attention}+#1#{} card selection limit", + "{C:inactive,s:0.7}You can do a lot more with this than you think.{}", }, }, v_cry_command_prompt = { @@ -3717,98 +4122,16 @@ return { "in the {C:attention}shop{}", }, }, - v_cry_copies = { - name = "Copies", + v_cry_satellite_uplink = { + name = "Satellite Uplink", text = { - "Double Tags become", - "{C:attention}Triple Tags{} and are", - "{C:attention}2X{} as common", - }, - }, - v_cry_curate = { - name = "Curate", - text = { - "All cards", - "appear with", - "an {C:dark_edition}Edition{}", - }, - unlock = { - "Discover", - "all {C:attention}Editions", - }, - }, - v_cry_dexterity = { - name = "Dexterity", - text = { - "Permanently", - "gain {C:blue}+#1#{} hand#1#", - "each round", - }, - unlock = { - "Play {C:attention}5000{}", - "{C:attention}Playing Cards{}", - "in total", - }, - }, - v_cry_double_down = { - name = "Double Down", - text = { - "After every round,", - "{X:dark_edition,C:white} X1.5 {} to all values", - "on the back of", - "{C:dark_edition}Double-Sided{} cards", - }, - }, - v_cry_double_slit = { - name = "Double Slit", - text = { - "{C:attention}Meld{} can appear", - "in the shop and", - "Arcana Packs", - }, - }, - v_cry_double_vision = { - name = "Double Vision", - text = { - "{C:dark_edition}Double-Sided{} cards appear", - "{C:attention}4X{} more frequently", - }, - }, - v_cry_fabric = { - name = "Universal Fabric", - text = { - "{C:dark_edition}+#1#{} Joker slot#1#", - }, - unlock = { - "Redeem {C:dark_edition}Antimatter", - "{C:attention}10{} times", - }, - }, - v_cry_massproduct = { - name = "Mass Production", - text = { - "All cards and packs", - "in shop cost {C:attention}$1{}", - }, - unlock = { - "Redeem {C:attention}25", - "{C:attention}Vouchers", - "in one run", - }, - }, - v_cry_moneybean = { - name = "Money Beanstalk", - text = { - "Raise the cap on", - "interest earned in", - "each round to {C:money}$#1#{}", - }, - unlock = { - "Max out the", - "{C:attention}interest earnings{}", - "for the {C:attention}whole run", + "{C:cry_code}Code{} cards may", + "appear in any of", + "the {C:attention}Celestial Packs{}", }, }, + + -- T3 Vouchers v_cry_overstock_multi = { name = "Multistock", text = { @@ -3823,49 +4146,28 @@ return { "in one run", }, }, - v_cry_pacclimator = { - name = "Planet Acclimator", + v_cry_massproduct = { + name = "Mass Production", text = { - "{C:planet}Planet{} cards appear", - "{C:attention}X#1#{} more frequently", - "in the shop", - "Allows control of the", - "shop's {C:planet}Planet Rate{}", - "{C:inactive}(Check {C:attention}Run Info{C:inactive})", + "All cards and packs", + "in shop cost {C:attention}$1{}", }, unlock = { - "Buy {C:attention}100{} {C:planet}Planet", - "cards total in", - "the shop", + "Redeem {C:attention}25", + "{C:attention}Vouchers", + "in one run", }, }, - v_cry_pairamount_plus = { - name = "Pairamount Plus", + v_cry_curate = { + name = "Curate", text = { - "{C:attention}Retrigger{} all M Jokers", - "once for every Pair", - "{C:attention}contained{} in played hand", + "All cards", + "appear with", + "an {C:dark_edition}Edition{}", }, - }, - v_cry_pairing = { - name = "Pairing", - text = { - "{C:attention}Retrigger{} all M Jokers", - "if played hand is a {C:attention}Pair", - }, - }, - v_cry_quantum_computing = { - name = "Quantum Computing", - text = { - "{C:cry_code}Code{} cards can spawn", - "with {C:dark_edition}Negative{} edition", - }, - }, - v_cry_repair_man = { - name = "Repair Man", - text = { - "{C:attention}Retrigger{} all M Jokers", - "if played hand contains a {C:attention}Pair", + unlock = { + "Discover", + "all {C:attention}Editions", }, }, v_cry_rerollexchange = { @@ -3881,27 +4183,47 @@ return { "in one run", }, }, - v_cry_satellite_uplink = { - name = "Satellite Uplink", + -- RESERVATION FOR CRYSTAL BALL T3 + -- RESERVATION FOR TELESCOPE T3 + -- v_cry_scope = { + -- name = "Galactic Scope", + -- text = { + -- "Create the {C:planet}Planet", + -- "card for played", + -- "{C:attention}poker hand{}", + -- "{C:inactive}(Must have room){}", + -- }, + -- unlock = { + -- "Use {C:attention}50{} {C:planet}Planet", + -- "cards from", + -- "{C:attention}Booster Packs{}", + -- "in one run", + -- }, + -- }, + v_cry_dexterity = { + name = "Dexterity", text = { - "{C:cry_code}Code{} cards may", - "appear in any of", - "the {C:attention}Celestial Packs{}", - }, - }, - v_cry_scope = { - name = "Galactic Scope", - text = { - "Create the {C:planet}Planet", - "card for played", - "{C:attention}poker hand{}", - "{C:inactive}(Must have room){}", + "Permanently", + "gain {C:blue}+#1#{} hand#1#", + "each round", }, unlock = { - "Use {C:attention}50{} {C:planet}Planet", - "cards from", - "{C:attention}Booster Packs{}", - "in one run", + "Play {C:attention}5000{}", + "{C:attention}Playing Cards{}", + "in total", + }, + }, + v_cry_threers = { + name = "The 3 Rs", + text = { + "Permanently", + "gain {C:red}+#1#{} discard#1#", + "each round", + }, + unlock = { + "Discard {C:attention}5000{}", + "{C:attention}Playing Cards{}", + "in total", }, }, v_cry_tacclimator = { @@ -3920,38 +4242,90 @@ return { "the shop", }, }, - v_cry_tag_printer = { - name = "Tag Printer", + v_cry_pacclimator = { + name = "Planet Acclimator", text = { - "Double Tags become", - "{C:attention}Quadruple Tags{} and", - "are {C:attention}3X{} as common", - }, - }, - v_cry_threers = { - name = "The 3 Rs", - text = { - "Permanently", - "gain {C:red}+#1#{} discard#1#", - "each round", + "{C:planet}Planet{} cards appear", + "{C:attention}X#1#{} more frequently", + "in the shop", + "Allows control of the", + "shop's {C:planet}Planet Rate{}", + "{C:inactive}(Check {C:attention}Run Info{C:inactive})", }, unlock = { - "Discard {C:attention}5000{}", - "{C:attention}Playing Cards{}", - "in total", + "Buy {C:attention}100{} {C:planet}Planet", + "cards total in", + "the shop", }, }, - v_cry_stickyhand = { - name = "Sticky Hand", + v_cry_moneybean = { + name = "Money Beanstalk", text = { - "{C:attention}+#1#{} card selection limit", + "Raise the cap on", + "interest earned in", + "each round to {C:money}$#1#{}", + }, + unlock = { + "Max out the", + "{C:attention}interest earnings{}", + "for the {C:attention}whole run", }, }, - v_cry_grapplinghook = { - name = "Grappling Hook", + v_cry_fabric = { + name = "Universal Fabric", text = { - "{C:attention}+#1#{} card selection limit", - "{C:inactive,s:0.7}You can do a lot more with this than you think.{}", + "{C:dark_edition}+#1#{} Joker slot#1#", + }, + unlock = { + "Redeem {C:dark_edition}Antimatter", + "{C:attention}10{} times", + }, + }, + -- RESERVATION FOR MAGIC TRICK T3 + v_cry_asteroglyph = { + name = "Asteroglyph", + text = { + "Set Ante to {C:attention}#1#{}", + }, + unlock = { + "Reach Ante {C:attention}36", + }, + }, + -- RESERVATION FOR DIRECTOR'S CUT T3 + v_cry_blankcanvas = { + name = "Blank Canvas", + text = { + "{C:attention}+#1#{} hand size", + }, + unlock = { + "Reduce your {C:attention}handsize", + "to {C:attention}0", + }, + }, + -- Cryptid Voucher T3 + v_cry_clone_machine = { + name = "Clone Machine", + text = { + "Double Tags become", + "{C:attention}Quintuple Tags{} and", + "are {C:attention}4X{} as common", + }, + }, + v_cry_pairamount_plus = { + name = "Pairamount Plus", + text = { + "{C:attention}Retrigger{} all M Jokers", + "once for every Pair", + "{C:attention}contained{} in played hand", + }, + }, + v_cry_double_down = { + name = "Double Down", + text = { + "After every round,", + "{X:dark_edition,C:white} X1.5 {} to all values", + "on the back of", + "{C:dark_edition}Double-Sided{} cards", }, }, v_cry_hyperspacetether = { @@ -3962,8 +4336,40 @@ return { "to {C:attention}Ascended Hands{}", }, }, + v_cry_quantum_computing = { + name = "Quantum Computing", + text = { + "All future {C:cry_code}Code{} cards each", + "have {C:cry_code}+#1#{} Multiuse", + }, + }, }, Other = { + alt_wheel_of_fortune = { + name = "The Wheel of Fortune", + text = { + "{C:green}#1# in #2#{} chance to add", + "{C:dark_edition}Foil{}, {C:dark_edition}Holographic{}, or", + "{C:dark_edition}Polychrome{} edition", + "to a random {C:attention}Joker", + }, + }, + asc_misc = { + name = "Ascended hand information", + text = { + "{C:gold}#1#{} Ascension power", + "{X:gold,C:white}X#2#{C:chips} Chips{} and {C:mult}Mult", + "{C:inactive}({C:gold}#3#{C:inactive} ^ {C:gold}#1#{C:inactive})", + }, + }, + asc_misc2 = { + name = "Ascended hand information", + text = { + "{C:gold}#1#{} Ascension power", + "{X:gold,C:white}X#2#{C:chips} Chips{} and {C:mult}Mult", + "{C:inactive}({C:gold}#3#{C:inactive} X {C:gold}#1#{C:inactive})", + }, + }, disabled = { name = "Disabled", text = { @@ -4018,6 +4424,16 @@ return { text = { "When this Joker is {C:cry_code}triggered{},", "trigger {C:cry_code}#1#", + "{C:inactive}Not all cards can be triggered this way{}", + "{C:inactive}but all Jokers can trigger the other{}", + }, + }, + cry_global_sticker = { + name = "Global", + text = { + "Draw this card", + "{C:cry_code}Before other cards{},", + "if possible", }, }, cry_flickering = { @@ -4035,6 +4451,21 @@ return { "{C:attention}#1#{} trigger#1#", }, }, + cry_function_sticker = { + name = "Function://", + text = { + "Creates {C:cry_code}#1#{}", + "when used", + }, + }, + cry_function_sticker_desc = { --for function:// card + name = "Function://", + text = { + "Creates the next", + "{C:cry_code}Function://{} consumable", + "{C:inactive}Currently #1#, #2# and #3#{}", + }, + }, cry_possessed = { name = "Possessed", text = { @@ -4240,6 +4671,7 @@ return { "unredeemed each round", }, }, + -- TODO fix typo cry_perishable_consumeable = { name = "Perishable", text = { @@ -4268,6 +4700,27 @@ return { "nothing on use", }, }, + o_nstar = { + name = "Observatory Effect", + text = { + "{X:mult,C:white}X#1#{} Mult for each", + "{C:attention}Neutron Star{} used", + "in this run", + "{C:inactive}(Currently {X:mult,C:white}X#2#{C:inactive} Mult)", + }, + }, + o_planetlua = { + name = "Observatory Effect", + text = { "" }, + }, + o_sunplanet = { + name = "Observatory Effect", + text = { + "Held {C:attention}Sol{} Cards increase", + "{C:attention}Ascension power", + "{C:inactive}(Currently {X:gold,C:white}+#1#{C:inactive})", + }, + }, p_cry_code_normal_1 = { name = "Program Pack", text = { @@ -4325,6 +4778,15 @@ return { "up to {C:attention}#2# Meme Joker#2#{}", }, }, + p_cry_baneful_1 = { + name = "Baneful Buffoon Pack", + text = { + "Choose {C:attention}#1#{} of", + "up to {C:attention}#2# {X:cry_cursed,C:white}Cursed{} Joker#2#{}", + "{C:attention}Skipping{} will {C:red}banish{}", + "{C:attention}rightmost{} owned Joker", + }, + }, undiscovered_code = { name = "Not Discovered", text = { @@ -4366,6 +4828,12 @@ return { '{C:inactive,s:0.8}"I hate this card" - SDM_0, 2024{}', }, }, + cry_multiuse = { + name = "m", + text = { + "{C:inactive}Multiuse: ({C:cry_code}#1#{C:inactive} remaining)", + }, + }, }, Unique = { c_cry_potion = { @@ -4451,6 +4919,7 @@ return { ["cry_UltPair"] = "Ultimate Pair", ["cry_WholeDeck"] = Cryptid_config.family_mode and "The Entire Deck" or "The Entire Fucking Deck", ["cry-Cluster Bulwark"] = "Clusterwark", + ["cry_None"] = "None", }, poker_hand_descriptions = { ["cry_Bulwark"] = { @@ -4470,6 +4939,15 @@ return { "card found in a 52-card deck.", "Are you insane?", }, + ["cry_None"] = { "A hand containing 0 cards" }, + + ["cry_Declare0"] = { "Always counts as a Straight" }, + ["cry_Declare1"] = { "Always counts as a Flush" }, + ["cry_Declare2"] = { "Always counts as a Full House" }, + + ["cry_Declare0_suitless"] = { "Always counts as a Straight", "Hand does not need specific suits" }, + ["cry_Declare1_suitless"] = { "Always counts as a Flush", "Hand does not need specific suits" }, + ["cry_Declare2_suitless"] = { "Always counts as a Full House", "Hand does not need specific suits" }, }, achievement_names = { ach_cry_ace_in_crash = "Pocket ACE", @@ -4493,8 +4971,13 @@ return { ach_cry_used_crash = "We Told You Not To", ach_cry_what_have_you_done = "WHAT HAVE YOU DONE?!", ach_cry_pin = "Pin of Shame", + ach_cry_technically_positive = "Technically Positive", ach_cry_youre_fucking_kidding = Cryptid_config.family_mode and "You Can't Be Serious" or "You're Fucking Kidding", + ach_cry_stoned = "Stoned", + ach_cry_fucked = Cryptid_config.family_mode and "Clustered" or "Fucked", + ach_cry_despaired = "Despaired", + ach_cry_decked = "Decked", }, achievement_descriptions = { ach_cry_ace_in_crash = 'check_for_unlock({type = "ace_in_crash"})', @@ -4518,7 +5001,12 @@ return { ach_cry_used_crash = "Use ://CRASH", ach_cry_what_have_you_done = "Delete or Sacrifice an Exotic Joker", ach_cry_pin = "Lose a run to The Pin", + ach_cry_technically_positive = "Obtain a Negative Negative Joker", ach_cry_youre_fucking_kidding = "Discard " .. localize("cry_WholeDeck", "poker_hands"), + ach_cry_stoned = "Get " .. localize("cry_Bulwark", "poker_hands") .. " to level 420", + ach_cry_fucked = "Get " .. localize("cry_Clusterfuck", "poker_hands") .. " to level 69", + ach_cry_stoned = "Get " .. localize("cry_UltPair", "poker_hands") .. " to level 2222", + ach_cry_stoned = "Get " .. localize("cry_WholeDeck", "poker_hands") .. " to level 5252", }, challenge_names = { c_cry_ballin = "Ballin'", @@ -4572,6 +5060,8 @@ return { k_cry_program_pack = "Program Pack", k_cry_meme_pack = "Meme Pack", + k_cry_baneful_pack = "Baneful Buffoon Pack", + cry_baneful_warning = "Skipping will Banish rightmost Joker", cry_critical_hit_ex = "Critical Hit!", cry_critical_miss_ex = "Critical Miss!", @@ -4586,16 +5076,19 @@ return { cry_debuff_oldflint = "No Flushes", cry_debuff_oldmark = "No hands containing a Pair", cry_debuff_obsidian_orb = "Applies abilities of all defeated bosses", + cry_blind_baneful_pack = "After round, open a Baneful Buffoon Pack", cry_tax_placeholder = "(X0.4 blind requirement)", cry_joke_placeholder = "(multiple of 8)", k_code = "Code", + k_chips = "Chips", k_content_set = "Thematic Set", b_content_sets = "Thematic Sets", --Why aren't these in vanilla? b_tag = "Tag", b_blind = "Blind", + rush_hour_reminder = "Enable the Clock and Lavender loop to play Rush Hour", b_tarot_rate = "Tarot Rate", b_planet_rate = "Planet Rate", @@ -4604,6 +5097,7 @@ return { b_code_cards = "Code Cards", b_unique_cards = "Unique Cards", b_pull = "PULL", + b_playing_cards = "Playing Cards", cry_hooked_ex = "Hooked!", k_end_blind = "End Blind", k_cry_shiny = "Shiny", @@ -4620,9 +5114,19 @@ return { cry_code_create_previous = "CREATE PREVIOUS", cry_code_execute = "EXECUTE", cry_code_cancel = "CANCEL", + cry_code_enter_hand = "ENTER POKER HAND NAME", + cry_code_with_suits = "INCLUDE SUITS", + cry_code_without_suits = "IGNORE SUITS", + cry_code_suitless = "Hand does not require specific suits", + cry_code_empty = "[Declare Hand]", + cry_code_exit = "EXIT", + cry_code_antevoucher = "Next Boss Blind and Voucher", + cry_code_nextjokers = "Next Shop Jokers", + cry_code_nextcards = "Next Drawn Cards", b_flip = "FLIP", b_merge = "MERGE", + b_store = "STORE", cry_hand_bulwark = "Bulwark", cry_hand_clusterfuck = "Clusterfuck", @@ -4634,6 +5138,7 @@ return { cry_again_q = "Again?", cry_curse = "Curse", cry_curse_ex = "Curse!", + cry_demicolon = "Demitrigger!", cry_sobbing = "Help me...", cry_gaming = "Gaming", cry_gaming_ex = "Gaming!", @@ -4652,6 +5157,8 @@ return { cry_unredeemed = "Unredeemed...", cry_active = "Active", cry_inactive = "Inactive", + cry_divorced = "Divorced!", + cry_destroyed_ex = "Destroyed!", k_disable_music = "Disable Music", @@ -4659,9 +5166,13 @@ return { k_cry_exotic = "Exotic", k_cry_candy = "Candy", k_cry_cursed = "Cursed", + + k_downgraded_ex = "Downgraded!", + k_planet_disc = "Circumstellar Disc", k_planet_satellite = "Natural Satellites", k_planet_universe = Cryptid_config.family_mode and "Universe" or "The Actual Fucking Universe", + k_planet_nibiru = "Nothing", cry_notif_jimball_1 = "Jimball", cry_notif_jimball_2 = "Copyright Notice", @@ -4691,6 +5202,8 @@ return { b_reset_gameset_modest = "Reset Gameset Config (Modest)", b_reset_gameset_mainline = "Reset Gameset Config (Mainline)", b_reset_gameset_madness = "Reset Gameset Config (Madness)", + + cry_circus_generic = "{V:#1#}#2#{} Jokers each give {X:mult,C:white} X#3# {} Mult", }, labels = { food_jokers = "Food Jokers", @@ -4701,6 +5214,7 @@ return { unique = "Unique", cry_rigged = "Rigged", cry_hooked = "Hooked", + cry_global_sticker = "Global", cry_flickering = "Flickering", cry_possessed = "Possessed", @@ -4827,7 +5341,7 @@ return { "to win on #2##1#", "#2#Stake#3# difficulty", }, - + tax_hand = { "Max #1#% of required chips" }, cry_art = { "Art: #1#" }, cry_code = { "Code: #1#" }, cry_idea = { "Idea: #1#" }, diff --git a/Cryptid/localization/es_419.lua b/Cryptid/localization/es_419.lua index 60150a8..35ac244 100644 --- a/Cryptid/localization/es_419.lua +++ b/Cryptid/localization/es_419.lua @@ -52,8 +52,8 @@ return { name = "Baraja crítica", text = { "Después de cada mano jugada,", - "{C:green}#1# en 4{} probabilidades para {X:dark_edition,C:white} ^2 {} multi", - "{C:green}#1# en 8{} probabilidades para {X:dark_edition,C:white} ^0.5 {} multi", + "{C:green}#1# en #2#{} probabilidades para {X:dark_edition,C:white} ^2 {} multi", + "{C:green}#1# en #3#{} probabilidades para {X:dark_edition,C:white} ^0.5 {} multi", }, }, b_cry_encoded = { @@ -136,7 +136,7 @@ return { name = "Baraja legendaria", text = { "Comienza con un comodín {C:legendary}legendario{C:legendary}", - "{C:green}1 en 5{} probabilidades para crear otro", + "{C:green}#1# en #2#{} probabilidades para crear otro", "cuando se derrota a la ciega jefe", "{C:inactive}(debe haber espacio){}", }, @@ -1427,7 +1427,7 @@ return { "{C:attention}primer descarte{} de cada ronda", }, }, - j_cry_Megg = { + j_cry_megg = { name = "Muevo", text = { "Vende esta carta para crear", @@ -1449,7 +1449,7 @@ return { "{X:mult,C:white}X#1#{} multi por cada miembro", "en el {C:attention}Discord de Cryptid{}", "{C:inactive}(Actual: {X:mult,C:white}X#2#{C:inactive} multi)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_membershipcardtwo = { @@ -1458,7 +1458,7 @@ return { "{C:chips}+#1#{} fichas por cada miembro", "en el {C:attention}Discord de Cryptid{}", "{C:inactive}(Actual: {C:chips}+#2#{C:inactive} fichas)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_meteor = { @@ -2406,6 +2406,14 @@ return { "gana {C:attention}2{} vales aleatorios", }, }, + c_cry_meld = { + name = "Fusionar", + text = { + "Selecciona un {C:attention}comodín{} o", + "{C:attention}carta de juego{} para", + "hacerla {C:dark_edition}Doble cara", + }, + }, c_cry_typhoon = { name = "Tifón", text = { @@ -2848,14 +2856,7 @@ return { "una {C:attention}Carta de eco", }, }, - c_cry_meld = { - name = "Fusionar", - text = { - "Selecciona un {C:attention}comodín{} o", - "{C:attention}carta de juego{} para", - "hacerla {C:dark_edition}Doble cara", - }, - }, + c_cry_theblessing = { name = "La bendición", text = { @@ -3084,6 +3085,15 @@ return { }, }, Other = { + alt_wheel_of_fortune = { + name = "La rueda de la fortuna", + text = { + "{C:green}#1# en #2#{} probabilidades de agregar", + "que sean {C:dark_edition}laminadas{}, {C:dark_edition}holográficas{} o", + "{C:dark_edition}polícromas{}", + "a un {C:attention}comodín al azar", + }, + }, banana = { name = "Banana", text = { @@ -3563,6 +3573,7 @@ return { cry_debuff_obsidian_orb = "Aplica las habilidades de todos los jefes derrotados", k_code = "Código", + k_chips = "fichas", k_unique = "Único", b_code_cards = "Cartas de código", b_unique_cards = "Cartas únicas", diff --git a/Cryptid/localization/es_ES.lua b/Cryptid/localization/es_ES.lua index 919d33b..9001069 100644 --- a/Cryptid/localization/es_ES.lua +++ b/Cryptid/localization/es_ES.lua @@ -65,8 +65,8 @@ return { name = "Baraja crítica", text = { "Después de cada mano jugada,", - "{C:green}#1# en 4{} probabilidades para {X:dark_edition,C:white} ^2 {} multi", - "{C:green}#1# en 8{} probabilidades para {X:dark_edition,C:white} ^0.5 {} multi", + "{C:green}#1# en #2#{} probabilidades para {X:dark_edition,C:white} ^2 {} multi", + "{C:green}#1# en #3#{} probabilidades para {X:dark_edition,C:white} ^0.5 {} multi", }, }, b_cry_e_deck = { @@ -188,7 +188,7 @@ return { name = "Baraja legendaria", text = { "Comienza con un comodín {C:legendary}legendario{C:legendary}", - "{C:green}1 en 5{} probabilidades para crear otro", + "{C:green}#1# en #2#{} probabilidades para crear otro", "cuando se derrota a la ciega jefe", "{C:inactive}(debe haber espacio){}", }, @@ -406,7 +406,7 @@ return { }, }, c_cry_crash = { - name = "://CHOQUE", + name = "://CRASH", text = { "{C:cry_code,E:1}No.", }, @@ -651,7 +651,7 @@ return { set_cry_poker_hand_stuff = { name = "Manos de póker", text = { - "Añade 4 {C:attention}manos de póker{} nuevas", + "Añade 5 {C:attention}manos de póker{} nuevas", "y habilita {C:attention}Manos ascendidas", }, }, @@ -800,6 +800,16 @@ return { "{C:inactive}(Actual: {X:mult,C:white}X#2#{C:inactive} multi)", }, }, + m_cry_abstract = { + name = "Carta abstracta", + text = { + "{X:dark_edition,C:white}^#1#{} multi,", + "Cuenta como su {C:attention}propio{} rango y palo", + "Chance de {C:green}#4# en #5#{} de que", + "{C:red,E:2}se destruya{} la carta al tenerla en la mano al", + "{C:attention}final de la ronda{} o al {C:attention}jugar una mano{}", + }, + }, }, Joker = { j_cry_test_modest = { @@ -925,6 +935,15 @@ return { "{C:inactive,s:0.8}La categoría no cambia", }, }, + j_cry_highfive = { + name = "Choca esos cinco", + text = { + "Si la carta {C:attention}puntuada más alta{}", + "es {C:attention}5{}, convierte {C:attention}todas{} las cartas que puntúan", + "en {C:attention}5{}s", + "{s:0.8,C:inactive}Se considera a los Aces como 1", + }, + }, j_cry_blender = { name = "Blender", text = { @@ -1149,6 +1168,18 @@ return { "una {E:1,C:attention}Pareja suprema", }, }, + j_cry_the = { + name = "El", + text = { + "{X:mult,C:white} X#1# {} multi si la mano", + "jugada es {C:attention}#2#", + }, + unlock = { + "Gana una partida con", + "tu última mano siendo", + "una {E:1,C:attention}None", --queda None por traducir, revisar el discord si alguien lo solucionó + }, + }, j_cry_clicked_cookie = { name = "Galleta clickeada", text = { @@ -1301,6 +1332,21 @@ return { "de su respectivo {C:attention}tipo{}", }, }, + j_cry_starfruit = { + name = "Carambola", + text = { + "{X:dark_edition,C:white}^#1#{} multi,", + "pierde {X:dark_edition,C:white}^#2#{} multi por cada", + "{C:attention}renovación{} en la tienda", + }, + }, + j_cry_demicolon = { + name = "Demicolon", + text = { + "{C:attention}Activa por la fuerza{} al Comodín", + "a la derecha", + }, + }, j_cry_discreet = { name = "Comodín discreto", text = { @@ -1462,6 +1508,15 @@ return { "{C:attention}#2#{} o menos veces", }, }, + j_cry_familiar_currency = { + name = "Moneda familiar", + text = { + "Crea un {C:attention}comodín meme{}", + "al final de la ronda", + "por {C:money}$#1#{} {C:inactive}(si es posible)", + "{C:inactive}(Debe haber espacio)", + }, + }, j_cry_filler = { name = "El relleno", text = { @@ -1514,6 +1569,13 @@ return { "un {C:attention}#2#", }, }, + j_cry_undefined = { + name = "Comodín indefinido", + text = { + "{C:red}+#1#{} multi si la mano", + "jugada es {C:attention}#2#", + }, + }, j_cry_formidiulosus = { name = "Formidiulosus", text = { @@ -1618,7 +1680,7 @@ return { "{X:dark_edition,C:white}^#1#{} multi sólo después de", "jugar {C:attention}114{} manos{}", "{C:inactive}(Actual: #2#/114){}", - "{C:inactive,s:0.8}¡No hay un lugar como el hugar!{}", + "{C:inactive,s:0.8}¡No hay lugar como el hogar!{}", }, }, j_cry_home = { @@ -1644,7 +1706,7 @@ return { j_cry_huntingseason = { name = "Época de caza", text = { - "Si la mano jugada contiene exactalemte {C:attention}3{} cartas,", + "Si la mano jugada contiene exactamente {C:attention}3{} cartas,", "{C:red}destruye{} la carta {C:attention}central{} después de puntuar", }, }, @@ -1658,7 +1720,7 @@ return { }, }, j_cry_jawbreaker = { - name = "Jawbreaker", + name = "Rompemuelas", text = { "Al derrotar la {C:attention}ciega jefe,", "{C:attention}duplica{} los valores de los comodines adyacentes", @@ -1708,6 +1770,14 @@ return { "o {C:attention}tipo fichas{} es vendido", }, }, + j_cry_kittyprinter = { + name = "Impresora de gatitos", + text = { + "{X:mult,C:white} X#1# {} multi", + "Todas las etiquetas {C:attention}salteadas{}", + "se vuelven {C:attention}etiquetas de gato{}", + }, + }, j_cry_kooky = { name = "Comodín raro", text = { @@ -1769,7 +1839,7 @@ return { "{C:attention}Reactiva{} todos los comodines", "una vez por cada {C:attention}comodín{}", "{C:attention}contento{} vendido esta ronda", - "{C:inactive}(Actual:{}{C:attention:} #1#{}{C:inactive} reactivaci#2#){}", + "{C:inactive}(Actual:{}{C:attention:} #1#{}{C:inactive} reactivaci#1#){}", "{C:inactive,s:0.8}No había suficiente espacio...{}", }, }, @@ -1868,7 +1938,7 @@ return { "{C:attention}primer descarte{} de cada ronda", }, }, - j_cry_Megg = { + j_cry_megg = { name = "Muevo", text = { "Vende esta carta para crear", @@ -1890,8 +1960,7 @@ return { "{X:mult,C:white}X#1#{} multi por cada miembro", "en el {C:attention}Discord de Cryptid{}", "{C:inactive}(Actual: {X:mult,C:white}X#2#{C:inactive} multi)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_membershipcardtwo = { @@ -1900,7 +1969,7 @@ return { "{C:chips}+#1#{} ficha#1# por cada miembro", "en el {C:attention}Discord de Cryptid{}", "{C:inactive}(Actual: {C:chips}+#2#{C:inactive} fichas)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_membershipcardtwo_balanced = { @@ -1909,7 +1978,7 @@ return { "{C:chips}+#1#{} ficha#1# por cada {C:attention}8{} miembros", "en el {C:attention}Discord de Cryptid{}", "{C:inactive}(Actual: {C:chips}+#2#{C:inactive} fichas)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_meteor = { @@ -2302,7 +2371,7 @@ return { }, }, j_cry_scrabble = { - name = "Teja de Scrabble", + name = "Ficha de Scrabble", text = { "{C:green}#1# en #2#{} probabilidades de crear", "un comodín {C:green}inusual{} {C:dark_edition}contento", @@ -2380,7 +2449,22 @@ return { '{C:inactive,s:0.8}"Esta prisión... para mantenerme...?"', }, }, - + j_cry_sock_and_sock = { + name = "Calcetín y calcetín", + text = { + "Reactiva todas las cartas", + "{C:attention}abstractas{} jugadas {C:attention}#1#{} vez#1#", + }, + }, + j_cry_brokenhome = { + name = "Hogar roto", + text = { + "{X:mult,C:white} X#1# {} multi", + "{C:green}#2# en #3#{} probabilidades", + "de que la carta se destruya", + "al final de la ronda", + }, + }, j_cry_spaceglobe = { name = "Esfera celestial", text = { @@ -2531,6 +2615,13 @@ return { "un {C:attention}#2#", }, }, + j_cry_nebulous = { + name = "Comodín Nebuloso", + text = { + "{C:chips}+#1#{} Chip#1# si la mano", + "jugada es {C:attention}#2#", + }, + }, j_cry_trick_or_treat = { name = "Dulce o truco", text = { @@ -3094,6 +3185,14 @@ return { "de tu mano al azar", }, }, + c_cry_meld = { + name = "Fusionar", + text = { + "Selecciona un {C:attention}comodín{} o", + "{C:attention}carta de juego{} para", + "hacerla {C:dark_edition}Doble cara", + }, + }, c_cry_vacuum = { name = "Vacío", text = { @@ -3536,14 +3635,7 @@ return { "una {C:attention}Carta de eco", }, }, - c_cry_meld = { - name = "Fusionar", - text = { - "Selecciona un {C:attention}comodín{} o", - "{C:attention}carta de juego{} para", - "hacerla {C:dark_edition}Doble cara", - }, - }, + c_cry_theblessing = { name = "La bendición", text = { @@ -3845,6 +3937,15 @@ return { }, }, Other = { + alt_wheel_of_fortune = { + name = "La rueda de la fortuna", + text = { + "{C:green}#1# en #2#{} probabilidades de agregar", + "que sean {C:dark_edition}laminadas{}, {C:dark_edition}holográficas{} o", + "{C:dark_edition}polícromas{}", + "a un {C:attention}comodín al azar", + }, + }, disabled = { name = "Deshabilitado", text = { @@ -4391,7 +4492,7 @@ return { ach_cry_pull_request = "Haz que ://COMMIT haga aparecer el mismo comodín que destruyó", ach_cry_traffic_jam = "Gana todos los desafíos Hora punta", ach_cry_ult_full_skip = "Gana en 1 ronda", - ach_cry_used_crash = "Usa ://CHOQUE", + ach_cry_used_crash = "Usa ://CRASH", ach_cry_what_have_you_done = "Elimina o sacrifica un comodín exótico", ach_cry_pin = "Pierde una partida contra El Alfiler", }, @@ -4465,6 +4566,7 @@ return { cry_joke_placeholder = "(múltiplo of 8)", k_code = "Código", + k_chips = "fichas", k_content_set = "Set temático", b_content_sets = "Sets temáticos", --Why aren't these in vanilla? diff --git a/Cryptid/localization/fr.lua b/Cryptid/localization/fr.lua index b26f86d..d81faa9 100644 --- a/Cryptid/localization/fr.lua +++ b/Cryptid/localization/fr.lua @@ -111,8 +111,8 @@ return { name = "Jeu Critique", text = { "Après chaque main jouée,", - "{C:green}#1# chance#1# sur 4{} d'obtenir {X:dark_edition,C:white} ^2 {} Multi", - "{C:green}#1# chance#1# sur 8{} d'obtenir {X:dark_edition,C:white} ^0.5 {} Multi", + "{C:green}#1# chance#1# sur #2#{} d'obtenir {X:dark_edition,C:white} ^2 {} Multi", + "{C:green}#1# chance#1# sur #3#{} d'obtenir {X:dark_edition,C:white} ^0.5 {} Multi", }, unlock = { "Obtenir un {C:attention}Joker Truqué", @@ -285,7 +285,7 @@ return { name = "Jeu Légendaire", text = { "Démarre avec un Joker {C:legendary}Légendaire{C:legendary}", - "{C:green}1 chance sur 5{} d'en créer un autre", + "{C:green}#1# chance sur #2#{} d'en créer un autre", "lorsque la Blinde de Boss est battue", "{C:inactive}(selon la place disponible)", }, @@ -307,7 +307,8 @@ return { name = "L'Horloge", text = { "+0.1X du score requis toutes", - "les 12 secondes passées dans cette Ante", + "les 12 secondes passées dans cette Ante,", + "multiplié par la vitesse du jeu", }, }, bl_cry_hammer = { @@ -335,7 +336,8 @@ return { name = "Boucle Lavande", text = { "1.25X du score requis toutes les", - "6 secondes passées dans cette manche", + "6 secondes passées dans cette manche,", + "multiplié par la vitesse du jeu", }, }, bl_cry_obsidian_orb = { @@ -412,6 +414,37 @@ return { "rareté supérieure sont affaiblis", }, }, + bl_cry_greed = { + name = "L'Avarice", + text = { + "+#2# à la taille de la blinde pour", + "chaque $#1# lorsqu'elle est sélectionnée", + }, + }, + bl_cry_repulsor = { + name = "Le Répulseur", + text = { + "Redéclenche les jokers", + "aux extrêmités, tous les autres", + "Jokers ne déclenchent pas", + }, + }, + bl_cry_chromatic = { + name = "Le Chromatisme", + text = { + "Le score de la main", + "est soustrait sur les", + "mains impaires", + }, + }, + bl_cry_landlord = { + name = "Le Locateur", + text = { + "Applique Location à", + "un Joker aléatoire", + "après que la main soit jouée", + }, + }, bl_cry_pinkbow = { name = "Nœud Rose", text = { @@ -422,9 +455,9 @@ return { bl_cry_scorch = { name = "La Grille", text = { - "Must play 5 cards,", - "destroy played and", - "discarded cards", + "5 cartes doivent être jouées,", + "toutes les cartes jouées", + "et défaussées sont détruites", }, }, bl_cry_sapphire_stamp = { @@ -490,8 +523,25 @@ return { "sont affaiblis", }, }, + bl_cry_decision = { + name = "La Décision", + text = { + "Attache les Jokers après qu'une main", + "soit jouée ou défaussée", + "Ouvre un Paquet Bouffon Maléfique", + "après la manche", + }, + }, }, Code = { + c_cry_assemble = { + name = "://ASSEMBLAGE", + text = { + "Ajoute du {C:cry_code}Multi{}", + "à la {C:cry_code}main sélectionnée{} égal au", + "nombre de Jokers possédés", + }, + }, c_cry_alttab = { name = "://ALTTAB", text = { @@ -518,7 +568,7 @@ return { c_cry_crash = { name = "://CRASH", text = { - "{C:cry_code,E:1}Ne le faites pas.", + "{C:cry_code,E:1}Ne le fais pas.", }, }, c_cry_ctrl_v = { @@ -555,12 +605,26 @@ return { "{C:inactive,s:0.8}découvertes pour être valides", }, }, + c_cry_cryfunction = { + name = "FONCTION://", + text = { + "Enregistre les {C:cry_code}trois derniers{} consommables utilisés,", + "réutiliser cette carte crée une copie du", + "premier consommable avec un sticker {C:cry_code}Fonction://{}", + }, + }, + c_cry_global = { + name = "://GLOBAL", + text = { + "Définit la carte sélectionnée", + "comme carte {C:cry_code}Globale{}", + }, + }, c_cry_hook = { name = "ACCROCHER://", text = { - "Les deux jokers sélectionnés deviennent {C:cry_code}Accrochés", - "{C:inactive,s:0.8}Ne marche seulement si les Jokers se déclenchent dans le même contexte,", - "{C:inactive,s:0.8}comme Joker et Le Duo (les deux après le compte)", + "Applique {C:cry_code}Accroché{} à", + "2 Jokers sélectionnés", }, }, c_cry_inst = { @@ -571,6 +635,21 @@ return { "{C:inactive}(si possible){}", }, }, + c_cry_keygen = { + name = "://KEYGEN", + text = { + "Crée un coupon {C:cry_code}Périssable Banane{}", + "aléatoire, {C:cry_code}détruit{} le dernier coupon créé", + "de cette manière", + }, + }, + c_cry_log = { + name = "://LOG", + text = { + "To Be {C:cry_code}Implemented{}", + "in a future {C:cry_code}update{}", + }, + }, c_cry_machinecode = { name = "://MACHINECODE", text = { @@ -596,6 +675,13 @@ return { "la fin de la manche", }, }, + c_cry_nperror = { + name = "://ERREURNP", + text = { + "Retourne la {C:cry_code}dernière main jouée{}", + "dans votre main", + }, + }, c_cry_patch = { name = "://PATCH", text = { @@ -620,6 +706,14 @@ return { "{C:inactive}(Currently {C:cry_code}+#2#{C:inactive})", }, }, + c_cry_quantify = { + name = "://QUANTIFIER", + text = { + "Transfère {C:attention}#1#{} {C:attention}Carte#1#{}", + "ou {C:attention}Paquet#1#{} sélectionné#1#", + "dans les emplacements de {C:attention}Jokers{}", + }, + }, c_cry_reboot = { name = "://REDÉMARRAGE", text = { @@ -671,6 +765,13 @@ return { "Nourriture {C:cry_code}Glitché", }, }, + c_cry_cryupdate = { + name = "://MISEAJOUR", + text = { + "on sait {C:cry_code}pas encore{},", + "reviens dans la prochaine {C:cry_code}mise à jour{}", + }, + }, c_cry_variable = { name = "://VARIABLE", text = { @@ -678,6 +779,15 @@ return { "en un rang {C:cry_code}choisi{}", }, }, + c_cry_declare = { + name = "://DECLARER", + text = { + "Vos {C:attention}cartes sélectionnées{}", + "deviennent une {C:cry_code}nouvelle{} main de Poker", + "qui est considérée comme un {C:attention}#1#{}", + "Un maximum de {C:attention}3{} {C:inactive}[#2#]{} mains peuvent être créées", + }, + }, }, ["Content Set"] = { set_cry_blind = { @@ -731,6 +841,13 @@ return { "et au {C:attention}Joker Joyeux", }, }, + set_cry_meme = { + name = "Mème", + text = { + "Tout un tas de références", + "à de nombreux mèmes", + }, + }, set_cry_misc = { name = "Divers", text = { @@ -757,7 +874,7 @@ return { set_cry_poker_hand_stuff = { name = "Mains de poker supplémentaires", text = { - "Rajoute 4 nouvelles {C:attention}mains de poker", + "Rajoute 5 nouvelles {C:attention}mains de poker", "et active les {C:attention}mains ascensionnées", }, }, @@ -839,6 +956,7 @@ return { "{C:green}#1# chance#1# sur #2#{} de", "ne pas {C:red}détruire{} cette carte", "lorsqu'elle est déclenchée", + "{C:inactive}Non-truquable{}", }, }, e_cry_glitched = { @@ -906,6 +1024,16 @@ return { "{C:inactive}(Actuellement {X:mult,C:white}X#2#{C:inactive} Multi)", }, }, + m_cry_abstract = { + name = "Carte abstraite", + text = { + "{X:dark_edition,C:white}^#1#{} Multi,", + "Compte comme son {C:attention}propre{} rang et couleur", + "{C:green}#4# chance#4# sur #5#{} de", + "{C:red,E:2}détruire{} la carte lorsqu'elle {C:attention}jouée", + "ou {C:attention}à la fin de la manche{} si elle est tenue en main", + }, + }, }, Joker = { j_cry_test_modest = { @@ -953,6 +1081,7 @@ return { "Vendre cette carte crée", "{C:attention}2{} copies du {C:attention}Joker{} le plus à gauche", "{C:inactive,s:0.8}Ne copie pas les Carte Googol Play Nostalgiques{}", + "{C:inactive}(Selon la place disponible){}", }, }, j_cry_altgoogol_balanced = { @@ -1038,6 +1167,16 @@ return { "{C:inactive,s:0.8}Le rang ne change pas", }, }, + j_cry_rotten_egg = { + name = "Œuf pourri", + text = { + "Lorsque obtenu, définit la valeur de vente", + "de tous les Jokers actuels et futurs à {C:attention}$#1#{}", + "Réduit la valeur de vente des {C:attention}Jokers{} de {C:attention}$#2#{}", + "À la fin de la manche, après avoir gagné {C:attention}$#3#{} {C:inactive}[#4#]{}", + "en vendant des {C:attention}Jokers{}, {C:red}s'auto-détruit{}", + }, + }, j_cry_blender = { name = "Blender", text = { @@ -1129,6 +1268,14 @@ return { "pour {C:mult}-#2#{} Multi", }, }, + j_cry_buttercup = { + name = "Potimarron", + text = { + "Permet de stocker {C:attention}#1#{} objet#1# de la boutique", + "Lorsque ce Joker est vendu: Ajoute l#1# stocké#1#", + "à la prochaîne boutique", + }, + }, j_cry_candy_basket = { name = "Panier de bonbons", text = { @@ -1272,6 +1419,18 @@ return { "comme main gagnante", }, }, + j_cry_the = { + name = "Le", + text = { + "{X:mult,C:white} X#1# {} Multi si", + "la dernière m {C:attention}#2#", + }, + unlock = { + "Gagner une partie", + "en ne jouant {E:1,C:attention}Rien", + "comme main gagnante", + }, + }, j_cry_clicked_cookie = { name = "Cookie cliqué", -- the joke works better in french :3c text = { @@ -1426,6 +1585,21 @@ return { "contient une {C:attention}#2#", }, }, + j_cry_demicolon = { + name = "Deux-points-et-demie", + text = { + "{C:attention}Force-déclenche{} le Joker", + "à droite de celui-ci", + }, + }, + j_cry_starfruit = { + name = "Starfruit", + text = { + "{X:dark_edition,C:white}^#1#{} Multi,", + "perd {X:dark_edition,C:white}^#2#{} Multi à chaque", + "{C:attention}réapprovisionnement{} de la boutique", + }, + }, j_cry_digitalhallucinations = { name = "Hallucinations digitales", text = { @@ -1597,7 +1771,7 @@ return { }, }, j_cry_highfive = { - name = "High five", + name = "Tapes-m'en-Cinq", text = { "Si le rang le plus haut {C:attention}marqué{}", "est un {C:attention}5{}, convertit {C:attention}toutes{} les cartes marquées", @@ -1613,6 +1787,15 @@ return { "que {C:attention}#2#{} fois ou moins", }, }, + j_cry_familiar_currency = { + name = "Monnaie connue", + text = { + "Crée un {C:attention}Joker Mème{}", + "à la fin de la manche", + "pour {C:money}$#1#{} {C:inactive}(si possible)", + "{C:inactive}(Selon la place disponible)", + }, + }, j_cry_filler = { name = "Le filler", -- "english word used in french" moment text = { @@ -1665,6 +1848,14 @@ return { "une {C:attention}#2#", }, }, + j_cry_undefined = { + name = "Undefined Joker", + text = { + "{C:red}+#1#{} Multi si la", + "main jouée contient", + "un {C:attention}#2#", + }, + }, j_cry_formidiulosus = { name = "Formidiulosus", text = { @@ -1809,6 +2000,7 @@ return { "{C:attention}#2#{} fois,", "chaque carte jouée donne", "{X:mult,C:white} X#1# {} Multi lorsqu'elle est comptée", + "{C:inactive}(Maximum {}{C:attention}#3#{}{C:inactive} redéclenchements)", }, }, j_cry_jawbreaker = { @@ -1907,6 +2099,7 @@ return { "Les {C:attention}Rois{} comptés donnent", "{C:attention}+#1#{} à la taille de la main cette manche", "et redéclenchent les effets des cartes {C:attention}tenues en main{}", + "{C:inactive}(Actuellement {}{C:attention}+#2#{}{C:inactive})", }, }, j_cry_lightupthenight = { @@ -2028,7 +2221,7 @@ return { "{C:attention}première défausse{} de chaque manche", }, }, - j_cry_Megg = { + j_cry_megg = { name = "Mœuf", text = { "Vendre cette carte crée", @@ -2050,7 +2243,7 @@ return { "{X:mult,C:white}X#1#{} Multi pour chaque membre", "dans le {C:attention}serveur Discord{} de {C:attention}Cryptid{}", "{C:inactive}(Actuellement {X:mult,C:white}X#2#{C:inactive} Multi)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_membershipcardtwo = { @@ -2059,7 +2252,7 @@ return { "{C:chips}+#1#{} Jeton#1# pour chaque membre", "dans le {C:attention}serveur Discord{} de {C:attention}Cryptid{}", "{C:inactive}(Actuellement {C:chips}+#2#{C:inactive} Jeton#2#)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_membershipcardtwo_balanced = { @@ -2068,7 +2261,7 @@ return { "{C:chips}+#1#{} Jeton#1# tous les {C:attention}8{} membres", "dans le {C:attention}serveur Discord{} de {C:attention}Cryptid{}", "{C:inactive}(Actuellement {C:chips}+#2#{C:inactive} Jeton#2#)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_meteor = { @@ -2305,6 +2498,14 @@ return { "donne un {C:attention}Badge{} aléatoire", }, }, + j_cry_pity_prize_modest = { + name = "Lot de pitié", + text = { + "Lorsqu'un {C:attention}Paquet Booster{} est passé,", + "donne un {C:attention}Badge{} aléatoire", + "{C:red,E:2}S'auto-détruit{}", + }, + }, j_cry_pot_of_jokes = { name = "Pot de Blagues", text = { @@ -2526,8 +2727,9 @@ return { "{C:attention}+#1#{} emplacement#1# de coupon", }, unlock = { - "Win a run with", - "only {C:attention}High Card", + "Gagner une partie", + "avec uniquement", + "des {C:attention}Carte Haute", }, }, j_cry_fleshpanopticon = { @@ -2540,6 +2742,71 @@ return { '{C:inactive,s:0.8}"This prison... to hold... me?"', }, }, + j_cry_sock_and_sock = { + name = "Chaussettes de Cirque", -- un cirque plutôt digital, mdr + text = { + "Redéclenche toutes les", + "cartes {C:attention}Abstraites{} {C:attention}#1#{} fois", + }, + }, + j_cry_brokenhome = { + name = "Maison cassée", + text = { + "{X:mult,C:white} X#1# {} Multi", + "{C:green}#2# chance#2# sur #3#{} que cette carte", + "soit détruite à la fin", + "de la manche", + }, + }, + j_cry_yarnball = { + name = "Boule de laine", + text = { + "Ajoute le niveau du {C:attention}Badge Chat{} le plus élevé", + "à toutes les {C:green}probabilités affichées", + }, + }, + j_cry_pizza = { + name = "Pizza", + text = { + "Après {C:attention}#1#{} {C:inactive}[#2#]{} manche#1#", + "vendre ce Joker crée", + "{C:attention}#3#{} Parts de pizza", + }, + }, + j_cry_pizza_slice = { + name = "Part de pizza", + text = { + "Ce Joker gagne {X:mult,C:white}X#1#{} Multi", + "lorsqu'une {C:attention}Part de pizza{} est vendue", + "{C:inactive}(Actuellement{} {X:mult,C:white}X#2#{}{C:inactive} Multi){}", + }, + }, + j_cry_paved_joker = { + name = "Joker pavé", + text = { + "Les Cartes Pierre peuvent remplir", + "{C:attention}#1#{} trou#1# dans les", + "{C:attention}Quintes{} et {C:attention}Couleurs{}", + }, + }, + j_cry_fading_joker = { + name = "Joker effacé", + text = { + "Ce Joker gagne", + "{X:mult,C:white}X#1#{} Multi lorsqu'une", + "carte {C:attention}Périssable{} est affaiblie", + "{C:inactive}(Actuellement{} {X:mult,C:white}X#2#{} {C:inactive}Multi){}", + }, + }, + j_cry_poor_joker = { + name = "Joker pauvre", + text = { + "Ce Joker gagne", + "{X:mult,C:white}X#1#{} Multi lorsqu'une", + "carte {C:attention}Location{} prend de l'argent", + "{C:inactive}(Actuellement{} {C:mult}+#2#{} {C:inactive}Multi){}", + }, + }, j_cry_spaceglobe = { name = "Globe Céleste", text = { @@ -2691,6 +2958,43 @@ return { "contient une {C:attention}#2#", }, }, + j_cry_nebulous = { + name = "Joker nébuleux", + text = { + "{C:chips}+#1#{} Jeton#1# si", + "la main jouée", + "ne contient {C:attention}#2#", + }, + }, + j_cry_words_cant_even = { + name = "Un joker dont je ne suis pas en mesure de décrire avec des mots", + text = { + "{X:mult,C:white}X#1#{} Multi si", + "la main jouée", + "contient {C:attention}#2#", + }, + }, + j_cry_many_lost_minds = { + name = "Nombreux sont ceux que ce joker a rendus fous en essayant de le comprendre", + text = { + "{C:chips}+#1#{} Jetons si", + "la main jouée", + "contient {C:attention}#2#", + }, + }, + j_cry_annihalation = { + name = "La destruction et la fin nette pure et dure de tout ce qui a rendu Balatro sacré", + text = { + "{X:dark_edition,C:white}^#1#{} Multi si", + "la main jouée", + "contient {C:attention}#2#", + }, + unlock = { + "Gagner une partie", + "en jouant l'{E:1,C:attention}#1#", + "comme main gagnante", + }, + }, j_cry_trick_or_treat = { name = "Des bonbons ou un sort!", text = { @@ -2720,7 +3024,7 @@ return { text = { "Vendre cette carte", "{C:attention}multiplie{} les valeurs", - "des jokers possédés de {C:attention}X1.5{}", + "des jokers possédés de {C:attention}X#1#{}", }, }, j_cry_unity = { @@ -2883,7 +3187,7 @@ return { }, Planet = { c_cry_Klubi = { - name = "Klubi", + name = "Risti", text = { "({V:1}lvl.#4#{})({V:2}lvl.#5#{})({V:3}lvl.#6#{})", "Améliore", @@ -2893,7 +3197,7 @@ return { }, }, c_cry_Lapio = { - name = "Lapio", + name = "Pata", text = { "({V:1}lvl.#4#{})({V:2}lvl.#5#{})({V:3}lvl.#6#{})", "Améliore", @@ -2912,6 +3216,16 @@ return { "et {C:attention}#3#{}", }, }, + c_cry_voxel = { + name = "Voxel", + text = { + "({V:1}lvl.#4#{})({V:2}lvl.#5#{})({V:3}lvl.#6#{})", + "Améliore", + "{C:attention}#1#{},", + "{C:attention}#2#{},", + "et {C:attention}#3#{}", + }, + }, c_cry_nstar = { name = "Étoile à neutrons", text = { @@ -2933,7 +3247,7 @@ return { }, }, c_cry_Sydan = { - name = "Sydan", + name = "Hertta", text = { "({V:1}lvl.#4#{})({V:2}lvl.#5#{})({V:3}lvl.#6#{})", "Améliore", @@ -2943,7 +3257,7 @@ return { }, }, c_cry_Timantti = { - name = "Timantti", + name = "Ruutu", text = { "({V:1}lvl.#4#{})({V:2}lvl.#5#{})({V:3}lvl.#6#{})", "Améliore", @@ -2998,6 +3312,26 @@ return { "{C:inactive}(Actuellement {X:gold,C:white}X(#3#^asc){C:inactive})", }, }, + c_cry_Timantii = { + name = "Ruutu", + text = { + "({V:1}lvl.#4#{})({V:2}lvl.#5#{})({V:3}lvl.#6#{})", + "Améliore", + "{C:attention}#1#{},", + "{C:attention}#2#{},", + "et {C:attention}#3#{}", + }, + }, + -- give it up for le rien + c_cry_nibiru = { + name = "Nibiru", + text = { + "{S:0.8}({S:0.8,V:1}niv.#1#{S:0.8}){} Améliore", + "{C:attention}#2#", + "{C:mult}+#3#{} Multi et", + "{C:chips}+#4#{} Jeton#4#", + }, + }, }, Sleeve = { sleeve_cry_beige_sleeve = { @@ -3141,12 +3475,22 @@ return { sleeve_cry_antimatter_sleeve = { name = "Pochette d'Antimatière", text = { - "Applique les {C:attention}effects{}", + "Applique les {C:attention}effets{}", "et autres {C:attention}effets spéciaux{}", "de toutes les autres pochettes", "{C:red}WIP", }, }, + sleeve_cry_antimatter_sleeve_balanced = { + name = "Pochette d'Antimatière", + text = { + "Applique les {C:attention}effets{}", + "et autres {C:attention}effets spéciaux{}", + "de {C:attention}toutes{} les pochettes", + "battues avec la {C:gold}Mise Or{}", + "{C:red}WIP", + }, + }, }, Spectral = { c_cry_adversary = { @@ -3170,6 +3514,7 @@ return { text = { "Crée {C:attention}#1#{} copie#1# {C:dark_edition}Négatives{}", "d'un consommable {C:attention}aléatoire", + "en votre possession", "{C:inactive,s:0.8}Ne copie pas Chambré{}", }, }, @@ -3261,6 +3606,14 @@ return { "sélectionnée", }, }, + c_cry_meld = { + name = "Mélange", -- c'était "le Mélange qd c'était un tarot" + text = { + "Transforme un {C:attention}Joker{} ou", + "une {C:attention}carte à jouer{} en", + "carte {C:dark_edition}Double-face", + }, + }, c_cry_vacuum = { name = "Aspiration", text = { @@ -3683,6 +4036,30 @@ return { "{s:0.8,C:inactive}Badges de Copie exclus", }, }, + tag_cry_clone = { + name = "Badge Clone", + text = { + "Les objets de la boutique coûtent {C:attention}X#1#{}", + "plus cher, octroie une {C:attention}Copie{}", + "de la prochaîne carte achetée", + }, + }, + tag_cry_lens = { + name = "Badge Optique", + text = { + "Applique {C:dark_edition}Négatif{}", + "à {C:attention}#1#{} consommable#1#", + "aléatoire#1#", + }, + }, + tag_cry_palette_cleanser = { + name = "Badge Nettoyant Palette", + text = { + "Enlève un sticker {C:attention}aléatoire{}", + "d'un Joker ou carte à jouer", + "{C:attention}aléatoire{}", + }, + }, }, Tarot = { c_cry_automaton = { @@ -3701,12 +4078,12 @@ return { "{C:attention}Carte#1# écho", }, }, - c_cry_meld = { - name = "le Mélange", + c_cry_instability = { + name = "Instabilité", text = { - "Transforme un {C:attention}Joker{} ou", - "une {C:attention}carte à jouer{} en", - "carte {C:dark_edition}Double-face", + "Transforme jusqu'à {C:attention}#1#{}", + "carte#1# sélectionnée#1# en", + "{C:attention}Carte#1# abstraites", }, }, c_cry_theblessing = { @@ -3873,6 +4250,9 @@ return { "Les cartes {C:planet}Planète{} apparaissent", "{C:attention}X#1#{} plus souvent", "dans la boutique", + "Permet de contrôler le {C:planet}taux d'apparition{}", + "{C:planet}des planètes{} dans la boutique", + "{C:inactive}(Voir les {C:attention}Infos de la partie{C:inactive})", "Toutes les futures cartes", "{C:planet}Planète{} sont {C:green}gratuites{}", }, @@ -3953,8 +4333,11 @@ return { "Les cartes {C:tarot}Tarot{} apparaissent", "{C:attention}X#1#{} plus souvent", "dans la boutique", + "Permet de contrôler le {C:tarot}taux d'apparition{}", + "{C:tarot}des Tarots{} dans la boutique", + "{C:inactive}(Voir les {C:attention}Infos de la partie{C:inactive})", "Toutes les futures cartes", - "{C:tarot}Tarot{} seront {C:green}gratuites{}", + "{C:tarot}Tarot{} sont {C:green}gratuites{}", }, unlock = { "Acheter {C:attention}100{} cartes", @@ -4002,12 +4385,21 @@ return { text = { "{C:attention}+#1#{} limite", "de sélection de cartes", - "{C:inactive,s:0.7}NOTE: Aura plus de{}", - "{C:inactive,s:0.7}fonctionnalités plus tard{}", + "Toutes les cartes sélectionnées contribuent", + "aux {C:attention}Mains Ascensionées{}", }, }, }, Other = { + alt_wheel_of_fortune = { + name = "La Roue de Fortune", + text = { + "{C:green}#1# chance(s) sur #2#{} d'ajouter une édition", + "{C:dark_edition}Brillantes{}, {C:dark_edition}Holographique{} ou", + "{C:dark_edition}Polychrome{}", + "à un {C:attention}Joker au hasard", + }, + }, disabled = { name = "Désactivé", text = { @@ -4062,6 +4454,16 @@ return { text = { "Quand ce joker est {C:cry_code}déclenché{},", "déclenche {C:cry_code}#1#", + "{C:inactive}Ne marche pas avec toutes les cartes{}", + "{C:inactive}mais tous les jokers peuvent déclencher l'autre{}", + }, + }, + cry_global_sticker = { + name = "Global", + text = { + "Cette carte est {C:cry_code}prioritaire", + "lorsque des cartes sont tirées,", + "si possible", }, }, cry_flickering = { @@ -4079,6 +4481,22 @@ return { "{C:attention}#1#{} déclenchements", }, }, + cry_function_sticker = { + name = "Fonction://", + text = { + "Crée {C:cry_code}#1#{}", + "à l'utilisation", + }, + }, + cry_function_sticker_desc = { --for function:// card + name = "Fonction://", + text = { + "Crée le consommable", + "{C:cry_code}Fonction://{} suivant", + "{C:inactive}Actuellement #1#, #2# puis #3#{}", + }, + }, + cry_possessed = { name = "Possédé", text = { @@ -4103,10 +4521,11 @@ return { }, }, ev_cry_choco0 = { - name = "", + name = "Événements possibles", text = { - "Les détails d'un {C:cry_ascendant,E:1}événement", - "seront affichés ici", + "{T:ev_cry_choco1}1{} {T:ev_cry_choco2}2{} {T:ev_cry_choco3}3{} {T:ev_cry_choco4}4{} {T:ev_cry_choco5}5{}", + "{T:ev_cry_choco6}6{} {T:ev_cry_choco7}7{} {T:ev_cry_choco8}8{} {T:ev_cry_choco9}9{} {T:ev_cry_choco10}10{}", + "{C:inactive}(Survolez pour plus d'informations)", }, }, ev_cry_choco1 = { @@ -4368,6 +4787,15 @@ return { "{C:attention}Joker Mème{} parmi {C:attention}#2#{}", }, }, + p_cry_baneful_1 = { + name = "Paquet Bouffon Maléfique", + text = { + "Jusqu'à {C:attention}#1#{} Joker#1#", + "parmi {C:attention}#2#{} Joker#2# {X:cry_cursed,C:white}Maudit#2#{}", + "{C:attention}Skipping{} will {C:red}banish{}", + "{C:attention}rightmost{} owned Joker", + }, + }, undiscovered_code = { name = "Non découvert", text = { @@ -4410,6 +4838,12 @@ return { '{C:inactive,s:0.7}"Je déteste cette carte" - SDM_0, 2024{}{}', }, }, + cry_multiuse = { + name = "m", + text = { + "{C:inactive}Réutilisable: ({C:cry_code}#1#{C:inactive} utilisations restantes)", + }, + }, }, Unique = { c_cry_potion = { @@ -4496,6 +4930,7 @@ return { ["cry_UltPair"] = "Super Paire", ["cry_WholeDeck"] = Cryptid_config.family_mode and "Jeu complet" or "un putain de jeu complet", ["cry-Cluster Bulwark"] = "Capharna-rempart", + ["cry_None"] = "Rien", }, poker_hand_descriptions = { ["cry_Bulwark"] = { @@ -4515,6 +4950,24 @@ return { "d'un jeu standard de 52 cartes.", "Je sais pas quoi dire, mais tu es fou.", }, + ["cry_None"] = { "Une main contenant 0 cartes" }, + + ["cry_Declare0"] = { "Compte toujours comme une Quinte" }, + ["cry_Declare1"] = { "Compte toujours comme une Couleur" }, + ["cry_Declare2"] = { "Compte toujours comme un Full" }, + + ["cry_Declare0_suitless"] = { + "Compte toujours comme une Quinte", + "La main n'a pas besoin de couleurs particulières", + }, + ["cry_Declare1_suitless"] = { + "Compte toujours comme une Couleur", + "La main n'a pas besoin de couleurs particulières", + }, + ["cry_Declare2_suitless"] = { + "Compte toujours comme un Full", + "La main n'a pas besoin de couleurs particulières", + }, }, achievement_names = { ach_cry_ace_in_crash = "ACE de poche", @@ -4540,6 +4993,11 @@ return { ach_cry_pin = "L'épingle de la honte", ach_cry_youre_fucking_kidding = Cryptid_config.family_mode and "J'ai plus besoin de ça" or "Tu te fous de moi", + ach_cry_decked = "Remis en jeu", + ach_cry_despaired = "Déparaillé", + ach_cry_stoned = "Solide", + ach_cry_fucked = "Foutu", + ach_cry_technically_positive = "Techniquement positif", }, achievement_descriptions = { ach_cry_ace_in_crash = 'check_for_unlock({type = "ace_in_crash"})', @@ -4558,12 +5016,17 @@ return { ach_cry_patience_virtue = "Attendre 2 minutes face à la Boucle Lavande avant de jouer la première main, puis battre la blinde", ach_cry_perfectly_balanced = "Battre le Jeu Très Équilibré avec la Mise Ascendante", ach_cry_pull_request = "Faire ://ENGAGER apparaître le même joker qu'il a détruit", - ach_cry_traffic_jam = "Battre tous les challenges Heure de Pointe", + ach_cry_traffic_jam = "Battre tous les challenges Heure de pointe", ach_cry_ult_full_skip = "Gagner en 1 tour", ach_cry_used_crash = "Utiliser ://CRASH", ach_cry_what_have_you_done = "Supprimer ou sacrifier un Joker exotique", ach_cry_pin = "Perdre une partie face à l'Épingle", ach_cry_youre_fucking_kidding = "Défausser " .. localize("cry_WholeDeck", "poker_hands"), + ach_cry_decked = "Monter " .. localize("cry_WholeDeck", "poker_hands") .. " au niveau 5252", + ach_cry_despaired = "Monter " .. localize("cry_UltPair", "poker_hands") .. " au niveau 2222", + ach_cry_fucked = "Monter " .. localize("cry_Clusterfuck", "poker_hands") .. " au niveau 69", + ach_cry_stoned = "Monter " .. localize("cry_Bulwark", "poker_hands") .. " au niveau 420", + ach_cry_technically_positive = "Obtenir un Joker Négatif négatif", }, challenge_names = { c_cry_ballin = "Ballin'", @@ -4617,6 +5080,8 @@ return { k_cry_program_pack = "Paquet Programme", k_cry_meme_pack = "Paquet Meme", + k_cry_baneful_pack = "Paquet Bouffon Maléfique", + cry_baneful_warning = "Passer bannira le Joker le plus à droite", cry_critical_hit_ex = "Coup critique!", cry_critical_miss_ex = "Échec critique!", @@ -4631,16 +5096,19 @@ return { cry_debuff_oldflint = "Pas de Couleur", cry_debuff_oldmark = "No hands containing a Pair", cry_debuff_obsidian_orb = "Applique les capacités de tous les boss battus", + cry_blind_baneful_pack = "Après la manche, ouvre un Paquet Bouffon Maléfique", cry_tax_placeholder = "(X0.4 taille de la blinde)", cry_joke_placeholder = "(multiple de 8)", k_code = "Code", + k_chips = "Jetons", k_content_set = "Set à thème", b_content_sets = "Sets à thème", --Why aren't these in vanilla? b_tag = "Badge", b_blind = "Blinde", + rush_hour_reminder = "Activez l'Horloge et la Boucle Lavande pour jouer à Heure de pointe", b_tarot_rate = "Taux de tarot", b_planet_rate = "Taux de planète", @@ -4668,6 +5136,7 @@ return { b_flip = "RETOURNER", b_merge = "FUSIONNER", + b_store = "STOCKER", cry_asc_hands = "Mains Asc.", cry_p_star = "Étoile", @@ -4679,6 +5148,7 @@ return { cry_again_q = "Encore?", cry_curse = "Malédiction", cry_curse_ex = "Malédiction!", + cry_demicolon = "Demi-déclenché!", cry_sobbing = "À l'aide...", cry_gaming = "Gaming", cry_gaming_ex = "Gaming!", @@ -4697,6 +5167,7 @@ return { cry_unredeemed = "Plus échangé...", cry_active = "Actif", cry_inactive = "Inactif", + cry_divorced = "Divorcé!", k_disable_music = "Désactiver la musique", @@ -4707,6 +5178,7 @@ return { k_planet_disc = "Disque Circumstellaire", k_planet_satellite = "Satellites Naturels", k_planet_universe = Cryptid_config.family_mode and "Univers" or "Le putain d'univers", + k_planet_nibiru = "Inexistante", cry_notif_jimball_1 = "Jimboule", cry_notif_jimball_2 = "Notice de droits d'auteur", @@ -4747,6 +5219,7 @@ return { unique = "Unique", cry_rigged = "Truqué", cry_hooked = "Accroché", + cry_global_sticker = "Global", cry_flickering = "Luisant", cry_possessed = "Possédé", diff --git a/Cryptid/localization/id.lua b/Cryptid/localization/id.lua index 579a341..35fb8e6 100644 --- a/Cryptid/localization/id.lua +++ b/Cryptid/localization/id.lua @@ -1222,7 +1222,7 @@ return { "{C:attention}first discard{} of each round", }, }, - j_cry_Megg = { + j_cry_megg = { name = "Megg", text = { "Sell this card to create", @@ -1236,7 +1236,7 @@ return { "{X:mult,C:white}X#1#{} Mult for each member", "in the {C:attention}Cryptid Discord{}", "{C:inactive}(Currently {X:mult,C:white}X#2#{C:inactive} Mult)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_membershipcardtwo = { @@ -1245,7 +1245,7 @@ return { "{C:chips}+#1#{} Chips for each member", "in the {C:attention}Cryptid Discord{}", "{C:inactive}(Currently {C:chips}+#2#{C:inactive} Chips)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_meteor = { @@ -2045,6 +2045,14 @@ return { "card in your hand", }, }, + c_cry_meld = { + name = "Meld", + text = { + "Select a {C:attention}Joker{} or", + "{C:attention}playing card{} to", + "become {C:dark_edition}Double-Sided", + }, + }, c_cry_vacuum = { name = "Vacuum", text = { @@ -2477,14 +2485,7 @@ return { "into an {C:attention}Echo Card", }, }, - c_cry_meld = { - name = "Meld", - text = { - "Select a {C:attention}Joker{} or", - "{C:attention}playing card{} to", - "become {C:dark_edition}Double-Sided", - }, - }, + c_cry_theblessing = { name = "The Blessing", text = { @@ -2716,6 +2717,15 @@ return { }, }, Other = { + alt_wheel_of_fortune = { + name = "The Wheel of Fortune", + text = { + "{C:green}#1# dalam #2#{} peluang untuk menambah", + "edisi {C:dark_edition}Foil{}, {C:dark_edition}Holographic{}, dan", + "{C:dark_edition}Polychrome{}", + "menghancurkan sebuah {C:attention}Joker secara acak", + }, + }, banana = { name = "Banana", text = { @@ -3041,6 +3051,7 @@ return { cry_debuff_obsidian_orb = "Applies abilities of all defeated bosses", k_code = "Code", + k_chips = "chip", b_code_cards = "Code Cards", b_pull = "PULL", cry_hooked_ex = "Hooked!", diff --git a/Cryptid/localization/ja.lua b/Cryptid/localization/ja.lua index df4410a..4c75816 100644 --- a/Cryptid/localization/ja.lua +++ b/Cryptid/localization/ja.lua @@ -1222,7 +1222,7 @@ return { "{C:attention}first discard{} of each round", }, }, - j_cry_Megg = { + j_cry_megg = { name = "Megg", text = { "Sell this card to create", @@ -1236,7 +1236,7 @@ return { "{X:mult,C:white}X#1#{} Mult for each member", "in the {C:attention}Cryptid Discord{}", "{C:inactive}(Currently {X:mult,C:white}X#2#{C:inactive} Mult)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_membershipcardtwo = { @@ -1245,7 +1245,7 @@ return { "{C:chips}+#1#{} Chips for each member", "in the {C:attention}Cryptid Discord{}", "{C:inactive}(Currently {C:chips}+#2#{C:inactive} Chips)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_meteor = { @@ -2045,6 +2045,14 @@ return { "card in your hand", }, }, + c_cry_meld = { + name = "Meld", + text = { + "Select a {C:attention}Joker{} or", + "{C:attention}playing card{} to", + "become {C:dark_edition}Double-Sided", + }, + }, c_cry_vacuum = { name = "Vacuum", text = { @@ -2477,14 +2485,6 @@ return { "into an {C:attention}Echo Card", }, }, - c_cry_meld = { - name = "Meld", - text = { - "Select a {C:attention}Joker{} or", - "{C:attention}playing card{} to", - "become {C:dark_edition}Double-Sided", - }, - }, c_cry_theblessing = { name = "The Blessing", text = { @@ -2716,6 +2716,15 @@ return { }, }, Other = { + alt_wheel_of_fortune = { + name = "運命の輪", + text = { + "{C:green}#2#分の#1#{} の確率で", + "ランダムな {C:attention}ジョーカー{} に", + "{C:dark_edition}フォイル{}、 {C:dark_edition}ホログラム{}", + "{C:dark_edition}ポリクローム{} エディションのいずれかを加える", + }, + }, banana = { name = "Banana", text = { @@ -3041,6 +3050,7 @@ return { cry_debuff_obsidian_orb = "Applies abilities of all defeated bosses", k_code = "Code", + k_chips = "チップ", b_code_cards = "Code Cards", b_pull = "PULL", cry_hooked_ex = "Hooked!", diff --git a/Cryptid/localization/ko.lua b/Cryptid/localization/ko.lua index 579a341..832f2f1 100644 --- a/Cryptid/localization/ko.lua +++ b/Cryptid/localization/ko.lua @@ -1,3316 +1,4881 @@ ---I couldn't get Meme Packs to work without crashing ---yes somehow that was harder than RNJoker return { descriptions = { Back = { b_cry_antimatter = { - name = "Antimatter Deck", + name = "반물질 덱", text = { - "Applies the {C:legendary,E:1}upsides{}", - "of {C:attention}every{} deck", + "모든 덱의", + "{C:legendary,E:1}장점{}을 적용합니다", + }, + unlock = { + "{C:attention}빈 덱{}으로", + "{C:attention}골드 스테이크{}에서", + "한 판 승리", + }, + }, + b_cry_antimatter_balanced = { + name = "반물질 덱", + text = { + "{C:gold}골드 스테이크{}에서 승리한", + "모든 덱의 {C:legendary,E:1}장점{}을", + "적용합니다", + }, + }, + b_cry_beige = { + name = "베이지 덱", + text = { + "{C:attention}일반{} 조커의", + "가치가 {C:attention}4배{}가 됩니다", + }, + unlock = { + "컬렉션에서", + "최소 {C:attention}200개{}의", + "아이템 발견", }, }, b_cry_beta = { - name = "Nostalgic Deck", + name = "향수 덱", text = { - "{C:attention}Joker{} and {C:attention}Consumable{}", - "slots are {C:attention}combined", - "{C:attention}Nostalgic{} Blinds replace", - "their updated Blind", + "{C:attention}조커{}와 {C:attention}소모품{} 슬롯이", + "{C:attention}통합됩니다", + "{C:attention}향수{} 블라인드가", + "업데이트된 블라인드를 대체합니다", + }, + unlock = { + "{C:attention}핑크 스테이크{}에서", + "한 판 승리", }, }, b_cry_blank = { - name = "Blank Deck", + name = "빈 덱", text = { - "{C:inactive,E:1}Does nothing?", + "{C:inactive,E:1}아무것도 안 함?", + }, + }, + b_cry_bountiful = { + name = "풍요로운 덱", + text = { + "{C:blue}플레이{} 또는 {C:red}버린{} 후,", + "항상 카드 {C:attention}5{}장을 뽑습니다", + }, + unlock = { + "{C:attention}The Serpent{}을", + "{C:red}버리기{} 없이 이기기", }, }, b_cry_CCD = { - name = "CCD Deck", + name = "CCD 덱", text = { - "Every card is also", - "a {C:attention}random{} consumable", + "모든 카드가", + "{C:attention}무작위{} 소모품이기도 합니다", + }, + unlock = { + "{C:spectral}Hammerspace{} 사용", }, }, b_cry_conveyor = { - name = "Conveyor Deck", + name = "컨베이어 덱", text = { - "Jokers may {C:attention}not{} be moved", - "At start of round,", - "{C:attention}duplicate{} rightmost Joker", - "and {C:attention}destroy{} leftmost Joker", + "조커를 {C:attention}움직일 수 없습니다", + "라운드 시작 시,", + "가장 오른쪽 조커를 {C:attention}복제{}하고", + "가장 왼쪽 조커를 {C:attention}파괴{}합니다", + }, + unlock = { + "{C:spectral}Analog{} 사용", }, }, b_cry_critical = { - name = "Critical Deck", + name = "치명타 덱", text = { - "After each hand played,", - "{C:green}#1# in 4{} chance for {X:dark_edition,C:white} ^2 {} Mult", - "{C:green}#1# in 8{} chance for {X:dark_edition,C:white} ^0.5 {} Mult", + "핸드를 낼 때마다,", + "{C:green}#2#분의 #1#{} 확률로 {X:dark_edition,C:white} 배수 ^2 {}", + "{C:green}#3#분의 #1#{} 확률로 {X:dark_edition,C:white} 배수 ^0.5 {}", + }, + unlock = { + "{C:attention}조작된 조커{} 획득", + }, + }, + b_cry_e_deck = { + name = "에디션 덱", + text = { + "모든 카드는 {C:dark_edition}#1#{}입니다", + "카드는 에디션을 변경할 수 없습니다", + "{C:inactive}(클릭하여 편집)", + }, + unlock = { + "모든 {C:dark_edition}에디션{} 발견", }, }, b_cry_encoded = { - name = "Encoded Deck", + name = "인코딩 덱", text = { - "Start with a {C:cry_code,T:j_cry_CodeJoker}Code Joker{}", - "and a {C:cry_code,T:j_cry_copypaste}Copy/Paste{}", - "Only {C:cry_code}Code Cards{} appear in shop", + "{C:cry_code,T:j_cry_CodeJoker}코드 조커{}와", + "{C:cry_code,T:j_cry_copypaste}복사/붙여넣기{}를 가지고 시작합니다", + "상점에는 {C:cry_code}코드 카드{}만 나타납니다", + }, + unlock = { + "{C:spectral}POINTER://{} 사용", }, }, b_cry_equilibrium = { - name = "Deck of Equilibrium", + name = "평형의 덱", text = { - "All cards have the", - "{C:attention}same chance{} of", - "appearing in shops,", - "start run with", - "{C:attention,T:v_overstock_plus}Overstock Plus", + "모든 카드가 상점에", + "나타날 확률이 {C:attention}동일{}해집니다", + "{C:attention,T:v_overstock_plus}초과 재고 플러스{}를", + "가지고 런을 시작합니다", + }, + unlock = { + "동시에 {C:attention}100개의 조커{}를", + "보유하기", + }, + }, + b_cry_et_deck = { + name = "강화 덱", + text = { + "모든 {C:attention}플레잉 카드{}는", + "{C:attention}#1#{}입니다", + "{C:inactive}(클릭하여 편집)", + }, + unlock = { + "{C:spectral}Vacuum{} 사용", }, }, b_cry_glowing = { - name = "Glowing Deck", + name = "빛나는 덱", text = { - "Multiply the values of", - "all Jokers by {X:dark_edition,C:white} X1.25 {}", - "when Boss Blind is defeated", - "{X:cry_jolly,C:white,s:0.8} Jolly#1#Open#1#Winner#1#-#1#wawa#1#person", --peak loc_vars right here + "보스 블라인드를 이길 때", + "모든 조커의 가치를", + "{X:dark_edition,C:white} X1.25 {} 곱합니다", + "{X:cry_jolly,C:white,s:0.8} 졸리#1#오픈#1#위너#1#-#1#와와#1#사람", + }, + unlock = { + "{C:attention}베이지 덱{}으로", + "한 판 승리", }, }, b_cry_infinite = { - name = "Infinite Deck", + name = "무한 덱", text = { - "You can select {C:attention}any", - "number of cards", - "{C:attention}+1{} hand size", + "{C:attention}원하는 만큼의", + "카드를 선택할 수 있습니다", + "핸드 크기 {C:attention}+1{}", + }, + unlock = { + "{C:attention}6장{} 이상의 카드를", + "포함한 핸드 플레이하기", }, }, b_cry_misprint = { - name = "Misprint Deck", + name = "오타 덱", text = { - "Values of cards", - "and poker hands", - "are {C:attention}randomized", + "카드와 포커 핸드의", + "가치가", + "{C:attention}무작위{}로 정해집니다", + }, + unlock = { + "{C:dark_edition}글리치{} {C:attention}조커{} 획득", }, }, b_cry_redeemed = { - name = "Redeemed Deck", + name = "상환된 덱", text = { - "When a {C:attention}Voucher{} is purchased,", - "gain its {C:attention}extra tiers", + "{C:attention}바우처{}를 구매하면,", + "그 {C:attention}추가 등급{}을 얻습니다", + }, + unlock = { + "모든 {C:attention}바우처{} 발견", + }, + }, + b_cry_sk_deck = { + name = "스티커 덱", + text = { + "모든 카드는 {C:attention}#1#{}입니다", + "{C:inactive}(클릭하여 편집)", + }, + unlock = { + "{C:spectral}Lock{} 사용", + }, + }, + b_cry_sl_deck = { + name = "봉인 덱", + text = { + "모든 플레잉 카드는 {C:dark_edition}#1#{}을 가집니다", + "카드는 봉인을 변경할 수 없습니다", + "{C:inactive}(클릭하여 편집)", + }, + unlock = { + "{C:spectral}Typhoon{} 사용", + }, + }, + b_cry_spooky = { + name = "으스스한 덱", + text = { + "{C:eternal}이터널{} {C:attention,T:j_cry_chocolate_dice}초콜릿 주사위{}를 가지고 시작", + "각 {C:attention}앤티{} 이후,", + "{C:cry_candy}사탕{} 또는 {X:cry_cursed,C:white}저주받은{} 조커 생성", + }, + unlock = { + "{C:cry_candy}사탕{C:attention} 조커{} 획득", + }, + }, + b_cry_st_deck = { + name = "문양 덱", + text = { + "모든 플레잉 카드는 {C:dark_edition}#1#", + "이며 문양을 변경할 수 없습니다", + "{C:inactive}(클릭하여 편집)", + }, + unlock = { + "{C:spectral}Replica{} 사용", }, }, b_cry_very_fair = { - name = "Very Fair Deck", + name = "아주 공정한 덱", text = { - "{C:blue}-2{} hands, {C:red}-2{} discards", - "every round", - "{C:attention}Vouchers{} no longer", - "appear in the shop", + "매 라운드 {C:blue}핸드 -2{}, {C:red}버리기 -2{}", + "{C:attention}바우처{}는 더 이상", + "상점에 나타나지 않습니다", + }, + unlock = { + "{C:attention}빈 덱{}으로", + "한 판 승리", }, }, b_cry_wormhole = { - name = "Wormhole Deck", + name = "웜홀 덱", text = { - "Start with an {C:cry_exotic}Exotic{C:attention} Joker", - "Jokers are {C:attention}20X{} more", - "likely to be {C:dark_edition}Negative", - "{C:attention}-2{} Joker slots", + "{C:cry_exotic}이그조틱{C:attention} 조커를 가지고 시작", + "조커가 {C:dark_edition}네거티브{}일", + "확률이 {C:attention}20배{} 높아집니다", + "조커 슬롯 {C:attention}-2{}", + }, + unlock = { + "{C:cry_exotic}이그조틱{C:attention} 조커{} 획득", }, }, b_cry_legendary = { - name = "Legendary Deck", + name = "전설 덱", text = { - "Start with an {C:legendary}Legendary{C:legendary} Joker", - "{C:green}1 in 5{} chance to create another", - "when Boss Blind is defeated {C:inactive}(must have room){}", + "{C:legendary}전설{} 조커를 가지고 시작", + "보스 블라인드를 이길 때 {C:green}#2#분의 #1#{} 확률로", + "다른 전설 조커 생성 {C:inactive}(공간 필요){}", + }, + unlock = { + "동시에 {C:attention}2개의 전설 조커{} 보유", }, }, }, Blind = { bl_cry_box = { - name = "The Box", + name = "상자", text = { - "All Common Jokers", - "are debuffed", + "모든 일반 조커가", + "디버프됩니다", }, }, bl_cry_clock = { - name = "The Clock", + name = "시계", text = { - "+0.1X blind requirements every", - "12 seconds spent this ante", + "이번 앤티에서 12초마다", + "블라인드 요구 점수 +0.1X,", + "게임 속도에 따라 배가됨", }, }, bl_cry_hammer = { - name = "The Hammer", + name = "망치", text = { - "All cards with odd", - "rank are debuffed", + "홀수 등급의 모든", + "카드가 디버프됩니다", }, }, bl_cry_joke = { - name = "The Joke", + name = "농담", text = { - "If score is >2X requirements,", - "set ante to multiple of #1#", + "점수가 요구 점수의 2배를 넘으면,", + "앤티를 #2#로 설정합니다", }, }, bl_cry_magic = { - name = "The Magic", + name = "마법", text = { - "All cards with even", - "rank are debuffed", + "짝수 등급의 모든", + "카드가 디버프됩니다", }, }, bl_cry_lavender_loop = { - name = "Lavender Loop", + name = "라벤더 루프", text = { - "1.25X blind requirements every", - "6 seconds spent this round", + "이번 라운드에서 6초마다", + "블라인드 요구 점수 1.25X,", + "게임 속도에 따라 배가됨", }, }, bl_cry_obsidian_orb = { - name = "Obsidian Orb", + name = "흑요석 구슬", text = { - "Applies abilities of", - "all defeated bosses", + "패배한 모든 보스의", + "능력을 적용합니다", }, }, bl_cry_oldarm = { - name = "Nostalgic Arm", + name = "향수의 팔", text = { - "Must play 4", - "or fewer cards", + "4장 이하의 카드를", + "플레이해야 합니다", }, }, bl_cry_oldfish = { - name = "Nostalgic Fish", + name = "향수의 물고기", text = { - "All hands start", - "with 1 Mult", + "모든 핸드가", + "1 배수로 시작합니다", }, }, bl_cry_oldflint = { - name = "Nostalgic Flint", + name = "향수의 부싯돌", text = { - "No Flushes", + "플러시 없음", }, }, bl_cry_oldhouse = { - name = "Nostalgic House", + name = "향수의 집", text = { - "No Full Houses", + "풀 하우스 없음", }, }, bl_cry_oldmanacle = { - name = "Nostalgic Manacle", + name = "향수의 족쇄", text = { - "Divide Mult by discards", + "배수를 버리기 횟수로 나눕니다", }, }, bl_cry_oldmark = { - name = "Nostalgic Mark", + name = "향수의 표식", text = { - "No hands that", - "contain a Pair", + "페어를 포함하는", + "핸드 없음", }, }, bl_cry_oldox = { - name = "Nostalgic Ox", + name = "향수의 황소", text = { - "All hands start", - "with 0 Chips", + "모든 핸드가", + "0 칩으로 시작합니다", }, }, bl_cry_oldpillar = { - name = "Nostalgic Pillar", + name = "향수의 기둥", text = { - "No Straights", + "스트레이트 없음", }, }, bl_cry_oldserpent = { - name = "Nostalgic Serpent", + name = "향수의 뱀", text = { - "Divide Mult by level", - "of played poker hand", + "배수를 플레이한 포커 핸드의", + "레벨로 나눕니다", }, }, bl_cry_pin = { - name = "The Pin", + name = "핀", text = { - "Jokers with Epic or higher", - "rarity are debuffed", + "에픽 등급 이상의", + "조커가 디버프됩니다", + }, + }, + bl_cry_scorch = { + name = "소각", + text = { + "5장의 카드를 플레이해야 하며,", + "플레이하고 버린 카드는", + "파괴됩니다", + }, + }, + bl_cry_greed = { + name = "탐욕", + text = { + "선택 시 $#1#당", + "블라인드 요구 점수 +#2#", + }, + }, + bl_cry_repulsor = { + name = "반발기", + text = { + "가장 오른쪽과 왼쪽 조커를", + "재발동하고, 다른 모든", + "조커는 발동하지 않습니다", + }, + }, + bl_cry_chromatic = { + name = "색채", + text = { + "홀수 번째 핸드에서", + "핸드 점수가", + "차감됩니다", + }, + }, + bl_cry_landlord = { + name = "집주인", + text = { + "핸드를 플레이할 때", + "무작위 조커에", + "임대료를 적용합니다", }, }, bl_cry_pinkbow = { - name = "Pink Bow", + name = "핑크 리본", text = { - "Randomize rank of cards", - "held in hand on play", + "플레이 시 손에 든", + "카드의 등급을 무작위로 변경합니다", }, }, bl_cry_sapphire_stamp = { - name = "Sapphire Stamp", + name = "사파이어 스탬프", text = { - "Select an extra card, deselect", - "random card before scoring", + "추가 카드를 선택하면, 점수 계산 전", + "무작위 카드를 선택 해제합니다", }, }, bl_cry_shackle = { - name = "The Shackle", + name = "족쇄", text = { - "All Negative Jokers", - "are debuffed", + "모든 네거티브 조커가", + "디버프됩니다", }, }, bl_cry_striker = { - name = "The Striker", + name = "공격수", text = { - "All Rare Jokers", - "are debuffed", + "모든 레어 조커가", + "디버프됩니다", }, }, bl_cry_tax = { - name = "The Tax", + name = "세금", text = { - "Score per hand capped at", - "0.4X blind requirements", + "핸드당 점수 상한선", + "#1#", }, }, bl_cry_tornado = { - name = "Turquoise Tornado", + name = "청록색 토네이도", text = { - "#1# in #2# chance for", - "played hand to not score", + "#2#분의 #1# 확률로", + "플레이한 핸드가 점수를 얻지 못함", }, }, bl_cry_trick = { - name = "The Trick", + name = "속임수", text = { - "After each hand, flip all", - "face-up cards held in hand", + "각 핸드 이후, 손에 든 모든", + "앞면 카드를 뒤집습니다", + }, + }, + bl_cry_trophy = { + name = "레몬 트로피", + text = { + "배수가 칩을", + "초과할 수 없습니다", }, }, bl_cry_vermillion_virus = { - name = "Vermillion Virus", + name = "주홍 바이러스", text = { - "One random Joker", - "replaced every hand", + "매 핸드마다 무작위", + "조커 하나가 교체됩니다", }, }, bl_cry_windmill = { - name = "The Windmill", + name = "풍차", text = { - "All Uncommon Jokers", - "are debuffed", + "모든 희귀 조커가", + "디버프됩니다", + }, + }, + bl_cry_decision = { + name = "결정", + text = { + "플레이 또는 버릴 때 조커를 고정", + "라운드 후 유해한 익살꾼", + "팩을 엽니다", }, }, }, Code = { - c_cry_class = { - name = "://CLASS", - text = { - "Convert {C:cry_code}#1#{} selected card", - "to a {C:cry_code}chosen{} enhancement", - }, - }, - c_cry_commit = { - name = "://COMMIT", - text = { - "Destroy a {C:cry_code}selected{} Joker,", - "create a {C:cry_code}new{} Joker", - "of the {C:cry_code}same rarity", - }, - }, c_cry_crash = { - name = "://CRASH", + name = "://충돌", text = { - "{C:cry_code,E:1}Don't.", + "{C:cry_code,E:1}하지 마세요.", }, }, - c_cry_delete = { - name = "://DELETE", + c_cry_keygen = { + name = "://키젠", text = { - "{C:cry_code}Permanently{} remove a", - "{C:cry_code}selected{} shop item", - "{C:inactive,s:0.8}Item cannot appear again this run", + "무작위 {C:cry_code}소멸성 바나나{} 바우처를", + "생성하고, 이전에 이 방법으로 생성된", + "바우처를 {C:cry_code}파괴{}합니다.", }, }, - c_cry_divide = { - name = "://DIVIDE", + c_cry_payload = { + name = "://페이로드", text = { - "{C:cry_code}Halve{} all listed prices", - "in current shop", + "다음으로 이기는 블라인드에서", + "{C:cry_code}X#1#{} 이자를 줍니다", }, }, c_cry_exploit = { - name = "://EXPLOIT", + name = "://익스플로잇", text = { - "The {C:cry_code}next{} hand played", - "is calculated as a", - "{C:cry_code}chosen{} poker hand", - "{C:inactive,s:0.8}Secret hands must be", - "{C:inactive,s:0.8}discovered to be valid", + "{C:cry_code}현재 보이는{} 포커 핸드를 {C:cry_code}선택{}하세요,", + "다음 핸드는 해당 핸드로 {C:cry_code}계산{}되며,", + "{C:cry_code}하나{}의 임시 {C:cry_code}승천 파워{}를 얻습니다", + }, + }, + c_cry_malware = { + name = "://멀웨어", + text = { + "{C:hand}손에 든{} 모든 카드에", + "{C:dark_edition}글리치{}를 추가합니다", + }, + }, + c_cry_nperror = { + name = "://NPERROR", + text = { + "{C:cry_code}마지막으로 플레이한 핸드{}를", + "손으로 되돌립니다", + }, + }, + c_cry_rework = { + name = "://재작업", + text = { + "{C:cry_code}선택한{} 조커를 파괴하고,", + "{C:cry_code}업그레이드된{} 에디션을 가진", + "{C:cry_code}재작업 태그{}를 생성합니다", + "{C:inactive,s:0.8}컬렉션 순서에 따라 업그레이드됩니다", + }, + }, + c_cry_merge = { + name = "://병합", + text = { + "선택한 {C:cry_code}소모품{}을", + "선택한 {C:cry_code}플레잉 카드{}와 병합합니다", + }, + }, + c_cry_commit = { + name = "://커밋", + text = { + "{C:cry_code}선택한{} 조커를 파괴하고,", + "{C:cry_code}동일한 희귀도{}의", + "{C:cry_code}새로운{} 조커를 생성합니다", + }, + }, + c_cry_machinecode = { + name = "://기계어", + text = { + "", + }, + }, + c_cry_spaghetti = { + name = "://스파게티", + text = { + "{C:cry_code}글리치", + "음식 조커를 생성합니다", + }, + }, + c_cry_seed = { + name = "://시드", + text = { + "조커 또는", + "플레잉 카드를 선택하여", + "{C:cry_code}조작됨{}으로 만듭니다", + }, + }, + c_cry_patch = { + name = "://패치", + text = { + "현재 보이는 아이템에서", + "모든 {C:cry_code}디버프{}를 제거합니다", + "상점 상태를 {C:cry_code}초기화{}합니다", + }, + }, + c_cry_cryupdate = { + name = "://업데이트", + text = { + "미래의 {C:cry_code}업데이트{}에서", + "{C:cry_code}결정될{} 예정", }, }, c_cry_hook = { name = "HOOK://", text = { - "Select two Jokers", - "to become {C:cry_code}Hooked", - }, - }, - c_cry_machinecode = { - name = "://MACHINECODE", - text = { - "", - }, - }, - c_cry_malware = { - name = "://MALWARE", - text = { "Add {C:dark_edition}Glitched{} to all", "cards {C:cry_code}held in hand" }, - }, - c_cry_merge = { - name = "://MERGE", - text = { - "Merge a selected {C:cry_code}consumable", - "with a selected {C:cry_code}playing card", - }, - }, - c_cry_multiply = { - name = "://MULTIPLY", - text = { - "{C:cry_code}Double{} all values of", - "a selected {C:cry_code}Joker{} until", - "end of round", - }, - }, - c_cry_payload = { - name = "://PAYLOAD", - text = { - "Next defeated Blind", - "gives {C:cry_code}X#1#{} interest", + "선택한 2개의 조커에", + "{C:cry_code}연결됨{}을 적용합니다", }, }, c_cry_oboe = { name = "://OFFBYONE", text = { - "Next {C:cry_code}Booster Pack{} has", - "{C:cry_code}#1#{} extra card and", - "{C:cry_code}#1#{} extra choice", - "{C:inactive}(Currently {C:cry_code}+#2#{C:inactive})", + "다음 {C:cry_code}부스터 팩{}은", + "{C:cry_code}#1#{}개의 추가 카드#1#와", + "{C:cry_code}#1#{}개의 추가 선택지#1#를 가집니다", + "{C:inactive}(현재 {C:cry_code}+#2#{C:inactive})", }, }, - c_cry_reboot = { - name = "://REBOOT", + c_cry_assemble = { + name = "://조립", text = { - "Replenish {C:blue}Hands{} and {C:red}Discards{},", - "return {C:cry_code}all{} cards to deck", - "and draw a {C:cry_code}new{} hand", + "소유한 조커 수만큼", + "{C:cry_code}선택한 핸드{}에", + "{C:cry_code}배수{}를 추가합니다", + }, + }, + c_cry_inst = { + name = "://인스턴스화", + text = { + "선택한 카드의 {C:cry_code}등급{}을 가진 카드와", + "선택한 카드의 {C:cry_code}문양{}을 가진 카드를 뽑습니다", + "{C:inactive}(가능한 경우){}", }, }, c_cry_revert = { - name = "://REVERT", + name = "://되돌리기", text = { - "Set {C:cry_code}game state{} to", - "start of {C:cry_code}this Ante{}", + "{C:cry_code}게임 상태{}를", + "{C:cry_code}이번 앤티{} 시작으로 되돌립니다", }, }, - c_cry_rework = { - name = "://REWORK", + c_cry_cryfunction = { + name = "FUNCTION://", text = { - "Destroy a {C:cry_code}selected{} Joker,", - "create a {C:cry_code}Rework Tag{} with", - "an {C:cry_code}upgraded{} edition", - "{C:inactive,s:0.8}Upgrades using order in the Collection", + "{C:cry_code}마지막으로 사용한 세 개{}의 소모품을 저장하고,", + "이 카드를 다시 사용하면 첫 번째 소모품의 복사본을", + "{C:cry_code}Function://{} 스티커와 함께 생성합니다", }, }, c_cry_run = { - name = "://RUN", + name = "://실행", text = { - "Visit a {C:cry_code}shop", - "during a {C:cry_code}Blind", + "{C:cry_code}블라인드{} 중에", + "{C:cry_code}상점{}을 방문합니다", }, }, - c_cry_seed = { - name = "://SEED", + c_cry_class = { + name = "://클래스", text = { - "Select a Joker", - "or playing card", - "to become {C:cry_code}Rigged", + "선택한 {C:cry_code}#1#{}장의 카드#1#를", + "{C:cry_code}선택한{} 강화로 변환합니다", }, }, - c_cry_semicolon = { - name = ";//", - text = { "Ends current non-Boss {C:cry_code}Blind{}", "{C:cry_code}without{} cashing out" }, - }, - c_cry_spaghetti = { - name = "://SPAGHETTI", + c_cry_global = { + name = "://전역", text = { - "Create a {C:cry_code}Glitched", - "Food Joker", + "플레잉 카드를 선택하여", + "{C:cry_code}전역{}으로 만듭니다", }, }, c_cry_variable = { - name = "://VARIABLE", + name = "://변수", text = { - "Convert {C:cry_code}#1#{} selected cards", - "to a {C:cry_code}chosen{} rank", + "선택한 {C:cry_code}#1#{}장의 카드#1#를", + "{C:cry_code}선택한{} 등급으로 변환합니다", + }, + }, + c_cry_log = { + name = "://로그", + text = { + "다음 정보 중 하나를 {C:cry_code}출력{}합니다: ", + "{C:attention}다음{} 앤티의 {C:attention}보스 블라인드{}와 {C:attention}바우처{},", + "상점의 다음 {C:attention}5개{}의 {C:attention}조커{}, 또는", + "다음에 {C:attention}뽑을{} {C:attention}10개{}의 플레잉 카드", + "{C:inactive}(블라인드 중인 경우){}", + }, + }, + c_cry_quantify = { + name = "://수량화", + text = { + "선택한 {C:attention}#1#{}개의", + "{C:attention}카드#1#{} 또는 {C:attention}부스터#1#{}를", + "{C:attention}조커{} 트레이로 옮깁니다", + }, + }, + c_cry_divide = { + name = "://나누기", + text = { + "현재 상점의 모든", + "가격을 {C:cry_code}절반{}으로 줄입니다", + }, + }, + c_cry_multiply = { + name = "://곱하기", + text = { + "선택한 {C:cry_code}조커{}의 모든", + "가치를 라운드 종료 시까지", + "{C:cry_code}두 배{}로 만듭니다", + }, + }, + c_cry_delete = { + name = "://삭제", + text = { + "{C:cry_code}선택한{} 상점 아이템을", + "{C:cry_code}추방{}합니다. 이번 런에서는", + "정상적으로 나타나지 않습니다", + }, + }, + c_cry_alttab = { + name = "://ALTTAB", + text = { + "{C:cry_code}현재{} 블라인드의", + "스킵 태그를 생성합니다", + "{C:inactive}(현재: {C:cry_code}#1#{C:inactive})", + }, + }, + c_cry_ctrl_v = { + name = "://CTRL+V", + text = { + "선택한 플레잉 카드 또는", + "소모품의 {C:cry_code}복사본{}을 생성합니다", + }, + }, + c_cry_reboot = { + name = "://재부팅", + text = { + "{C:blue}핸드{}와 {C:red}버리기{}를 보충하고,", + "{C:cry_code}모든{} 카드를 덱으로 되돌린 후", + "{C:cry_code}새로운{} 핸드를 뽑습니다", + }, + }, + c_cry_semicolon = { + name = ");//", + text = { + "현재 비-보스 {C:cry_code}블라인드{}를", + "정산 {C:cry_code}없이{} 종료합니다", + }, + }, + c_cry_declare = { + name = "://선언", + text = { + "{C:attention}현재{} 선택한 카드들이", + "{C:attention}#1#{}를 포함하는 것으로 간주되는", + "{C:cry_code}새로운{} 포커 핸드가 됩니다", + "최대 {C:attention}3{}개의 {C:inactive}[#2#]{} 핸드를 생성할 수 있습니다", + }, + }, + }, + ["Content Set"] = { + set_cry_blind = { + name = "블라인드", + text = { + "Cryptid가 추가한", + "{C:attention}보스 블라인드{}", + }, + }, + set_cry_code = { + name = "코드 카드", + text = { + "{C:cry_code}코드 카드{} 및", + "관련 콘텐츠", + }, + }, + set_cry_cursed = { + name = "저주받은 조커", + text = { + "{X:cry_cursed,C:white}저주받은{} 희귀도를 가진", + "해로운 조커", + }, + }, + set_cry_deck = { + name = "덱", + text = { + "Cryptid가 추가한", + "{C:attention}덱{}", + }, + }, + set_cry_epic = { + name = "에픽 조커", + text = { + "{C:cry_epic}에픽{} 희귀도를 가진", + "조커", + "{C:inactive,s:0.8}(레어와 전설 사이)", + }, + }, + set_cry_exotic = { + name = "이그조틱 조커", + text = { + "{C:cry_exotic}이그조틱{} 희귀도를 가진", + "강력한 조커", + }, + }, + set_cry_m = { + name = "M 조커", + text = { + "문자 {C:attention}M{}과", + "{C:attention}쾌활한 조커{}에 관련된", + "조커", + }, + }, + set_cry_meme = { + name = "밈", + text = { + "다양한 레퍼런스와", + "관련된 것들", + }, + }, + set_cry_misc = { + name = "기타", + text = { + "다른 {C:cry_ascendant}테마 세트{}에", + "속하지 않는", + "것들", + }, + }, + set_cry_misc_joker = { + name = "기타 조커", + text = { + "다른 {C:cry_ascendant}테마 세트{}에", + "속하지 않는", + "{C:attention}조커{}", + }, + }, + set_cry_planet = { + name = "행성 카드", + text = { + "Cryptid가 추가한", + "기타 {C:planet}행성{} 카드", + }, + }, + set_cry_poker_hand_stuff = { + name = "포커 핸드 관련", + text = { + "5개의 새로운 {C:attention}포커 핸드{}를 추가하고", + "{C:attention}승천 핸드{}를 활성화합니다", + }, + }, + set_cry_spectral = { + name = "스펙트럴 카드", + text = { + "Cryptid가 추가한", + "{C:spectral}스펙트럴{} 카드", + }, + }, + set_cry_spooky = { + name = "으스스한 업데이트", + text = { + "으스스한 업데이트 콘텐츠,", + "{C:cry_candy}사탕{} 조커 포함", + }, + }, + set_cry_tag = { + name = "태그", + text = { + "Cryptid가 추가한", + "{C:attention}태그{}", + }, + }, + set_cry_tier3 = { + name = "3등급 바우처", + text = { + "바우처의", + "추가 {C:attention}등급{}", + }, + }, + set_cry_timer = { + name = "타이머 메커니즘", + text = { + "{C:attention}시간 기반{} 효과와", + "메커니즘을 가진 아이템", + }, + }, + set_cry_voucher = { + name = "기타 바우처", + text = { + "Cryptid가 추가한", + "1, 2등급 {C:attention}바우처{}", }, }, }, Edition = { e_cry_astral = { - name = "Astral", + name = "아스트랄", text = { - "{X:dark_edition,C:white}^#1#{} Mult", + "{X:dark_edition,C:white}배수 ^#1#{}", }, }, e_cry_blur = { - name = "Blurred", + name = "흐릿함", text = { - "{C:attention}Retrigger{} this", - "card {C:attention}1{} time", - "{C:green}#1# in #2#{} chance", - "to retrigger {C:attention}#3#{}", - "additional time", + "이 카드를 {C:attention}1회{}", + "{C:attention}재발동{}합니다", + "{C:green}#2#분의 #1#{} 확률로", + "{C:attention}#3#{}회 추가 재발동", }, }, e_cry_double_sided = { - name = "Double-Sided", + name = "양면", text = { - "This card can be", - "{C:attention}flipped{} to reveal", - "a different card", - "{C:inactive}(Blank side can be merged", - "{C:inactive}with another card)", + "이 카드를 {C:attention}뒤집어서{}", + "다른 카드를", + "드러낼 수 있습니다", + "{C:inactive}(빈 면은 다른 카드와", + "{C:inactive}병합할 수 있습니다)", }, }, e_cry_glass = { - name = "Fragile", - label = "Fragile", + name = "깨지기 쉬움", + label = "깨지기 쉬움", text = { - "{C:white,X:mult} X#3# {} Mult", - "{C:green}#1# in #2#{} chance this", - "card isn't {C:red}destroyed", - "when triggered", + "{C:white,X:mult} 배수 X#3# {}", + "{C:green}#2#분의 #1#{} 확률로", + "발동 시 이 카드가", + "{C:red}파괴{}되지 않습니다", + "{C:inactive}조작 불가{}", }, }, e_cry_glitched = { - name = "Glitched", + name = "글리치", text = { - "All values on this card", - "are {C:dark_edition}randomized{}", - "between {C:attention}X0.1{} and {C:attention}X10{}", - "{C:inactive}(If possible){}", + "이 카드의 모든 값은", + "{C:attention}X0.1{}에서 {C:attention}X10{} 사이로", + "{C:dark_edition}무작위{}화됩니다", + "{C:inactive}(가능한 경우){}", }, }, e_cry_gold = { - name = "Golden", - label = "Golden", + name = "황금", + label = "황금", text = { - "Earn {C:money}$#1#{} when used", - "or triggered", + "사용 또는 발동 시", + "{C:money}$#1#{} 획득", }, }, e_cry_m = { - name = "Jolly", + name = "졸리", text = { - "{C:mult}+#1#{} Mult", - "This card is feeling", - "rather {C:attention}jolly{}", + "{C:mult}배수 +#1#{}", + "이 카드는 꽤", + "{C:attention}유쾌한{} 기분입니다", }, }, e_cry_mosaic = { - name = "Mosaic", + name = "모자이크", text = { - "{X:chips,C:white} X#1# {} Chips", + "{X:chips,C:white} 칩 X#1# {}", }, }, e_cry_noisy = { - name = "Noisy", + name = "시끄러움", text = { "???", }, }, e_cry_oversat = { - name = "Oversaturated", + name = "과포화", text = { - "All values", - "on this card", - "are {C:attention}doubled{}", - "{C:inactive}(If possible)", + "이 카드의", + "모든 값이", + "{C:attention}두 배{}가 됩니다", + "{C:inactive}(가능한 경우)", }, }, }, Enhanced = { m_cry_echo = { - name = "Echo Card", + name = "메아리 카드", text = { - "{C:green}#2# in #3#{} chance to", - "{C:attention}retrigger{} #1# additional", - "times when scored", + "점수를 얻을 때 {C:green}#3#분의 #2#{} 확률로", + "#1#회 추가", + "{C:attention}재발동{}합니다", + }, + }, + m_cry_light = { + name = "빛 카드", + text = { + "{C:attention}#4#{}장({C:inactive}#3#{})의 다른 점수 카드와", + "함께 발동 시, {X:mult,C:white}배수 X#1#{}를 얻고", + "요구 사항을 {C:attention}5{}만큼 증가시킵니다", + "{C:inactive}(현재 {X:mult,C:white}배수 X#2#{C:inactive})", + }, + }, + m_cry_abstract = { + name = "추상 카드", + text = { + "{X:dark_edition,C:white}배수 ^#1#{},", + "고유한 등급과 문양으로 취급됩니다", + "{C:green}#5#분의 #4#{} 확률로", + "{C:attention}라운드 종료{} 또는 {C:attention}핸드 플레이{} 시", + "손에 있을 때 카드를 {C:red,E:2}파괴{}합니다", }, }, }, Joker = { - j_cry_altgoogol = { - name = "Nostalgic Googol Play Card", + j_cry_adroit = { + name = "재주꾼 조커", text = { - "Sell this card to create", - "{C:attention}2{} copies of the leftmost {C:attention}Joker{}", - "{C:inactive,s:0.8}Does not copy Nostalgic Googol Play Cards{}", + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{C:chips}칩 +#1#{}", + }, + }, + j_cry_altgoogol = { + name = "향수 구골 플레이 카드", + text = { + "이 카드를 팔아 가장 왼쪽", + "{C:attention}조커{}를 {C:attention}#1#{}개 복제합니다", + "{C:inactive,s:0.8}향수 구골 플레이 카드는 복제하지 않음{}", + "{C:inactive}(공간 필요){}", }, }, j_cry_antennastoheaven = { - name = "...Like Antennas to Heaven", + name = "...천국으로 향하는 안테나처럼", text = { - "This Joker gains", - "{X:chips,C:white} X#1# {} Chips when each", - "played {C:attention}7{} or {C:attention}4{} is scored", - "{C:inactive}(Currently {X:chips,C:white}X#2# {C:inactive} Chips)", + "플레이한 {C:attention}7{} 또는 {C:attention}4{}가 점수를 얻을 때마다", + "이 조커는 {X:chips,C:white} 칩 X#1# {}를 얻습니다", + "{C:inactive}(현재 {X:chips,C:white}칩 X#2# {C:inactive})", }, }, j_cry_apjoker = { - name = "AP Joker", - text = { "{X:mult,C:white} X#1# {} Mult against {C:attention}Boss Blinds{}" }, + name = "AP 조커", + text = { "{C:attention}보스 블라인드{}에 대해 {X:mult,C:white} 배수 X#1# {}" }, + }, + j_cry_arsonist = { + name = "방화범", + text = { + "플레이한 핸드에", + "{C:attention}풀 하우스{}가 포함되어 있으면,", + "점수 계산 후 모든 카드를", + "{C:red}파괴{}합니다", + }, + }, + j_cry_astral_bottle = { + name = "병 속의 아스트랄", + text = { + "판매 시, 무작위 {C:attention}조커{}에", + "{C:dark_edition}아스트랄{}과 {C:attention}소멸성{}을", + "적용합니다", + }, }, j_cry_big_cube = { - name = "Big Cube", + name = "큰 큐브", text = { - "{X:chips,C:white} X#1# {} Chips", + "{X:chips,C:white} 칩 X#1# {}", }, }, j_cry_biggestm = { - name = "Huge", + name = "거대함", text = { - "{X:mult,C:white} X#1# {} Mult until end", - "of round if {C:attention}poker hand{}", - "is a {C:attention}#2#{}", - "{C:inactive}(Currently {C:attention}#3#{}{C:inactive}){}", - "{C:inactive,s:0.8}not fat, just big boned.", + "{C:attention}포커 핸드{}가 {C:attention}#2#{}이면 라운드", + "종료 시까지 {X:mult,C:white} 배수 X#1# {}", + "{C:inactive}(현재 {C:attention}#3#{}{C:inactive}){}", + "{C:inactive,s:0.8}뚱뚱한 게 아니라 뼈가 굵은 거야.", + }, + }, + j_cry_blacklist = { + name = "블랙리스트", + text = { + "손에 {C:attention}#1#{}가 있거나 플레이하면,", + "{C:chips}칩{}과 {C:mult}배수{}를 0으로 설정합니다", + "덱에 {C:attention}#1#{}가 없으면 {C:red,E:2}자폭{}합니다", + "{C:inactive,s:0.8}등급은 변경되지 않습니다", + }, + }, + j_cry_rotten_egg = { + name = "썩은 달걀", + text = { + "획득 시, 모든 현재 및 미래 조커의 판매 가치를 {C:attention}$#1#{}로 설정", + "모든 {C:attention}조커{}의 판매 가치를 {C:attention}$#2#{} 감소", + "라운드 종료 시, {C:attention}조커{} 판매로 {C:attention}$#3#{} {C:inactive}[#4#]{}를 얻으면 {C:red}자폭{}", }, }, j_cry_blender = { - name = "Blender", + name = "블렌더", text = { - "Create a {C:attention}random{}", - "consumable when a", - "{C:cry_code}Code{} card is used", - "{C:inactive}(Must have room){}", + "{C:cry_code}코드{} 카드를 사용할 때", + "{C:attention}무작위{} 소모품을", + "생성합니다", + "{C:inactive}(공간 필요){}", }, }, j_cry_blurred = { - name = "Blurred Joker", + name = "흐릿한 조커", text = { - "Gain {C:blue}+#1#{} hand(s) when", - "{C:attention}Blind{} is selected", + "{C:attention}블라인드{}를 선택하면", + "{C:blue}핸드 +#1#{}개#1#를 얻습니다", }, }, j_cry_bonk = { - name = "Bonk", + name = "봉크", text = { - "Each {C:attention}Joker{} gives {C:chips}+#1#{} Chips", - "Increase amount by {C:chips}+#2#{} if", - "{C:attention} poker hand{} is a {C:attention}#3#{}", - "{C:inactive,s:0.8}Jolly Jokers give{} {C:chips,s:0.8}+#4#{} {C:inactive,s:0.8}Chips instead{}", + "각 {C:attention}조커{}가 {C:chips}칩 +#1#{}을 줍니다", + "{C:attention}포커 핸드{}가 {C:attention}#3#{}이면", + "양을 {C:chips}칩 +#2#{}만큼 증가시킵니다", + "{C:inactive,s:0.8}쾌활한 조커는 대신 {C:chips,s:0.8}칩 +#4#{}를 줍니다{}", + }, + }, + j_cry_bonkers = { + name = "봉커스 조커", + text = { + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{C:red}배수 +#1#{}", }, }, j_cry_bonusjoker = { - name = "Bonus Joker", + name = "보너스 조커", text = { - "{C:green}#1# in #2#{} chance for each", - "played {C:attention}Bonus{} card to increase", - "{C:attention}Joker{} or {C:attention}Consumable slots", - "by {C:dark_edition}1{} when scored", - "{C:red}Works twice per round", - "{C:inactive,s:0.8}(Equal chance for each){}", + "플레이한 각 {C:attention}보너스{} 카드가 점수를 얻을 때", + "{C:green}#2#분의 #1#{} 확률로 {C:attention}조커{} 또는", + "{C:attention}소모품 슬롯을 {C:dark_edition}#3#{}만큼 증가시킵니다", + "{C:red}라운드당 두 번 작동합니다", + "{C:inactive,s:0.8}(각각 동일한 확률){}", }, }, j_cry_booster = { - name = "Booster Joker", + name = "부스터 조커", text = { - "{C:attention}+#1#{} Booster Pack slot", - "available in shop", + "상점에서 사용 가능한", + "{C:attention}부스터 팩 슬롯 +#1#{}개#1#", }, }, j_cry_boredom = { - name = "Boredom", + name = "지루함", text = { - "{C:green}#1# in #2#{} chance to", - "{C:attention}retrigger{} each {C:attention}Joker{}", - "or {C:attention}played card{}", - "{C:inactive,s:0.8}Does not affect other Boredom{}", + "각 {C:attention}조커{} 또는", + "{C:attention}플레이한 카드{}를 {C:attention}재발동{}할", + "{C:green}#2#분의 #1#{} 확률", + "{C:inactive,s:0.8}다른 지루함에는 영향을 미치지 않습니다{}", + }, + unlock = { + "타이틀 화면에서", + "{C:attention}10분{} 동안", + "자리 비움", + }, + }, + j_cry_brittle = { + name = "부서지기 쉬운 사탕", + text = { + "다음 {C:attention}#1#{} 핸드#1# 동안,", + "가장 오른쪽 점수 카드에", + "{C:attention}돌{}, {C:attention}황금{}, 또는 {C:attention}강철{}을 추가합니다", }, }, j_cry_bubblem = { - name = "Bubble M", + name = "버블 M", text = { - "Create a {C:dark_edition}Foil {C:attention}Jolly Joker{}", - "if played hand contains", - "a {C:attention}#1#{}", - "{C:red,E:2}self destructs{}", + "플레이한 핸드에 {C:attention}#1#{}가 포함되어 있으면", + "{C:dark_edition}포일 {C:attention}쾌활한 조커{}를 생성합니다", + "{C:red,E:2}자폭{}합니다", }, }, j_cry_busdriver = { - name = "Bus Driver", + name = "버스 기사", text = { - "{C:green}#1# in #3#{} chance", - "for {C:mult}+#2#{} Mult", - "{C:green}1 in 4{} chance", - "for {C:mult}-#2#{} Mult", + "{C:green}#3#분의 #1#{} 확률로", + "{C:mult}배수 +#2#{}", + "{C:green}#3#분의 #4#{} 확률로", + "{C:mult}배수 -#2#{}", + }, + }, + j_cry_buttercup = { + name = "버터컵", + text = { + "선택한 상점 아이템 {C:attention}#1#{}개를 저장할 수 있습니다", + "판매 시: 저장된 아이템#1#을", + "다음 상점에 추가합니다", + }, + }, + j_cry_candy_basket = { + name = "사탕 바구니", + text = { + "이 카드를 팔아 {C:attention}#1#{}개의 {C:cry_candy}사탕#1#을 생성합니다", + "매 {C:attention}#3#{} 블라인드를 이길 때마다 {C:attention}#2#{}개의 {C:cry_candy}사탕#2#{} 추가", + "{C:attention}보스 블라인드{}를 이길 때 {C:attention}#3#{}개의 {C:cry_candy}사탕#4#{} 추가", + }, + }, + j_cry_candy_buttons = { + name = "사탕 단추", + text = { + "다음 {C:attention}#1#{}번의 리롤#1#은", + "{C:money}$1{}입니다", + }, + }, + j_cry_candy_cane = { + name = "지팡이 사탕", + text = { + "다음 {C:attention}#1#{} 라운드#1# 동안,", + "플레잉 카드가 {C:attention}재발동{}될 때", + "{C:money}$#2#를 줍니다", + }, + }, + j_cry_candy_dagger = { + name = "사탕 단검", + text = { + "{C:attention}블라인드{}를 선택할 때,", + "오른쪽 조커를 파괴하여", + "{C:cry_candy}사탕{}을 생성합니다", + }, + }, + j_cry_candy_sticks = { + name = "막대 사탕", + text = { + "다음 보스 블라인드의 효과는", + "{C:attention}#1#{} 핸드#1#를 플레이하기 전까지 비활성화됩니다", }, }, j_cry_canvas = { - name = "Canvas", + name = "캔버스", text = { - "{C:attention}Retrigger{} all {C:attention}Jokers{} to the left", - "once for {C:attention}every{} non-{C:blue}Common{C:attention} Joker{}", - "to the right of this Joker", + "이 조커의 오른쪽에 있는 비-{C:blue}일반{C:attention} 조커마다", + "왼쪽에 있는 모든 {C:attention}조커{}를", + "한 번씩 {C:attention}재발동{}합니다", + }, + unlock = { + "한 핸드에서 조커를", + "{C:attention}114회{}", + "{C:attention}재발동{}하기", + }, + }, + j_cry_canvas_balanced = { + name = "캔버스", + text = { + "이 조커의 오른쪽에 있는 비-{C:blue}일반{C:attention} 조커마다", + "왼쪽에 있는 모든 {C:attention}조커{}를", + "한 번씩 {C:attention}재발동{}합니다", + "{C:inactive}(최대 2회 재발동)", + }, + unlock = { + "한 핸드에서 조커를", + "{C:attention}114회{}", + "{C:attention}재발동{}하기", }, }, j_cry_caramel = { - name = "Caramel", + name = "카라멜", text = { - "Each played card gives", - "{X:mult,C:white}X#1#{} Mult when scored", - "for the next {C:attention}#2#{} rounds", + "다음 {C:attention}#2#{} 라운드#2# 동안,", + "플레이한 각 카드가 점수를 얻을 때", + "{X:mult,C:white}배수 X#1#{}를 줍니다", + }, + }, + j_cry_cat_owl = { + name = "고양이 올빼미", + text = { + "{C:attention}럭키 카드{}는", + "{C:attention}메아리 카드{}로도 간주됩니다", + "{C:attention}메아리 카드{}는", + "{C:attention}럭키 카드{}로도 간주됩니다", }, }, j_cry_chad = { - name = "Chad", + name = "채드", text = { - "Retrigger {C:attention}leftmost{} Joker", - "{C:attention}#1#{} additional time(s)", + "가장 왼쪽 {C:attention}조커{}를", + "{C:attention}#1#{}회 추가 재발동합니다", }, }, j_cry_chili_pepper = { - name = "Chili Pepper", + name = "칠리 페퍼", text = { - "This Joker gains {X:mult,C:white} X#2# {} Mult", - "at end of round,", - "{C:red,E:2}self destructs{} after {C:attention}#3#{} rounds", - "{C:inactive}(Currently{} {X:mult,C:white} X#1# {} {C:inactive}Mult){}", + "라운드 종료 시 이 조커는 {X:mult,C:white} 배수 X#2# {}를 얻고,", + "{C:attention}#3#{} 라운드#3# 후에 {C:red,E:2}자폭{}합니다", + "{C:inactive}(현재 {X:mult,C:white} 배수 X#1# {}{C:inactive}){}", + }, + }, + j_cry_chocolate_dice = { + name = "초콜릿 주사위", + text = { + "{C:attention}보스 블라인드{}를 이길 때", + "{C:green}d10{}을 굴려", + "{C:cry_ascendant,E:1}이벤트{}를 시작합니다", + "{C:inactive}(현재: #1#)", }, }, j_cry_circulus_pistoris = { - name = "Circulus Pistoris", + name = "키르쿨루스 피스토리스", text = { - "{X:dark_edition,C:white}^#1#{} Chips and {X:dark_edition,C:white}^#1#{} Mult", - "if {C:attention}exactly{} #2#", - "hands remaining", + "남은 핸드가 {C:attention}정확히{} #2#개#2#일 경우", + "{X:dark_edition,C:white}칩 ^#1#{} 및 {X:dark_edition,C:white}배수 ^#1#{}", }, }, j_cry_circus = { - name = "Circus", + name = "서커스", + text = Cryptid.get_circus_description(), -- 자동 번역됩니다. cry_circus_generic이 번역되어 있다면 복사해도 됩니다. + unlock = { + "{C:attention}앤티 9{} 이전에", + "{C:red}레어{}, {C:cry_epic}에픽{},", + "{C:legendary}전설{} 조커를 획득하기", + }, + }, + j_cry_clash = { + name = "더 클래시", text = { - "{C:red}Rare{} Jokers each give {X:mult,C:white} X#1# {} Mult", - "{C:cry_epic}Epic{} Jokers each give {X:mult,C:white} X#2# {} Mult", - "{C:legendary}Legendary{} Jokers each give {X:mult,C:white} X#3# {} Mult", - "{C:cry_exotic}Exotic{} Jokers each give {X:mult,C:white} X#4# {} Mult", + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{X:mult,C:white} 배수 X#1# {}", + }, + unlock = { + "마지막 핸드가", + "{E:1,C:attention}얼티밋 페어{}인 상태로", + "한 판 승리", + }, + }, + j_cry_the = { + name = "더", + text = { + "플레이한 핸드가", + "{C:attention}#2#이면", + "{X:mult,C:white} 배수 X#1# {}", + }, + unlock = { + "마지막 핸드가", + "{E:1,C:attention}없음{}인 상태로", + "한 판 승리", + }, + }, + j_cry_clicked_cookie = { + name = "클릭된 쿠키", + text = { + "{C:chips}칩 +#1#{}", + "{C:attention}클릭{}할 때마다", + "{C:chips}칩 -#2#{}", + }, + }, + j_cry_clockwork = { + name = "시계태엽 조커", + text = { + "매 {C:attention}#9#{} 핸드({C:inactive}#1#{})마다 손에 든 강철 카드 재발동", + "매 {C:attention}#10#{} 핸드({C:inactive}#2#{})마다 이 조커는 {X:mult,C:white}배수 X#6#{} ({C:inactive}X#5#{})를 얻습니다", + "매 {C:attention}#11#{} 핸드({C:inactive}#3#{})마다 처음 플레이한 카드를 강철로 만듭니다", + "매 {C:attention}#12#{} 핸드({C:inactive}#4#{})마다 손에 든 강철 카드는 +{X:mult,C:white}배수 X#8#{} ({C:inactive}X#7#{})를 줍니다", }, }, j_cry_CodeJoker = { - name = "Code Joker", + name = "코드 조커", text = { - "Create a {C:dark_edition}Negative{}", - "{C:cry_code}Code Card{} when", - "{C:attention}Blind{} is selected", + "{C:attention}블라인드{}를 선택할 때", + "{C:dark_edition}네거티브{} {C:cry_code}코드 카드{}를", + "생성합니다", + }, + unlock = { + "모든 {C:attention}", + "{C:cry_code}코드 카드{} 발견", }, }, j_cry_coin = { - name = "Crypto Coin", + name = "암호화폐 코인", text = { - "Earn between", - "{C:money}$#1#{} and {C:money}$#2#{} for", - "each Joker {C:attention}sold{}", + "각 조커를 {C:attention}판매{}할 때마다", + "{C:money}$#1#{}에서 {C:money}$#2#{} 사이의", + "금액을 법니다", }, }, j_cry_compound_interest = { - name = "Compound Interest", + name = "복리", text = { - "Earn {C:money}#1#%{} of total money", - "at end of round,", - "increases by {C:money}#2#%{} per", - "consecutive payout", + "라운드 종료 시 총 금액의", + "{C:money}#1#%{}를 벌고,", + "연속 지급마다 {C:money}#2#%{}씩", + "증가합니다", }, }, j_cry_copypaste = { - name = "Copy/Paste", + name = "복사/붙여넣기", text = { - "When a {C:cry_code}Code{} card is used,", - "{C:green}#1# in #2#{} chance to add a copy", - "to your consumable area", - "{C:inactive}(Must have room)", + "사용한 {C:cry_code}코드{} 카드를 복제할", + "{C:green}#2#분의 #1#{} 확률", + "{C:red}라운드당 한 번 작동{}", + "{C:inactive}(공간 필요)", + }, + }, + j_cry_cotton_candy = { + name = "솜사탕", + text = { + "판매 시, 인접한", + "{C:attention}조커{}가 {C:dark_edition}네거티브{}가 됩니다", }, }, j_cry_crustulum = { - name = "Crustulum", + name = "크루스툴룸", text = { - "This Joker gains {C:chips}+#2#{} Chips", - "per {C:attention}reroll{} in the shop", - "{C:green}All rerolls are free{}", - "{C:inactive}(Currently {C:chips}+#1#{C:inactive} chips)", + "상점에서 {C:attention}리롤{}할 때마다", + "이 조커는 {C:chips}칩 +#2#{}을 얻습니다", + "{C:green}모든 리롤은 무료입니다{}", + "{C:inactive}(현재 {C:chips}+#1#{C:inactive} 칩)", }, }, j_cry_cryptidmoment = { - name = "M Chain", + name = "M 체인", text = { - "Sell this card to", - "add {C:money}$#1#{} of {C:attention}sell value{}", - "to every {C:attention}Joker{} card", + "이 카드를 팔아", + "모든 {C:attention}조커{} 카드에", + "{C:money}$#1#{}의 {C:attention}판매 가치{}를 추가합니다", }, }, j_cry_cube = { - name = "Cube", + name = "큐브", text = { - "{C:chips}+#1#{} Chips", + "{C:chips}칩 +#1#{}", }, }, j_cry_curse_sob = { - name = "Sob", + name = "흐느낌", text = { - "{C:edition,E:1}you cannot{} {C:cry_ascendant,E:1}run...{}", - "{C:edition,E:1}you cannot{} {C:cry_ascendant,E:1}hide...{}", - "{C:dark_edition,E:1}you cannot escape...{}", - "{C:inactive}(Must have room){}", + "{C:edition,E:1}도망칠 수 없어...{} {C:cry_ascendant,E:1}숨을 수도 없어...{}", + "{C:dark_edition,E:1}벗어날 수 없어...{}", + "{C:inactive}(공간 필요){}", + }, + unlock = { + "{C:purple}이터널{} {C:attention}오벨리스크{} 획득", }, }, j_cry_cursor = { - name = "Cursor", + name = "커서", text = { - "This Joker gains {C:chips}+#2#{} Chips", - "for each card {C:attention}purchased{}", - "{C:inactive}(Currently {C:chips}+#1#{C:inactive} Chips)", + "카드를 {C:attention}구매{}할 때마다", + "이 조커는 {C:chips}칩 +#2#{}을 얻습니다", + "{C:inactive}(현재 {C:chips}+#1#{C:inactive} 칩)", }, }, j_cry_cut = { - name = "Cut", + name = "컷", text = { - "This Joker destroys", - "a random {C:cry_code}Code{} card", - "and gains {X:mult,C:white} X#1# {} Mult", - "at the end of the {C:attention}shop{}", - "{C:inactive}(Currently {X:mult,C:white} X#2# {C:inactive} Mult)", + "{C:attention}상점{} 종료 시,", + "무작위 {C:cry_code}코드{} 카드를 파괴하여", + "이 조커는 {X:mult,C:white} 배수 X#1# {}를 얻습니다", + "{C:inactive}(현재 {X:mult,C:white} 배수 X#2# {C:inactive})", }, }, j_cry_delirious = { - name = "Delirious Joker", + name = "섬망 조커", text = { - "{C:red}+#1#{} Mult if played", - "hand contains", - "a {C:attention}#2#", + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{C:red}배수 +#1#{}", + }, + }, + j_cry_demicolon = { + name = "데미콜론", + text = { + "오른쪽 조커를", + "{C:attention}강제 발동{}합니다", + }, + }, + j_cry_starfruit = { + name = "스타프루트", + text = { + "{X:dark_edition,C:white}배수 ^#1#{},", + "상점에서 {C:attention}리롤{}할 때마다", + "{X:dark_edition,C:white}배수 ^#2#{}를 잃습니다", + }, + }, + j_cry_digitalhallucinations = { + name = "디지털 환각", + text = { + "{C:attention}부스터 팩{}을 열 때,", + "{C:green}#2#분의 #1#{} 확률로", + "해당 {C:attention}유형{}에 맞는 무작위", + "{C:dark_edition}네거티브{} 카드를 생성합니다", }, }, j_cry_discreet = { - name = "Discreet Joker", + name = "신중한 조커", text = { - "{C:chips}+#1#{} Chips if played", - "hand contains", - "a {C:attention}#2#", + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{C:chips}칩 +#1#{}", }, }, j_cry_doodlem = { - name = "Doodle M", + name = "두들 M", text = { - "Create 2 {C:dark_edition}Negative{} {C:attention}consumables{}", - "when {C:attention}Blind{} is selected", - "Create 1 more {C:attention}consumable", - "for each {C:attention}Jolly Joker{}", + "{C:attention}블라인드{}를 선택할 때", + "#2#개의 {C:dark_edition}네거티브{} {C:attention}소모품{}을 생성합니다", + "각 {C:attention}쾌활한 조커{}마다", + "#1#개의 {C:attention}소모품{}을 더 생성합니다", }, }, ["j_cry_Double Scale"] = { - name = "Double Scale", + name = "더블 스케일", text = { - "Scaling {C:attention}Jokers{}", - "scale {C:attention}quadratically", - "{C:inactive,s:0.8}(ex. +1, +3, +6, +10)", - "{C:inactive,s:0.8}(grows by +1, +2, +3)", + "스케일링 {C:attention}조커{}가", + "{C:attention}제곱{}으로 스케일링됩니다", + "{C:inactive,s:0.8}(예: +1, +3, +6, +10)", + "{C:inactive,s:0.8}(+1, +2, +3씩 증가)", }, }, j_cry_dropshot = { - name = "Dropshot", + name = "드롭샷", text = { - "This Joker gains {X:mult,C:white} X#1# {} Mult for", - "each played, {C:attention}nonscoring{} {V:1}#2#{} card,", - "suit changes every round", - "{C:inactive}(Currently {X:mult,C:white} X#3# {C:inactive} Mult)", + "플레이된, 점수를 얻지 않는 각 {V:1}#2#{} 카드마다", + "이 조커는 {X:mult,C:white} 배수 X#1# {}를 얻습니다,", + "문양은 매 라운드 변경됩니다", + "{C:inactive}(현재 {X:mult,C:white} 배수 X#3# {C:inactive})", + }, + unlock = { + "{C:attention}같은 문양{}의", + "{C:attention}4개{}의 카드로", + "{C:attention}하이 카드{} 플레이하기", }, }, j_cry_dubious = { - name = "Dubious Joker", + name = "의심스러운 조커", text = { - "{C:chips}+#1#{} Chips if played", - "hand contains", - "a {C:attention}#2#", + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{C:chips}칩 +#1#{}", }, }, j_cry_duos = { - name = "The Duos", + name = "듀오", text = { - "{X:mult,C:white} X#1# {} Mult if played", - "hand contains", - "a {C:attention}#2#", + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{X:mult,C:white} 배수 X#1# {}", + }, + unlock = { + "{E:1,C:attention}투 페어{}를 플레이하지", + "않고 한 판 승리", }, }, j_cry_duplicare = { - name = "Duplicare", + name = "듀플리카레", text = { - "Every {C:attention}Joker{} gives", - "{X:dark_edition,C:white}^#1#{} Mult", + "{C:attention}조커{} 또는 플레잉 카드가", + "점수를 얻을 때 이 조커는", + "{X:mult,C:white} 배수 X#2# {}를 얻습니다", + "{C:inactive}(현재 {X:mult,C:white} 배수 X#1# {C:inactive})", }, }, j_cry_effarcire = { - name = "Effarcire", + name = "에파르키레", text = { - "Draw {C:green}full deck{} to hand", - "when {C:attention}Blind{} is selected", - "{C:inactive,s:0.8}\"If you can't handle me at my 1x,", - "{C:inactive,s:0.8}you don't deserve me at my 2x\"", + "{C:attention}블라인드{}를 선택할 때", + "{C:green}덱 전체{}를 손으로 뽑습니다", + '{C:inactive,s:0.8}"1배일 때의 나를 감당하지 못하면,', + '{C:inactive,s:0.8}2배일 때의 나를 가질 자격이 없다"', }, }, j_cry_energia = { - name = "Energia", + name = "에네르기아", text = { - "When a {C:attention}Tag{} is acquired,", - "create {C:attention}#1#{} copies of it", - "and {C:attention}increase{} the number of", - "copies by {C:attention}#2#", + "{C:attention}태그{}를 획득하면,", + "최대 {C:attention}#1#{}개의 복사본#1#을 생성하고", + "복사본 수를 {C:attention}#2#{}만큼", + "{C:attention}증가{}시킵니다", }, }, j_cry_equilib = { - name = "Ace Aequilibrium", + name = "에이스 애퀼리브리움", text = { - "Jokers appear using the", - "order from the {C:attention}Collection{}", - "Create {C:attention}#1#{} {C:dark_edition}Negative{} Joker(s)", - "when hand is played", - "{C:cry_exotic,s:0.8}Exotic {C:inactive,s:0.8}or better Jokers cannot appear", - "{s:0.8}Last Joker Generated: {C:attention,s:0.8}#2#", + "조커가 {C:attention}컬렉션{}의", + "순서대로 나타납니다", + "핸드를 플레이할 때 {C:attention}#1#{}개의", + "{C:dark_edition}네거티브{} 조커#1#를 생성합니다", + "{C:cry_exotic,s:0.8}이그조틱{C:inactive,s:0.8} 이상의 조커는 나타날 수 없습니다", + "{s:0.8}마지막으로 생성된 조커: {C:attention,s:0.8}#2#", }, }, j_cry_error = { - name = "{C:red}ERR{}{C:dark_edition}O{}{C:red}R{}", + name = "{C:red}오{}{C:dark_edition}류{}", text = { "", }, }, j_cry_eternalflame = { - name = "Eternal Flame", + name = "영원한 불꽃", text = { - "This Joker gains {X:mult,C:white} X#1# {} Mult", - "for each card {C:attention}sold{}", - "{C:inactive}(Currently {X:mult,C:white} X#2# {C:inactive} Mult)", + "판매 가치가 {C:money}$3{} 이상인", + "카드를 {C:attention}판매{}할 때마다 이 조커는", + "{X:mult,C:white} 배수 X#1# {}를 얻습니다", + "{C:inactive}(현재 {X:mult,C:white} 배수 X#2# {C:inactive})", }, }, j_cry_exoplanet = { - name = "Exoplanet", + name = "외계 행성", text = { - "{C:dark_edition}Holographic{} cards", - "each give {C:mult}+#1#{} Mult", + "다른 {C:dark_edition}홀로그래픽{} 카드는", + "각각 {C:mult}배수 +#1#{}를 줍니다", }, }, j_cry_exponentia = { - name = "Exponentia", + name = "엑스포넨티아", text = { - "This Joker gains {X:dark_edition,C:white} ^#1# {} Mult", - "when {X:red,C:white} XMult {} is triggered", - "{C:inactive}(Currently {X:dark_edition,C:white} ^#2# {C:inactive} Mult)", + "{X:red,C:white} X배수 {}가 발동될 때", + "이 조커는 {X:dark_edition,C:white} 배수 ^#1# {}를 얻습니다", + "{C:inactive}(현재 {X:dark_edition,C:white} 배수 ^#2# {C:inactive})", + }, + }, + j_cry_exposed = { + name = "노출됨", + text = { + "점수를 얻은 모든 비-{C:attention}페이스{} 카드를", + "{C:attention}#1#{}회 추가 재발동합니다", + "모든 {C:attention}페이스{} 카드는 디버프됩니다", + }, + }, + j_cry_eyeofhagane = { + name = "하가네의 눈", + text = { + "플레이한 모든 {C:attention}페이스{} 카드는", + "점수를 얻을 때 {C:attention}강철{} 카드가 됩니다", + }, + }, + j_cry_highfive = { + name = "하이파이브", + text = { + "가장 높은 {C:attention}점수 등급{}이 {C:attention}5{}이면,", + "{C:attention}모든{} 점수 카드를 {C:attention}5{}로 변환합니다", + "{s:0.8,C:inactive}에이스는 1로 간주됩니다", }, }, j_cry_facile = { - name = "Facile", + name = "파실레", text = { - "{X:dark_edition,C:white}^#1#{} Mult if", - "played cards are scored", - "{C:attention}#2#{} or fewer times", + "플레이한 카드가 {C:attention}#2#{}회", + "이하로 점수를 얻으면", + "{X:dark_edition,C:white}배수 ^#1#{}", + }, + }, + j_cry_familiar_currency = { + name = "익숙한 화폐", + text = { + "라운드 종료 시 {C:money}$#1#{}에", + "{C:attention}밈 조커{}를 생성합니다 {C:inactive}(가능한 경우)", + "{C:inactive}(공간 필요)", }, }, j_cry_filler = { - name = "The Filler", + name = "필러", text = { - "{X:mult,C:white} X#1# {} Mult if played", - "hand contains", - "a {C:attention}#2#", + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{X:mult,C:white} 배수 X#1# {}", + }, + unlock = { + "{E:1,C:attention}하이 카드{}를 플레이하지", + "않고 한 판 승리", }, }, j_cry_fractal = { - name = "Fractal Fingers", + name = "프랙탈 손가락", text = { - "{C:attention}+#1#{} card selection limit", + "카드 선택 제한 {C:attention}+#1#{}", + }, + unlock = { + "{C:attention}스트레이트{}가 {C:attention}플러시{}가", + "아닌 상태로 {C:attention}스트레이트 플러시{} 플레이하기", }, }, j_cry_flip_side = { - name = "On the Flip Side", + name = "반면에", text = { - "{C:dark_edition}Double-Sided{} Jokers use", - "their back side for effects", - "instead of the front side", - "{C:attention}Retrigger{} all {C:dark_edition}Double-Sided{} Jokers", + "{C:dark_edition}양면{} 조커는 앞면 대신", + "뒷면의 효과를 사용합니다", + "모든 {C:dark_edition}양면{} 조커를 {C:attention}재발동{}합니다", }, }, j_cry_foodm = { - name = "Fast Food M", + name = "패스트푸드 M", text = { - "{C:mult}+#1#{} Mult", - "{C:red,E:2}self destructs{} in {C:attention}#2#{} round(s)", - "Increases by {C:attention}#3#{} round when", - "{C:attention}Jolly Joker{} is {C:attention}sold{}", - "{C:inactive,s:0.8}2 McDoubles, 2 McChickens{}", - "{C:inactive,s:0.8}Large Fries, 20 Piece & Large Cake{}", + "{C:mult}배수 +#1#{}", + "{C:attention}#2#{} 라운드#2# 후에 {C:red,E:2}자폭{}합니다", + "{C:attention}쾌활한 조커{}가 {C:attention}판매{}될 때", + "{C:attention}#3#{} 라운드만큼 증가합니다", + }, + }, + j_cry_foolhardy = { + name = "무모한 조커", + text = { + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{C:red}배수 +#1#{}", + }, + }, + j_cry_undefined = { + name = "정의되지 않은 조커", + text = { + "플레이한 핸드가", + "{C:attention}#2#이면", + "{C:red}배수 +#1#{}", + }, + }, + j_cry_formidiulosus = { + name = "포르미디울로수스", + text = { + "{X:cry_cursed,C:white}저주받은{} 조커를 획득하면 파괴합니다", + "상점 종료 시 {C:attention}#1#{}개의 {C:dark_edition}네거티브 {C:cry_candy}사탕#1#{}을 생성합니다", + "소지한 각 {C:cry_candy}사탕{}마다 {X:dark_edition,C:white}배수 ^#2#{}를 얻습니다", + "{C:inactive}(현재 {X:dark_edition,C:white}배수 ^#3#{C:inactive})", }, }, j_cry_foxy = { - name = "Foxy Joker", + name = "여우 조커", text = { - "{C:chips}+#1#{} Chips if played", - "hand contains", - "a {C:attention}#2#", + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{C:chips}칩 +#1#{}", }, }, j_cry_fspinner = { - name = "Fidget Spinner", + name = "피젯 스피너", text = { - "This Joker gains {C:chips}+#2#{} Chips", - "if hand played is {C:attention}not{}", - "most played {C:attention}poker hand{}", - "{C:inactive}(Currently {C:chips}+#1#{C:inactive} Chips)", + "플레이한 핸드가 가장 많이 플레이한", + "{C:attention}포커 핸드{}가 {C:attention}아닐{} 경우,", + "이 조커는 {C:chips}칩 +#2#{}을 얻습니다", + "{C:inactive}(현재 {C:chips}+#1#{C:inactive} 칩)", + }, + }, + j_cry_fuckedup = { + name = Cryptid_config.family_mode and "깔끔한 조커" or "개판 조커", + text = { + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{C:red}배수 +#1#{}", }, }, j_cry_gardenfork = { - name = "Garden of Forking Paths", + name = "갈림길의 정원", text = { - "Earn {C:money}$#1#{} if {C:attention}played hand{}", - "contains an {C:attention}Ace{} and a {C:attention}7{}", + "{C:attention}플레이한 핸드{}에 {C:attention}에이스{}와", + "{C:attention}7{}이 포함되어 있으면 {C:money}$#1#{}를 법니다", }, }, j_cry_gemino = { - name = "Gemini", + name = "제미니", text = { - "{C:attention}Double{} all values", - "of leftmost {C:attention}Joker", - "at end of round", + "라운드 종료 시 가장 왼쪽", + "{C:attention}조커{}의 모든 값을", + "{C:attention}두 배{}로 만듭니다", + }, + }, + j_cry_ghost = { + name = "유령", + text = { + "라운드 종료 시:", + "{C:green}#3#분의 #1#{} 확률로", + "무작위 {C:attention}조커{}에 {C:attention}빙의{}합니다", + "{C:green}#4#분의 #2#{} 확률로", + "{E:2,C:red}자폭{}합니다", }, }, j_cry_giggly = { - name = "Absurd Joker", + name = "터무니없는 조커", text = { - "{C:red}+#1#{} Mult if played", - "hand contains", - "a {C:attention}#2#", + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{C:red}배수 +#1#{}", }, }, j_cry_goldjoker = { - name = "Gold Joker", + name = "황금 조커", text = { - "Earn {C:money}#1#%{} of total", - "money at end of round", - "Payout increases by {C:money}#2#%{}", - "when each played {C:attention}Gold{}", - "card is scored", + "라운드 종료 시", + "총 금액의 {C:money}#1#%{}를 법니다", + "플레이한 각 {C:attention}황금{} 카드가", + "점수를 얻을 때마다 지급액이", + "{C:money}#2#%{} 증가합니다", }, }, j_cry_googol_play = { - name = "Googol Play Card", + name = "구골 플레이 카드", text = { - "{C:green}#1# in #2#{} chance for", - "{X:red,C:white} X#3# {} Mult", + "{X:red,C:white} 배수 X#3# {}를 얻을", + "{C:green}#2#분의 #1#{} 확률", + }, + unlock = { + "한 핸드에서", + "{C:attention}1.0e100{} 칩{}을", + "득점하기", }, }, j_cry_happy = { name = ":D", text = { - "Create a random {C:attention}Joker{}", - "at end of round", - "Sell this card to", - "create a random {C:attention}Joker{}", - "{C:inactive}(Must have room){}", + "라운드 종료 시", + "무작위 {C:attention}조커{}를 생성합니다", + "이 카드를 팔아", + "무작위 {C:attention}조커{}를 생성합니다", + "{C:inactive}(공간 필요){}", }, }, j_cry_happyhouse = { - name = "Happy House", + name = "행복한 집", text = { - "{X:dark_edition,C:white}^#1#{} Mult only after", - "playing {C:attention}114{} hands{}", - "{C:inactive}(Currently #2#/114){}", - "{C:inactive,s:0.8}There is no place like home!{}", + "{C:attention}#3#{} 핸드{}를 플레이한 후에만", + "{X:dark_edition,C:white}배수 ^#1#{}", + "{C:inactive}(현재 #2#/#3#){}", + "{C:inactive,s:0.8}집만한 곳이 없지!{}", }, }, j_cry_home = { - name = "The Home", + name = "집", text = { - "{X:mult,C:white} X#1# {} Mult if played", - "hand contains", - "a {C:attention}#2#", + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{X:mult,C:white} 배수 X#1# {}", + }, + unlock = { + "{E:1,C:attention}풀 하우스{}를 플레이하지", + "않고 한 판 승리", }, }, j_cry_hunger = { - name = "Consume-able", + name = "소비 가능", text = { - "Earn {C:money}$#1#{} when", - "using a {C:attention}consumable{}", + "{C:attention}소모품{}을 사용할 때", + "{C:money}$#1#{}를 법니다", + }, + }, + j_cry_huntingseason = { + name = "사냥 시즌", + text = { + "플레이한 핸드에 정확히 {C:attention}3{}장의 카드가 포함되어 있으면,", + "점수 계산 후 {C:attention}가운데{} 카드를 {C:red}파괴{}합니다", }, }, j_cry_iterum = { - name = "Iterum", + name = "이테룸", text = { - "Retrigger all cards played", - "{C:attention}#2#{} time(s),", - "each played card gives", - "{X:mult,C:white} X#1# {} Mult when scored", + "플레이한 모든 카드를 {C:attention}#2#{}회#2# 재발동하고,", + "플레이한 각 카드가 점수를 얻을 때", + "{X:mult,C:white} 배수 X#1# {}를 줍니다", + "{C:inactive}(최대 {}{C:attention}#3#{}{C:inactive}회 재발동)", + }, + }, + j_cry_jawbreaker = { + name = "턱 깨물기", + text = { + "{C:attention}보스 블라인드{}를 이길 때,", + "인접한 조커의 값을 {C:attention}두 배{}로 만듭니다", + "{E:2,C:red}자폭{}합니다", }, }, j_cry_jimball = { - name = "Jimball", + name = "짐볼", text = { - "This Joker gains {X:mult,C:white} X#1# {} Mult", - "per {C:attention}consecutive{} hand played", - "while playing your", - "most played {C:attention}poker hand", - "{C:inactive}(Currently {X:mult,C:white} X#2# {C:inactive} Mult)", + "가장 많이 플레이한 {C:attention}포커 핸드{}를", + "플레이하는 동안 {C:attention}연속{}으로 플레이한", + "핸드마다 이 조커는 {X:mult,C:white} 배수 X#1# {}를 얻습니다", + "{C:inactive}(현재 {X:mult,C:white} 배수 X#2# {C:inactive})", + }, + unlock = { + "{C:attention}단일 종류{}의", + "{C:attention}포커 핸드{}만 플레이하며", + "한 판 승리", }, }, j_cry_jollysus = { - name = "Jolly Joker?", + name = "쾌활한 조커?", text = { - "Create a {C:dark_edition}Jolly{} Joker", - "when a Joker is {C:attention}sold{}", - "{C:red}Works once per round{}", + "조커를 {C:attention}판매{}할 때", + "{C:dark_edition}쾌활한{} 조커를 생성합니다", + "{C:red}라운드당 한 번 작동{}", "{C:inactive}#1#{}", - "{C:inactive,s:0.8}Seems legit...{}", + "{C:inactive,s:0.8}믿을만한데...{}", + }, + }, + j_cry_jtron = { + name = "짐보-트론 9000", + text = { + "각 기본 {C:attention}조커{}마다", + "이 조커는 {X:dark_edition,C:white} 배수 ^#1# {}를 얻습니다", + "{C:inactive}(현재 {X:dark_edition,C:white}배수 ^#2#{C:inactive})", }, }, j_cry_kidnap = { - name = "Kidnapping", + name = "납치", text = { - "Earn {C:money}$#2#{} at end of round", - "Increase payout by {C:money}$#1#{}", - "when a {C:attention}Type Mult{} or", - "{C:attention}Type Chips{} Joker is sold", + "이번 런에서 판매된 고유한 {C:attention}타입 배수{} 또는", + "{C:attention}타입 칩{} 조커당 라운드 종료 시", + "{C:money}$#1#{}를 법니다", + "{C:inactive}(현재 {C:money}$#2#{C:inactive})", + }, + }, + j_cry_kittyprinter = { + name = "고양이 프린터", + text = { + "{X:mult,C:white} 배수 X#1# {}", + "모든 {C:attention}스킵{} 태그가", + "{C:attention}고양이 태그{}가 됩니다", }, }, j_cry_kooky = { - name = "Kooky Joker", + name = "쿠키 조커", text = { - "{C:red}+#1#{} Mult if played", - "hand contains", - "a {C:attention}#2#", + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{C:red}배수 +#1#{}", }, }, j_cry_krustytheclown = { - name = "Krusty the Clown", + name = "광대 크러스티", text = { - "This Joker gains", - "{X:mult,C:white} X#1# {} Mult when", - "each played {C:attention}card{} is scored", - "{C:inactive}(Currently {X:mult,C:white} X#2# {C:inactive} Mult)", + "플레이한 각 {C:attention}카드{}가 점수를 얻을 때마다", + "이 조커는 {X:mult,C:white} 배수 X#1# {}를 얻습니다", + "{C:inactive}(현재 {X:mult,C:white} 배수 X#2# {C:inactive})", }, }, j_cry_kscope = { - name = "Kaleidoscope", + name = "만화경", text = { - "Add {C:dark_edition}Polychrome{} to", - "a random {C:attention}Joker{} when", - "{C:attention}Boss Blind{} is defeated", + "{C:attention}보스 블라인드{}를 이길 때", + "무작위 {C:attention}조커{}에", + "{C:dark_edition}폴리크롬{}을 추가합니다", + }, + unlock = { + "{C:attention}5개{} 이상의 {C:attention}에디션 카드{} 또는", + "{C:attention}조커{}로 {C:attention}보스 블라인드{}를", + "이기기", + }, + }, + j_cry_lebaron_james = { + name = "르바론 제임스", + text = { + "플레이하고 점수를 얻은 {C:attention}킹{}은", + "라운드 동안 핸드 크기를 {C:attention}+#1#{}만큼 증가시키고", + "{C:attention}손에 들고 있을 때{} 효과를 발동합니다", + "{C:inactive}(현재 {}{C:attention}+#2#{}{C:inactive})", }, }, j_cry_lightupthenight = { - name = "Light Up the Night", + name = "밤을 밝혀라", text = { - "Each played {C:attention}7{} or {C:attention}2{}", - "gives {X:mult,C:white}X#1#{} Mult when scored", + "플레이한 각 {C:attention}7{} 또는 {C:attention}2{}가 점수를 얻을 때", + "{X:mult,C:white}배수 X#1#{}를 줍니다", }, }, j_cry_longboi = { - name = "Monster", + name = "괴물", text = { - "Give future copies of", - "this Joker {X:mult,C:white}X#1#{} Mult", - "at end of round", - "{C:inactive}(Currently {X:mult,C:white}X#2#{C:inactive} Mult){}", + "라운드 종료 시 이 조커의", + "미래 복사본에 {X:mult,C:white}배수 X#1#{}를 줍니다", + "{C:inactive}(현재 {X:mult,C:white}배수 X#2#{C:inactive}){}", }, }, j_cry_loopy = { - name = "Loopy", + name = "루피", text = { - "{C:attention}Retrigger{} all Jokers", - "once for each {C:attention}Jolly{}", - "{C:attention}Joker{} sold this round", - "{C:inactive}(Currently{}{C:attention:} #1#{}{C:inactive} Retrigger(s)){}", - "{C:inactive,s:0.8}There wasn't enough room...{}", + "이번 라운드에 판매된 각 {C:attention}쾌활한{}", + "{C:attention}조커{}마다 모든 조커를", + "한 번씩 {C:attention}재발동{}합니다", + "{C:inactive}(현재{}{C:attention:} #1#{}{C:inactive}회 재발동){}", + "{C:inactive,s:0.8}공간이 부족했어...{}", }, }, j_cry_lucky_joker = { - name = "Lucky Joker", + name = "행운의 조커", text = { - "Earn {C:money}$#1#{} every time a", - "{C:attention}Lucky{} card {C:green}successfully{}", - "triggers", + "{C:attention}럭키{} 카드가 {C:green}성공적{}으로", + "발동할 때마다 {C:money}$#1#{}를 법니다", }, }, j_cry_luigi = { - name = "Luigi", + name = "루이지", text = { - "All Jokers give", - "{X:chips,C:white} X#1# {} Chips", + "모든 조커가", + "{X:chips,C:white} 칩 X#1# {}를 줍니다", }, }, j_cry_m = { name = "m", text = { - "This Joker gains {X:mult,C:white} X#1# {} Mult", - "when {C:attention}Jolly Joker{} is sold", - "{C:inactive}(Currently {X:mult,C:white} X#2# {C:inactive} Mult)", + "{C:attention}쾌활한 조커{}를 판매할 때", + "이 조커는 {X:mult,C:white} 배수 X#1# {}를 얻습니다", + "{C:inactive}(현재 {X:mult,C:white} 배수 X#2# {C:inactive})", }, }, j_cry_M = { name = "M", text = { - "Create a {C:dark_edition}Negative{}", - "{C:attention}Jolly Joker{} when", - "{C:attention}Blind{} is selected", + "{C:attention}블라인드{}를 선택할 때", + "{C:dark_edition}네거티브{} {C:attention}쾌활한 조커{}를", + "생성합니다", }, }, j_cry_macabre = { - name = "Macabre Joker", + name = "섬뜩한 조커", text = { - "When {C:attention}Blind{} is selected,", - "destroys each {C:attention}Joker{} except", - "{C:legendary}M Jokers{} and {C:attention}Jolly Jokers{}", - "and create 1 {C:attention}Jolly Joker{}", - "for each destroyed card", + "{C:attention}블라인드{}를 선택할 때,", + "{C:legendary}M 조커{}와 {C:attention}쾌활한 조커{}를 제외한", + "각 {C:attention}조커{}를 파괴하고 파괴된 카드마다", + "#1#개의 {C:attention}쾌활한 조커#1#{}를 생성합니다", }, }, j_cry_magnet = { - name = "Fridge Magnet", + name = "냉장고 자석", text = { - "Earn {C:money}$#1#{} at end of round", - "This earns {X:money,C:white} X#2# {} if there are", - "{C:attention}#3#{} or fewer {C:attention}Joker{} cards", + "라운드 종료 시 {C:money}$#1#{}를 법니다", + "{C:attention}#3#{}개 이하의 {C:attention}조커{} 카드가 있으면", + "이 금액은 {X:money,C:white} X#2# {}가 됩니다", }, }, j_cry_manic = { - name = "Manic Joker", + name = "조증 조커", text = { - "{C:red}+#1#{} Mult if played", - "hand contains", - "a {C:attention}#2#", + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{C:red}배수 +#1#{}", }, }, j_cry_mario = { - name = "Mario", + name = "마리오", text = { - "Retrigger all Jokers", - "{C:attention}#1#{} additional time(s)", + "모든 조커를", + "{C:attention}#1#{}회 추가 재발동합니다", + }, + }, + j_cry_mask = { + name = "가면", + text = { + "점수를 얻은 모든 {C:attention}페이스{} 카드를", + "{C:attention}#1#{}회 추가 재발동합니다", + "모든 비-{C:attention}페이스{} 카드는 디버프됩니다", }, }, j_cry_maximized = { - name = "Maximized", + name = "최대화됨", text = { - "All {C:attention}face{} cards", - "are considered {C:attention}Kings{},", - "all {C:attention}numbered{} cards", - "are considered {C:attention}10s{}", + "모든 {C:attention}페이스{} 카드는", + "{C:attention}킹{}으로 간주되고,", + "모든 {C:attention}숫자{} 카드는", + "{C:attention}10{}으로 간주됩니다", + }, + unlock = { + "{C:attention}킹{}으로 구성된", + "{C:attention}플러시 파이브{} 플레이하기", }, }, j_cry_maze = { - name = "Labyrinth", + name = "미궁", text = { - "All hands are considered the", - "{C:attention}first hand{} of each round,", - "all discards are considered the", - "{C:attention}first discard{} of each round", + "모든 핸드는 각 라운드의", + "{C:attention}첫 번째 핸드{}로 간주되고,", + "모든 버리기는 각 라운드의", + "{C:attention}첫 번째 버리기{}로 간주됩니다", }, }, - j_cry_Megg = { - name = "Megg", + j_cry_megg = { + name = "메그", text = { - "Sell this card to create", - "{C:attention}#2#{} Jolly #3#, increase", - "by {C:attention}#1#{} at end of round", + "이 카드를 팔아", + "{C:attention}#2#{}개의 졸리 #3#을 생성하고, 라운드 종료 시", + "{C:attention}#1#{}만큼 증가시킵니다", + }, + }, + j_cry_mellowcreme = { + name = "멜로크림", + text = { + "이 카드를 팔아 모든", + "{C:attention}소모품{}의 판매 가치를", + "{C:attention}X#1#배로 곱합니다", }, }, j_cry_membershipcard = { - name = "Membership Card", + name = "멤버십 카드", text = { - "{X:mult,C:white}X#1#{} Mult for each member", - "in the {C:attention}Cryptid Discord{}", - "{C:inactive}(Currently {X:mult,C:white}X#2#{C:inactive} Mult)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:attention}Cryptid 디스코드{}의 각 멤버당", + "{X:mult,C:white}배수 X#1#{}", + "{C:inactive}(현재 {X:mult,C:white}배수 X#2#{C:inactive})", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_membershipcardtwo = { - name = "Old Membership Card", --Could probably have a diff Name imo + name = "구 멤버십 카드", text = { - "{C:chips}+#1#{} Chips for each member", - "in the {C:attention}Cryptid Discord{}", - "{C:inactive}(Currently {C:chips}+#2#{C:inactive} Chips)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:attention}Cryptid 디스코드{}의 각 멤버당", + "{C:chips}칩 +#1#{}", + "{C:inactive}(현재 {C:chips}칩 +#2#{C:inactive})", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_meteor = { - name = "Meteor Shower", + name = "유성우", text = { - "{C:dark_edition}Foil{} cards each", - "give {C:chips}+#1#{} Chips", + "다른 {C:dark_edition}포일{} 카드는", + "각각 {C:chips}칩 +#1#{}를 줍니다", }, }, j_cry_mneon = { - name = "Neon M", + name = "네온 M", text = { - "Earn {C:money}$#2#{} at end of round", - "Increase payout by", - "{C:money}$#1#{} for each {C:attention}Jolly Joker{}", - "or {C:legendary}M Joker{} at", - "end of round", + "라운드 종료 시 {C:money}$#2#{}를 법니다", + "라운드 종료 시 각 {C:attention}쾌활한 조커{} 또는", + "{C:legendary}M 조커{}마다 지급액을", + "{C:money}$#1#{}만큼 증가시킵니다", }, }, j_cry_mondrian = { - name = "Mondrian", + name = "몬드리안", text = { - "This Joker gains {X:mult,C:white} X#1# {} Mult", - "if no {C:attention}discards{} were", - "used this round", - "{C:inactive}(Currently {X:mult,C:white} X#2# {C:inactive} Mult)", + "이번 라운드에 {C:attention}버리기{}를", + "사용하지 않았을 경우 이 조커는", + "{X:mult,C:white} 배수 X#1# {}를 얻습니다", + "{C:inactive}(현재 {X:mult,C:white} 배수 X#2# {C:inactive})", }, }, j_cry_monkey_dagger = { - name = "Monkey Dagger", + name = "원숭이 단검", text = { - "When {C:attention}Blind{} is selected,", - "destroy Joker to the left", - "and permanently add {C:attention}ten times{}", - "its sell value to this {C:chips}Chips{}", - "{C:inactive}(Currently {C:chips}+#1#{C:inactive} Chips)", + "{C:attention}블라인드{}를 선택할 때,", + "왼쪽 조커를 파괴하고 그 판매 가치의", + "{C:attention}열 배{}를 이 {C:chips}칩{}에 영구적으로 추가합니다", + "{C:inactive}(현재 {C:chips}+#1#{C:inactive} 칩)", + }, + }, + j_cry_monopoly_money = { + name = "모노폴리 돈", + text = { + "구매한 아이템을 {C:attention}파괴{}할", + "{C:green}#2#분의 #1#{} 확률", + "{C:attention}판매{} 시 돈을 절반으로 줄입니다", }, }, j_cry_morse = { - name = "Morse Code", + name = "모스 부호", text = { - "Earn {C:money}$#2#{} at end of round", - "Increase payout by {C:money}$#1#{} when", - "a card with an {C:attention}Edition{} is sold", + "라운드 종료 시 {C:money}$#2#{}를 법니다", + "{C:attention}에디션{}이 있는 카드를 판매할 때마다", + "지급액을 {C:money}$#1#{}만큼 증가시킵니다", }, }, j_cry_mprime = { - name = "Tredecim", + name = "트레데킴", text = { - "Create an {C:legendary}M Joker{} at end of round", - "Each {C:attention}Jolly Joker{} or {C:legendary}M Joker", - "gives {X:dark_edition,C:white}^#1#{} Mult", - "Increase amount by {X:dark_edition,C:white}^#2#{}", - "when a {C:attention}Jolly Joker{} is {C:attention}sold", - "{C:inactive,s:0.8}(Tredecim excluded)", + "라운드 종료 시 {C:legendary}M 조커{}를 생성합니다", + "각 {C:attention}쾌활한 조커{} 또는 {C:legendary}M 조커{}는", + "{X:dark_edition,C:white}배수 ^#1#{}를 줍니다", + "{C:attention}쾌활한 조커{}를 {C:attention}판매{}할 때", + "양을 {X:dark_edition,C:white}배수 ^#2#{}만큼 증가시킵니다", + "{C:inactive,s:0.8}(트레데킴 제외)", }, }, j_cry_mstack = { - name = "M Stack", + name = "M 스택", text = { - "Retrigger all cards played", - "once for every", - "{C:attention}#2#{} {C:inactive}[#3#]{} {C:attention}Jolly Jokers{} sold", - "{C:inactive}(Currently{}{C:attention:} #1#{}{C:inactive} retriggers){}", + "판매된 {C:attention}#2#{}개의 {C:inactive}[#3#]{} {C:attention}쾌활한 조커#2#{}마다", + "플레이한 모든 카드를 한 번씩 재발동합니다", + "{C:inactive}(현재{}{C:attention:} #1#{}{C:inactive}회 재발동){}", }, }, j_cry_multjoker = { - name = "Mult Joker", + name = "멀트 조커", text = { - "{C:green}#1# in #2#{} chance for each", - "played {C:attention}Mult{} card to create", - "a {C:spectral}Cryptid{} card when scored", - "{C:inactive}(Must have room)", + "플레이한 각 {C:attention}멀트{} 카드가 점수를 얻을 때", + "{C:green}#2#분의 #1#{} 확률로 {C:spectral}크립티드{} 카드를", + "생성합니다", + "{C:inactive}(공간 필요)", + }, + }, + j_cry_necromancer = { + name = "네크로맨서", + text = { + "조커를 {C:attention}#1#{}보다 비싸게 {C:attention}판매{}하면,", + "이번 런에서 판매된 {C:attention}무작위{} 조커를", + "{C:money}#1#{} 판매 가치로 얻습니다", }, }, j_cry_negative = { - name = "Negative Joker", + name = "네거티브 조커", text = { - "{C:dark_edition}+#1#{C:attention} Joker{} slots", + "{C:dark_edition}조커 슬롯 +#1#{}{C:attention}", }, }, j_cry_nice = { - name = "Nice", + name = "나이스", text = { - "{C:chips}+#1#{} Chips if played hand", - "contains a {C:attention}6{} and a {C:attention}9", - "{C:inactive,s:0.8}Nice.{}", + "플레이한 핸드에 {C:attention}6{}과 {C:attention}9{}가", + "포함되어 있으면 {C:chips}칩 +#1#{}", + "{C:inactive,s:0.8}나이스.{}", }, }, j_cry_night = { - name = "Night", + name = "밤", text = { - "{X:dark_edition,C:white}^#1#{} Mult on final", - "hand of round", - "{E:2,C:red}self destructs{} on", - "final hand of round", + "라운드의 마지막 핸드에", + "{X:dark_edition,C:white}배수 ^#1#{}", + "라운드의 마지막 핸드에", + "{E:2,C:red}자폭{}합니다", }, }, j_cry_nosound = { - name = "No Sound, No Memory", + name = "소리도, 기억도 없이", text = { - "Retrigger each played {C:attention}7{}", - "{C:attention:}#1#{} additional time(s)", + "플레이한 각 {C:attention}7{}을", + "{C:attention:}#1#{}회 추가 재발동합니다", }, }, j_cry_notebook = { - name = "Notebook", + name = "모트북", text = { - "{C:green} #1# in #2#{} chance to gain {C:dark_edition}+1{} Joker", - "slot per {C:attention}reroll{} in the shop", - "{C:green}Always triggers{} if there are", - "{C:attention}#5#{} or more {C:attention}Jolly Jokers{}", - "{C:red}Works once per round{}", - "{C:inactive}(Currently {C:dark_edition}+#3#{}{C:inactive} and #4#){}", + "상점에서 {C:attention}리롤{}할 때마다 {C:green} #2#분의 #1#{} 확률로", + "{C:dark_edition}조커 슬롯 +#6#{}을 얻습니다", + "{C:attention}#5#{}개 이상의 {C:attention}쾌활한 조커{}가 있으면", + "{C:green}항상 발동{}합니다", + "{C:red}라운드당 한 번 작동{}", + "{C:inactive}(현재 {C:dark_edition}+#3#{}{C:inactive} 및 #4#){}", }, }, j_cry_number_blocks = { - name = "Number Blocks", + name = "숫자 블록", text = { - "Earn {C:money}$#1#{} at end of round", - "Increase payout by {C:money}$#2#{}", - "for each {C:attention}#3#{} held in hand,", - "rank changes every round", + "라운드 종료 시 {C:money}$#1#{}를 법니다", + "손에 든 각 {C:attention}#3#{}마다 지급액을", + "{C:money}$#2#{}만큼 증가시킵니다,", + "등급은 매 라운드 변경됩니다", }, }, j_cry_nuts = { - name = "The Nuts", + name = "더 넛츠", text = { - "{X:mult,C:white} X#1# {} Mult if played", - "hand contains", - "a {C:attention}#2#", + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{X:mult,C:white} 배수 X#1# {}", + }, + unlock = { + "{E:1,C:attention}스트레이트 플러시{}를 플레이하지", + "않고 한 판 승리", }, }, j_cry_nutty = { - name = "Nutty Joker", + name = "너티 조커", text = { - "{C:red}+#1#{} Mult if played", - "hand contains", - "a {C:attention}#2#", + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{C:red}배수 +#1#{}", + }, + }, + j_cry_oil_lamp = { + name = "오일 램프", + text = { + "라운드 종료 시 오른쪽", + "{C:attention}조커{}의 값을 {C:attention}X#1#{}만큼 증가시킵니다", }, }, j_cry_oldblueprint = { - name = "Old Blueprint", + name = "오래된 청사진", text = { - "Copies ability of", - "{C:attention}Joker{} to the right", - "{C:green}#1# in #2#{} chance this", - "card is destroyed", - "at end of round", + "오른쪽 {C:attention}조커{}의", + "능력을 복사합니다", + "라운드 종료 시 이 카드가", + "파괴될 {C:green}#2#분의 #1#{} 확률", }, }, j_cry_oldcandy = { - name = "Nostalgic Candy", + name = "향수 사탕", text = { - "Sell this card to", - "permanently gain", - "{C:attention}+#1#{} hand size", + "이 카드를 팔아", + "영구적으로 {C:attention}핸드 크기 +#1#{}을", + "얻습니다", }, }, j_cry_oldinvisible = { - name = "Nostalgic Invisible Joker", + name = "향수 투명 조커", text = { - "{C:attention}Duplicate{} a random", - "{C:attention}Joker{} every {C:attention}4", - "Joker cards sold", - "{s:0.8}Nostalgic Invisible Joker Excluded{}", - "{C:inactive}(Currently #1#/4){}", + "조커 카드를 4장 판매할 때마다", + "무작위 {C:attention}조커{}를 {C:attention}복제{}합니다", + "{s:0.8}향수 투명 조커 제외{}", + "{C:inactive}(현재 #1#/4){}", }, }, j_cry_panopticon = { - name = "Panopticon", + name = "파놉티콘", text = { - "All hands are considered the", - "{C:attention}last hand{} of each round", -- +$4 + "모든 핸드는 각 라운드의", + "{C:attention}마지막 핸드{}로 간주됩니다", + }, + }, + j_cry_penetrating = { + name = "관통 조커", + text = { + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{C:chips}칩 +#1#{}", }, }, j_cry_pickle = { - name = "Pickle", + name = "피클", text = { - "When {C:attention}Blind{} is skipped, create", - "{C:attention}#1#{} Tags, reduced by", - "{C:red}#2#{} when {C:attention}Blind{} is selected", + "{C:attention}블라인드{}를 스킵할 때 {C:attention}#1#{}개의 태그를 생성하고,", + "{C:attention}블라인드{}를 선택할 때 {C:red}#2#{}만큼 감소합니다", }, }, j_cry_pirate_dagger = { - name = "Pirate Dagger", + name = "해적 단검", text = { - "When {C:attention}Blind{} is selected,", - "destroy Joker to the right", - "and gain {C:attention}one-fourth{} of", - "its sell value as {X:chips,C:white} XChips {}", - "{C:inactive}(Currently {X:chips,C:white} X#1# {C:inactive} Chips)", + "{C:attention}블라인드{}를 선택할 때,", + "오른쪽 조커를 파괴하고 그 판매 가치의", + "{C:attention}4분의 1{}을 {X:chips,C:white} X칩 {}으로 얻습니다", + "{C:inactive}(현재 {X:chips,C:white} X#1# {C:inactive} 칩)", + }, + }, + j_cry_pity_prize = { + name = "위로상", + text = { + "{C:attention}부스터 팩{}을 스킵할 때,", + "무작위 {C:attention}태그{}를 얻습니다", }, }, j_cry_pot_of_jokes = { - name = "Pot of Jokes", + name = "농담의 냄비", text = { - "{C:attention}#1#{} hand size,", - "increases by", - "{C:blue}#2#{} every round", + "{C:attention}핸드 크기 #1#{},", + "매 라운드마다", + "{C:blue}#2#{}씩 증가합니다", + "{C:inactive}(최대 {}{C:attention}#3#{}{C:inactive} 핸드 크기){}", + }, + unlock = { + "{C:attention}핸드 크기{}를", + "{C:attention}12{}로 늘리기", }, }, j_cry_primus = { - name = "Primus", + name = "프라이머스", text = { - "This Joker gains {X:dark_edition,C:white} ^#1# {} Mult", - "if all cards in played hand are", - "{C:attention}Aces{}, {C:attention}2s{}, {C:attention}3s{}, {C:attention}5s{}, or {C:attention}7s{}", - "{C:inactive}(Currently {X:dark_edition,C:white} ^#2# {C:inactive} Mult)", + "플레이한 핸드의 모든 카드가 {C:attention}에이스{}, {C:attention}2{},", + "{C:attention}3{}, {C:attention}5{}, 또는 {C:attention}7{}일 경우,", + "이 조커는 {X:dark_edition,C:white} 배수 ^#1# {}를 얻습니다", + "{C:inactive}(현재 {X:dark_edition,C:white} 배수 ^#2# {C:inactive})", + }, + }, + j_cry_pumpkin = { + name = "호박", + text = { + "얻은 칩이 요구 칩의 {C:attention}50%{} 이상이면", + "죽음을 방지합니다", + "{C:red}파괴{}되면 {C:attention}조각된 호박{}으로", + "{C:attention}변합니다", + }, + }, + j_cry_carved_pumpkin = { + name = "조각된 호박", + text = { + "다음 {C:attention}#1#{}개의 보스 블라인드의", + "능력이", + "{C:attention}비활성화{}됩니다", }, }, j_cry_python = { - name = "Python", + name = "파이썬", text = { - "This Joker gains", - "{X:mult,C:white} X#1# {} Mult when a", - "{C:cry_code}Code{} card is used", - "{C:inactive}(Currently {X:mult,C:white} X#2# {C:inactive} Mult)", + "{C:cry_code}코드{} 카드를 사용할 때마다", + "이 조커는 {X:mult,C:white} 배수 X#1# {}를 얻습니다", + "{C:inactive}(현재 {X:mult,C:white} 배수 X#2# {C:inactive})", }, }, j_cry_queens_gambit = { - name = "Queen's Gambit", + name = "퀸스 갬빗", text = { - "If {C:attention}poker hand{} is a", - "{C:attention}Royal Flush{}, destroy scored", - "{C:attention}Queen{} and create a", - "{C:dark_edition}Negative {}{C:red}Rare{}{C:attention} Joker{}", + "{C:attention}포커 핸드{}가 {C:attention}로열 플러시{}이면,", + "점수를 얻은 {C:attention}퀸{}을 파괴하고", + "{C:dark_edition}네거티브 {}{C:red}레어{}{C:attention} 조커{}를 생성합니다", }, }, j_cry_quintet = { - name = "The Quintet", + name = "퀸텟", text = { - "{X:mult,C:white} X#1# {} Mult if played", - "hand contains", - "a {C:attention}#2#", + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{X:mult,C:white} 배수 X#1# {}", + }, + unlock = { + "마지막 핸드가", + "{E:1,C:attention}파이브 오브 어 카인드{}인 상태로", + "한 판 승리", }, }, j_cry_redbloon = { - name = "Red Bloon", + name = "레드 블룬", text = { - "Earn {C:money}$#1#{} in {C:attention}#2#{} round(s)", - "{C:red,E:2}self destructs{}", + "{C:attention}#2#{} 라운드#2# 후에", + "{C:money}$#1#{}를 법니다", + "{C:red,E:2}자폭{}합니다", }, }, j_cry_redeo = { - name = "Redeo", + name = "레데오", text = { - "{C:attention}-#1#{} Ante when", - "{C:money}$#2#{} {C:inactive}($#3#){} spent", - "{s:0.8}Requirements increase", - "{C:attention,s:0.8}exponentially{s:0.8} per use", - "{C:money,s:0.8}Next increase: {s:1,c:money}$#4#", + "{C:money}$#2#{} {C:inactive}($#3#{})를 쓸 때마다", + "{C:attention}앤티 -#1#{}", + "{s:0.8}요구 사항은 사용마다", + "{C:attention,s:0.8}기하급수적으로{s:0.8} 증가합니다", + "{C:money,s:0.8}다음 증가: {s:1,c:money}$#4#", }, }, j_cry_rescribere = { - name = "Rescribere", + name = "레스크리베레", text = { - "When a {C:attention}Joker{} is sold,", - "add its effects to", - "every other Joker", - "{C:inactive,s:0.8}Does not affect other Rescribere{}", + "{C:attention}조커{}를 판매하면,", + "그 효과를 다른 모든", + "조커에 추가합니다", + "{C:inactive,s:0.8}다른 레스크리베레에는 영향을 미치지 않습니다{}", }, }, j_cry_reverse = { - name = "Reverse Card", + name = "리버스 카드", text = { - "Fill all empty Joker slots {C:inactive}(Max 100){}", - "with {C:dark_edition}Holographic{} {C:attention}Jolly Jokers{} if", - "{C:attention}discarded poker hand{} is a {C:attention}#1#{}", - "{C:red,E:2}self destructs{}", - "{C:inactive,s:0.8}The ULTIMATE comeback{}", + "{C:attention}버린 포커 핸드{}가 {C:attention}#1#{}이면,", + "모든 빈 조커 슬롯을 {C:dark_edition}홀로그래픽{}", + "{C:attention}쾌활한 조커{}로 채웁니다 {C:inactive}(최대 100개){}", + "{C:red,E:2}자폭{}합니다", + "{C:inactive,s:0.8}궁극의 역전승{}", }, }, j_cry_rnjoker = { - name = "RNJoker", + name = "RN조커", text = { - "Randomize abilities each {C:attention}Ante{}", + "매 {C:attention}앤티{}마다 능력을", + "무작위로 변경합니다", + }, + unlock = { + "{C:green}20분의 1{} 확률로", + "{C:attention}게임 오버{} 시", + "이 카드를 잠금 해제합니다", }, }, j_cry_sacrifice = { - name = "Sacrifice", + name = "희생", text = { - "Create an {C:green}Uncommon{} Joker", - "and 3 {C:attention}Jolly Jokers{} when", - "a {C:spectral}Spectral{} card is used", - "{C:red}Works once per round{}", + "{C:spectral}스펙트럴{} 카드를 사용할 때", + "#3#개의 {C:green}희귀{} 조커#3#와", + "#2#개의 {C:attention}쾌활한 조커#2#{}를 생성합니다", + "{C:red}라운드당 한 번 작동{}", "{C:inactive}#1#{}", }, }, j_cry_sapling = { - name = "Sapling", + name = "묘목", text = { - "After scoring {C:attention}#2#{} {C:inactive}[#1#]{} Enhanced", - "cards, sell this card to", - "create an {C:cry_epic}Epic{} {C:attention}Joker{}", - "{C:inactive,s:0.8}Will create a {C:red,s:0.8}Rare{} {C:attention,s:0.8}Joker{}", - "{C:inactive,s:0.8}if {C:cry_epic,s:0.8}Epic{} {C:inactive,s:0.8}Jokers are disabled{}", + "{C:attention}#2#{}개의 {C:inactive}[#1#]{} 강화 카드를 점수 계산 후,", + "이 카드를 팔아 #4#개의", + "{V:1}#3#{} {C:attention}조커{}를 생성합니다", }, }, j_cry_savvy = { - name = "Savvy Joker", + name = "새비 조커", text = { - "{C:chips}+#1#{} Chips if played", - "hand contains", - "a {C:attention}#2#", + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{C:chips}칩 +#1#{}", }, }, j_cry_Scalae = { - name = "Scalae", + name = "스칼라에", text = { - "Scaling {C:attention}Jokers{} scale", - "as a degree-{C:attention}#1#{} polynomial", - "raise degree by {C:attention}#2#{}", - "at end of round", - "{C:inactive,s:0.8}({C:attention,s:0.8}Scalae{C:inactive,s:0.8} excluded)", + "스케일링 {C:attention}조커{}는", + "{C:attention}#1#{}차 다항식으로 스케일링됩니다", + "라운드 종료 시 차수를", + "{C:attention}#2#{}만큼 올립니다", + "{C:inactive,s:0.8}({C:attention,s:0.8}스칼라에{C:inactive,s:0.8} 제외)", + "{C:inactive,s:0.8}(예: +1, +#3#, +#4#, +#5#)", }, }, j_cry_scrabble = { - name = "Scrabble Tile", + name = "스크래블 타일", text = { - "{C:green}#1# in #2#{} chance to create", - "a {C:dark_edition}Jolly {C:green}Uncommon{} Joker", - "when hand is played", + "핸드를 플레이할 때", + "{C:green}#2#분의 #1#{} 확률로 {C:dark_edition}졸리{}", + "{C:green}희귀{} 조커를 생성합니다", }, }, j_cry_seal_the_deal = { - name = "Seal the Deal", + name = "거래 성사", text = { - "Add a {C:attention}random seal{} to each card", - "scored on {C:attention}final hand{} of round", + "라운드의 {C:attention}마지막 핸드{}에서 점수를 얻은", + "각 카드에 {C:attention}무작위 봉인{}을 추가합니다", }, }, j_cry_shrewd = { - name = "Shrewd Joker", + name = "기민한 조커", text = { - "{C:chips}+#1#{} Chips if played", - "hand contains", - "a {C:attention}#2#", + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{C:chips}칩 +#1#{}", }, }, j_cry_silly = { - name = "Silly Joker", + name = "어리석은 조커", text = { - "{C:red}+#1#{} Mult if played", - "hand contains", - "a {C:attention}#2#", + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{C:red}배수 +#1#{}", }, }, j_cry_smallestm = { - name = "Tiny", + name = "작음", text = { - "Create a {C:cry_jolly}Double M", - "tag if {C:attention}poker hand{}", - "is a {C:attention}#1#{}", - "{C:inactive,s:0.8}ok so basically i'm very smol", + "{C:attention}포커 핸드{}가 {C:attention}#1#{}이면", + "{C:cry_jolly}더블 M 태그{}를 생성합니다", + "{C:inactive,s:0.8}음 그러니까 기본적으로 난 아주 작아", }, }, j_cry_soccer = { - name = "One for All", --changed the name from latin because this isn't exotic + name = "모두를 위한 하나", text = { - "{C:attention}+#1#{} Joker slot", - "{C:attention}+#1#{} Booster Pack slot", - "{C:attention}+#1#{} hand size", - "{C:attention}+#1#{} consumable slot", - "{C:attention}+#1#{} card in shop", + "{C:attention}조커 슬롯 +#1#{}", + "{C:attention}부스터 팩 슬롯 +#1#{}", + "핸드 크기 {C:attention}+#1#{}", + "{C:attention}소모품 슬롯 +#1#{}", + "상점 카드 {C:attention}+#1#{}개", + "{C:attention}바우처 슬롯 +#1#{}", + }, + unlock = { + "{C:attention}하이 카드{}만으로", + "한 판 승리", + }, + }, + j_cry_fleshpanopticon = { + name = "살점 파놉티콘", + text = { + "{C:red}보스 블라인드{} 크기 X#1#{}", + "{C:attention}보스 블라인드{}를 이기면,", + "{C:red}자폭{}하고 {C:dark_edition}네거티브{}", + "{C:spectral}관문{} 카드를 생성합니다", + '{C:inactive,s:0.8}"이 감옥이... 나를... 가두려고?"', + }, + }, + j_cry_sock_and_sock = { + name = "양말과 양말", + text = { + "플레이한 모든 {C:attention}추상{} 카드를", + "{C:attention}#1#{}회 재발동합니다", + }, + }, + j_cry_brokenhome = { + name = "망가진 집", + text = { + "{X:mult,C:white} 배수 X#1# {}", + "라운드 종료 시 이 카드가", + "파괴될 {C:green}#3#분의 #2#{} 확률", + }, + }, + j_cry_yarnball = { + name = "털실 뭉치", + text = { + "가장 높은 레벨의 {C:attention}고양이 태그{}의 레벨을", + "모든 {C:green}나열된 확률{}에 추가합니다", + }, + }, + j_cry_pizza = { + name = "피자", + text = { + "{C:attention}#1#{} {C:inactive}[#2#]{} 라운드#1# 후", + "이 조커를 팔아 {C:attention}#3#{}개의", + "피자 조각을 생성합니다", + }, + }, + j_cry_pizza_slice = { + name = "피자 조각", + text = { + "{C:attention}피자 조각{}을 판매할 때", + "이 조커는 {X:mult,C:white}배수 X#1#{}를 얻습니다", + "{C:inactive}(현재 {X:mult,C:white}배수 X#2#{}{C:inactive}){}", + }, + }, + j_cry_paved_joker = { + name = "포장된 조커", + text = { + "돌 카드는 {C:attention}스트레이트{}와", + "{C:attention}플러시{}에서 {C:attention}#1#{}개의", + "공백을 채울 수 있습니다", + }, + }, + j_cry_fading_joker = { + name = "사라지는 조커", + text = { + "{C:attention}소멸성{} 카드가 디버프될 때마다", + "이 조커는 {X:mult,C:white}배수 X#1#{}를 얻습니다", + "{C:inactive}(현재 {X:mult,C:white}배수 X#2#{} {C:inactive}){}", + }, + }, + j_cry_poor_joker = { + name = "가난한 조커", + text = { + "{C:attention}임대{} 카드가 돈을 가져갈 때마다", + "이 조커는 {C:mult}배수 +#1#{}를 얻습니다", + "{C:inactive}(현재 {C:mult}배수 +#2#{} {C:inactive}){}", }, }, j_cry_spaceglobe = { - name = "Celestial Globe", + name = "천체구", text = { - "This Joker gains {X:chips,C:white}X#2#{} Chips", - "if {C:attention}poker hand{} is a {C:attention}#3#{},", - "Hand changes after increase{}", - "{C:inactive}(Currently{} {X:chips,C:white}X#1#{} {C:inactive}Chips){}", + "{C:attention}포커 핸드{}가 {C:attention}#3#{}이면,", + "이 조커는 {X:chips,C:white}칩 X#2#{}를 얻습니다,", + "증가 후 핸드가 변경됩니다{}", + "{C:inactive}(현재 {X:chips,C:white}칩 X#1#{} {C:inactive}){}", + }, + }, + j_cry_spectrogram = { + name = "스펙트로그램", + text = { + "플레이하고 점수를 얻은 각", + "{C:attention}메아리 카드{}마다", + "가장 오른쪽 조커를 한 번씩 재발동합니다", }, }, j_cry_speculo = { - name = "Speculo", + name = "스페쿨로", text = { - "Creates a {C:dark_edition}Negative{} copy", - "of a random {C:attention}Joker{}", - "at the end of the {C:attention}shop", - "{C:inactive,s:0.8}Does not copy other Speculo{}", + "{C:attention}상점{} 종료 시", + "무작위 {C:attention}조커{}의 {C:dark_edition}네거티브{} 복사본을", + "생성합니다", + "{C:inactive,s:0.8}다른 스페쿨로는 복사하지 않습니다{}", + }, + }, + j_cry_spy = { + name = "스파이", + text = { + "{X:mult,C:white} 배수 X#2# {}, {C:dark_edition}조커 슬롯 +1{}{C:attention}", + "{C:inactive}저 #1#는 스파이야!", }, }, j_cry_stardust = { - name = "Stardust", + name = "별가루", text = { - "{C:dark_edition}Polychrome{} cards", - "each give {X:mult,C:white}X#1#{} Mult", + "다른 {C:dark_edition}폴리크롬{} 카드는", + "각각 {X:mult,C:white}배수 X#1#{}를 줍니다", }, }, j_cry_stella_mortis = { - name = "Stella Mortis", + name = "스텔라 모르티스", text = { - "This Joker destroys a", - "random {C:planet}Planet{} card", - "and gains {X:dark_edition,C:white} ^#1# {} Mult", - "at the end of the {C:attention}shop{}", - "{C:inactive}(Currently {X:dark_edition,C:white} ^#2# {C:inactive} Mult)", + "{C:attention}상점{} 종료 시,", + "무작위 {C:planet}행성{} 카드를 파괴하여", + "이 조커는 {X:dark_edition,C:white} 배수 ^#1# {}를 얻습니다", + "{C:inactive}(현재 {X:dark_edition,C:white} 배수 ^#2# {C:inactive})", + }, + }, + j_cry_stronghold = { + name = "요새", + text = { + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{X:mult,C:white} 배수 X#1# {}", + }, + unlock = { + "마지막 핸드가", + "{E:1,C:attention}보루{}인 상태로", + "한 판 승리", }, }, j_cry_subtle = { - name = "Subtle Joker", + name = "교묘한 조커", text = { - "{C:chips}+#1#{} Chips if played", - "hand contains", - "a {C:attention}#2#", + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{C:chips}칩 +#1#{}", }, }, j_cry_supercell = { - name = "Supercell", + name = "슈퍼셀", text = { - "{C:chips}+#1#{} Chips, {C:mult}+#1#{} Mult,", - "{X:chips,C:white}X#2#{} Chips, {X:mult,C:white}X#2#{} Mult", - "Earn {C:money}$#3#{} at", - "end of round", + "{C:chips}칩 +#1#{}, {C:mult}배수 +#1#{},", + "{X:chips,C:white}칩 X#2#{}, {X:mult,C:white}배수 X#2#{}", + "라운드 종료 시", + "{C:money}$#3#{}를 법니다", }, }, j_cry_sus = { name = "SUS", text = { - "At end of round, create", - "a {C:attention}copy{} of a random", - "card {C:attention}held in hand{},", - "destroy all others", - "{C:attention,s:0.8}Kings{s:0.8} of {C:hearts,s:0.8}Hearts{s:0.8} are prioritized", + "라운드 종료 시, 손에 든", + "무작위 카드의 {C:attention}복사본{}을 생성하고,", + "다른 모든 카드를 파괴합니다", + "{C:attention,s:0.8}하트{s:0.8}의 {C:hearts,s:0.8}킹{s:0.8}이 우선 순위입니다", }, }, j_cry_swarm = { - name = "The Swarm", + name = "스웜", text = { - "{X:mult,C:white} X#1# {} Mult if played", - "hand contains", - "a {C:attention}#2#", + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{X:mult,C:white} 배수 X#1# {}", + }, + unlock = { + "마지막 핸드가", + "{E:1,C:attention}플러시 파이브{}인 상태로", + "한 판 승리", }, }, j_cry_sync_catalyst = { - name = "Sync Catalyst", + name = "동기화 촉매", text = { - "Balances {C:chips}Chips{} and {C:mult}Mult{}", - "{C:inactive,s:0.8}Hey! I've seen this one before!", + "{C:chips}칩{}과 {C:mult}배수{}의", + "균형을 맞춥니다", + "{C:inactive,s:0.8}어! 이거 전에 본 적 있는데!", + }, + }, + j_cry_tax_fraud = { + name = "탈세", + text = { + "라운드 종료 시 각 {C:attention}임대 조커{}당", + "{C:attention}$#1#{}를 얻습니다", }, }, j_cry_tenebris = { - name = "Tenebris", + name = "테네브리스", text = { - "{C:dark_edition}+#1#{C:attention} Joker{} slots", - "Earn {C:money}$#2#{} at end of round", + "{C:dark_edition}조커 슬롯 +#1#{}{C:attention}", + "라운드 종료 시 {C:money}$#2#{}를 법니다", }, }, j_cry_translucent = { - name = "Translucent Joker", + name = "반투명 조커", text = { - "Sell this card to create", - "a {C:attention}Banana Perishable{} copy", - "of a random {C:attention}Joker{}", - "{s:0.8,C:inactive}(Copy bypasses perish compat)", + "이 카드를 팔아 무작위", + "{C:attention}조커{}의 {C:attention}바나나 소멸성{} 복사본을", + "생성합니다", + "{s:0.8,C:inactive}(복사본은 소멸 호환성을 우회합니다)", + }, + }, + j_cry_treacherous = { + name = "배신적인 조커", + text = { + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{C:chips}칩 +#1#{}", + }, + }, + j_cry_nebulous = { + name = "성운 조커", + text = { + "플레이한 핸드가", + "{C:attention}#2#이면", + "{C:chips}칩 +#1#{}", + }, + }, + j_cry_words_cant_even = { + name = "말로 다 표현할 수 없는 조커", + text = { + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{X:mult,C:white}배수 X#1#{}", + }, + }, + j_cry_many_lost_minds = { + name = "이 조커를 이해하다가 많은 이들이 정신을 잃었다", + text = { + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{C:chips}칩 +#1#{}", + }, + }, + j_cry_trick_or_treat = { + name = "트릭 오어 트릿", + text = { + "{C:attention}판매{} 시:", + "{C:green}#2#분의 #1#{} 확률로 {C:attention}#3#{}개의 {C:cry_candy}사탕{} 생성", + "그렇지 않으면 {X:cry_cursed,C:white}저주받은{} 조커 생성", + "{C:inactive}(초과 가능)", }, }, j_cry_tricksy = { - name = "Tricksy Joker", + name = "교활한 조커", text = { - "{C:chips}+#1#{} Chips if played", - "hand contains", - "a {C:attention}#2#", + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{C:chips}칩 +#1#{}", }, }, j_cry_triplet_rhythm = { - name = "Triplet Rhythm", + name = "셋잇단 리듬", text = { - "{X:mult,C:white} X#1# {} Mult if scoring hand", - "contains {C:attention}exactly{} three {C:attention}3s", + "점수 핸드에 {C:attention}정확히{} 세 개의", + "{C:attention}3{}이 포함되어 있으면 {X:mult,C:white} 배수 X#1# {}", + }, + }, + j_cry_tropical_smoothie = { + name = "열대 스무디", + text = { + "이 카드를 팔아", + "소유한 조커의 배수을", + "{C:attention}X#1#{}배로 {C:attention}곱합니다{}", }, }, j_cry_unity = { - name = "The Unity", + name = "통합", text = { - "{X:mult,C:white} X#1# {} Mult if played", - "hand contains", - "a {C:attention}#2#", + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{X:mult,C:white} 배수 X#1# {}", + }, + unlock = { + "마지막 핸드가", + "{E:1,C:attention}플러시 하우스{}인 상태로", + "한 판 승리", + }, + }, + j_cry_universe = { + name = "우주", + text = { + "다른 {C:dark_edition}아스트랄{} 카드는", + "각각 {X:dark_edition,C:white}배수 ^#1#{}를 줍니다", }, }, j_cry_universum = { - name = "Universum", + name = "우니베르숨", text = { - "{C:attention}Poker hands{} gain", - "{X:red,C:white} X#1# {} Mult and {X:blue,C:white} X#1# {} Chips", - "when leveled up", + "{C:attention}포커 핸드{}가 레벨 업될 때", + "{X:red,C:white} 배수 X#1# {}와 {X:blue,C:white} 칩 X#1# {}를", + "얻습니다", }, }, j_cry_unjust_dagger = { - name = "Unjust Dagger", + name = "부당한 단검", text = { - "When {C:attention}Blind{} is selected,", - "destroy Joker to the left", - "and gain {C:attention}one-fifth{} of", - "its sell value as {X:mult,C:white} XMult {}", - "{C:inactive}(Currently {X:mult,C:white} X#1# {C:inactive} Mult)", + "{C:attention}블라인드{}를 선택할 때,", + "왼쪽 조커를 파괴하고 그 판매 가치의", + "{C:attention}5분의 1{}을 {X:mult,C:white} X배수 {}로 얻습니다", + "{C:inactive}(현재 {X:mult,C:white} X#1# {C:inactive} 배수)", }, }, j_cry_verisimile = { - name = "Non Verisimile", + name = "논 베리시밀레", text = { - "When any probability", - "is {C:green}successfully{} triggered,", - "this Joker gains {X:red,C:white}XMult{}", - "equal to its listed {C:attention}odds", - "{C:inactive}(Currently {X:mult,C:white} X#1# {C:inactive} Mult)", + "어떤 확률이든 {C:green}성공적{}으로 발동되면,", + "이 조커는 나열된 {C:attention}확률{}과", + "같은 {X:red,C:white}X배수{}를 얻습니다", + "{C:inactive}(현재 {X:mult,C:white} X#1# {C:inactive} 배수)", }, }, j_cry_virgo = { - name = "Virgo", + name = "처녀자리", text = { - "This Joker gains {C:money}$#1#{} of {C:attention}sell value{}", - "if {C:attention}poker hand{} contains a {C:attention}#2#{}", - "Sell this card to create a", - "{C:dark_edition}Polychrome{} {C:attention}Jolly Joker{} for", - "every {C:money}$4{} of {C:attention}sell value{} {C:inactive}(Min 1){}", + "{C:attention}포커 핸드{}에 {C:attention}#2#{}가 포함되어 있으면,", + "이 조커는 {C:money}$#1#{}의 {C:attention}판매 가치{}를 얻습니다", + "판매 가치 {C:money}$4{}마다 {C:dark_edition}폴리크롬{}", + "{C:attention}쾌활한 조커{}를 생성하기 위해 이 카드를 판매합니다", + "{C:inactive}(최소 1개){}", }, }, j_cry_wacky = { - name = "Wacky Joker", + name = "괴짜 조커", text = { - "{C:red}+#1#{} Mult if played", - "hand contains", - "a {C:attention}#2#", + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{C:red}배수 +#1#{}", }, }, j_cry_waluigi = { - name = "Waluigi", + name = "와루이지", text = { - "All Jokers give", - "{X:mult,C:white} X#1# {} Mult", + "모든 조커가", + "{X:mult,C:white} 배수 X#1# {}를 줍니다", }, }, j_cry_wario = { - name = "Wario", + name = "와리오", text = { - "All Jokers give", - "{C:money}$#1#{} when triggered", + "모든 조커가 발동될 때", + "{C:money}$#1#{}를 줍니다", }, }, j_cry_wee_fib = { - name = "Weebonacci", + name = "위보나치", text = { - "This Joker gains", - "{C:mult}+#2#{} Mult when each played", - "{C:attention}Ace{}, {C:attention}2{}, {C:attention}3{}, {C:attention}5{}, or {C:attention}8{}", - "is scored", - "{C:inactive}(Currently {C:mult}+#1#{C:inactive} Mult)", + "플레이한 각 {C:attention}에이스{}, {C:attention}2{},", + "{C:attention}3{}, {C:attention}5{}, 또는 {C:attention}8{}이 점수를 얻을 때마다", + "이 조커는 {C:mult}배수 +#2#{}를 얻습니다", + "{C:inactive}(현재 {C:mult}배수 +#1#{C:inactive})", }, }, j_cry_weegaming = { name = "2D", text = { - "Retrigger each played {C:attention}2{}", --wee gaming - "{C:attention:}#1#{} additional time(s)", --wee gaming? - "{C:inactive,s:0.8}Wee Gaming?{}", + "플레이한 각 {C:attention}2{}를", + "{C:attention:}#1#{}회 추가 재발동합니다", + "{C:inactive,s:0.8}위 게이밍?{}", }, }, j_cry_wheelhope = { - name = "Wheel of Hope", + name = "희망의 수레바퀴", text = { - "This Joker gains", - "{X:mult,C:white} X#1# {} Mult when failing", - "a {C:attention}Wheel of Fortune{}", - "{C:inactive}(Currently {X:mult,C:white} X#2# {C:inactive} Mult)", + "{C:attention}운명의 수레바퀴{}에 실패할 때마다", + "이 조커는 {X:mult,C:white} 배수 X#1# {}를 얻습니다", + "{C:inactive}(현재 {X:mult,C:white} 배수 X#2# {C:inactive})", }, }, j_cry_whip = { - name = "The WHIP", + name = "더 윕", text = { - "This Joker gains {X:mult,C:white} X#1# {} Mult", - "if {C:attention}played hand{} contains a", - "{C:attention}2{} and {C:attention}7{} of different suits", - "{C:inactive}(Currently {X:mult,C:white} X#2# {C:inactive} Mult)", + "{C:attention}플레이한 핸드{}에 다른 문양의", + "{C:attention}2{}와 {C:attention}7{}이 포함되어 있으면,", + "이 조커는 {X:mult,C:white} 배수 X#1# {}를 얻습니다", + "{C:inactive}(현재 {X:mult,C:white} 배수 X#2# {C:inactive})", + }, + }, + j_cry_wonka_bar = { + name = "웡카 바", + text = { + "이 카드를 팔아 영구적으로", + "{C:attention}카드 선택 제한 +#1#{}을", + "얻습니다", + }, + }, + j_cry_wrapped = { + name = "포장된 사탕", + text = { + "{C:attention}#1#{} 라운드#1# 후에", + "무작위 {C:attention}음식 조커{}를 생성합니다", + "{C:red,E:2}자폭{}합니다", + }, + }, + j_cry_wtf = { + name = Cryptid_config.family_mode and "클러스터" or "이런 젠장!?", + text = { + "플레이한 핸드에", + "{C:attention}#2#가 포함되어 있으면", + "{X:mult,C:white} 배수 X#1# {}", + }, + unlock = { + "마지막 핸드가", + "{E:1,C:attention}#1#{}인 상태로", + "한 판 승리", + }, + }, + j_cry_zooble = { + name = "주블", + text = { + "플레이한 핸드에 {C:attention}스트레이트{}가", + "{C:attention}포함되어 있지 않으면{}, 점수 핸드의", + "각 {C:attention}고유 등급{}마다 이 조커는", + "{C:mult}배수 +#2#{}를 얻습니다", + "{C:inactive}(현재 {C:mult}배수 +#1#{C:inactive})", }, }, }, Planet = { - c_cry_Klubi = { - name = "Klubi", + c_cry_asteroidbelt = { + name = "소행성대", text = { - "({V:1}lvl.#4#{})({V:2}lvl.#5#{})({V:3}lvl.#6#{})", - "Level up", - "{C:attention}#1#{},", - "{C:attention}#2#{},", - "and {C:attention}#3#{}", + "{S:0.8}({S:0.8,V:1}레벨 #1#{S:0.8}){} {C:attention}#2#", + "레벨 업", + "{C:mult}배수 +#3#{} 및", + "{C:chips}칩 +#4#{}", }, }, - c_cry_Lapio = { - name = "Lapio", + c_cry_void = { + name = "공허", text = { - "({V:1}lvl.#4#{})({V:2}lvl.#5#{})({V:3}lvl.#6#{})", - "Level up", - "{C:attention}#1#{},", - "{C:attention}#2#{},", - "and {C:attention}#3#{}", + "{S:0.8}({S:0.8,V:1}레벨 #1#{S:0.8}){} {C:attention}#2#", + "레벨 업", + "{C:mult}배수 +#3#{} 및", + "{C:chips}칩 +#4#{}", }, }, - c_cry_nstar = { - name = "Neutron Star", + c_cry_marsmoons = { + name = "포보스 & 데이모스", text = { - "Upgrade a random", - "poker hand by", - "{C:attention}1{} level for each", - "{C:attention}Neutron Star{} used", - "in this run", - "{C:inactive}(Currently{C:attention} #1#{C:inactive}){}", + "{S:0.8}({S:0.8,V:1}레벨 #1#{S:0.8}){} {C:attention}#2#", + "레벨 업", + "{C:mult}배수 +#3#{} 및", + "{C:chips}칩 +#4#{}", + }, + }, + c_cry_nibiru = { + name = "니비루", + text = { + "{S:0.8}({S:0.8,V:1}레벨 #1#{S:0.8}){} {C:attention}#2#", + "레벨 업", + "{C:mult}배수 +#3#{} 및", + "{C:chips}칩 +#4#{}", + }, + }, + c_cry_universe = { + name = Cryptid_config.family_mode and "우주" or "빌어먹을 우주 전체", + text = { + "{S:0.8}({S:0.8,V:1}레벨 #1#{S:0.8}){} {C:attention}#2#", + "레벨 업", + "{C:mult}배수 +#3#{} 및", + "{C:chips}칩 +#4#{}", }, }, c_cry_planetlua = { name = "Planet.lua", text = { - "{C:green}#1# in #2#{} chance to", - "upgrade every", - "{C:legendary,E:1}poker hand{}", - "by {C:attention}1{} level", + "{C:green}#2#분의 #1#{} 확률로", + "모든 {C:legendary,E:1}포커 핸드{}를", + "{C:attention}1{} 레벨 업그레이드합니다", + }, + }, + c_cry_nstar = { + name = "중성자별", + text = { + "이번 런에서 사용된 각", + "{C:attention}중성자별{}마다 무작위", + "포커 핸드를 {C:attention}1{} 레벨", + "업그레이드합니다", + "{C:inactive}(현재 {C:attention}#1#{C:inactive}){}", + }, + }, + c_cry_sunplanet = { + name = "솔", + text = { + "{S:0.8}({S:0.8,V:1}레벨 #1#{S:0.8}){}", + "{C:attention}승천{} 핸드의", + "능력을 {X:gold,C:white}#2#{}만큼 증가시킵니다", + "{C:inactive}(현재 {X:gold,C:white}X(#3#^승천){C:inactive})", + }, + }, + c_cry_Timantii = { + name = "루투", + text = { + "({V:1}레벨 #4#{})({V:2}레벨 #5#{})({V:3}레벨 #6#{})", + "{C:attention}#1#{},", + "{C:attention}#2#{},", + "그리고 {C:attention}#3#{} 레벨 업", + }, + }, + c_cry_Klubi = { + name = "리스티", + text = { + "({V:1}레벨 #4#{})({V:2}레벨 #5#{})({V:3}레벨 #6#{})", + "{C:attention}#1#{},", + "{C:attention}#2#{},", + "그리고 {C:attention}#3#{} 레벨 업", }, }, c_cry_Sydan = { - name = "Sydan", + name = "헤르타", text = { - "({V:1}lvl.#4#{})({V:2}lvl.#5#{})({V:3}lvl.#6#{})", - "Level up", + "({V:1}레벨 #4#{})({V:2}레벨 #5#{})({V:3}레벨 #6#{})", "{C:attention}#1#{},", "{C:attention}#2#{},", - "and {C:attention}#3#{}", + "그리고 {C:attention}#3#{} 레벨 업", }, }, - c_cry_Timantti = { - name = "Timantti", + c_cry_Lapio = { + name = "파타", text = { - "({V:1}lvl.#4#{})({V:2}lvl.#5#{})({V:3}lvl.#6#{})", - "Level up", + "({V:1}레벨 #4#{})({V:2}레벨 #5#{})({V:3}레벨 #6#{})", "{C:attention}#1#{},", "{C:attention}#2#{},", - "and {C:attention}#3#{}", + "그리고 {C:attention}#3#{} 레벨 업", + }, + }, + c_cry_Kaikki = { + name = "카이키", + text = { + "({V:1}레벨 #4#{})({V:2}레벨 #5#{})({V:3}레벨 #6#{})", + "{C:attention}#1#{},", + "{C:attention}#2#{},", + "그리고 {C:attention}#3#{} 레벨 업", + }, + }, + c_cry_voxel = { + name = "복셀", + text = { + "({V:1}레벨 #4#{})({V:2}레벨 #5#{})({V:3}레벨 #6#{})", + "{C:attention}#1#{},", + "{C:attention}#2#{},", + "그리고 {C:attention}#3#{} 레벨 업", }, }, }, Sleeve = { - sleeve_cry_ccd_sleeve = { - name = "CCD Sleeve", + sleeve_cry_beige_sleeve = { + name = "베이지 슬리브", text = { - "Every card is also", - "a {C:attention}random{} consumable", + "{C:attention}일반{} 조커의", + "가치가 {C:attention}4배{}가 됩니다", + }, + }, + sleeve_cry_beta_sleeve = { + name = "향수 슬리브", + text = { + "{C:attention}조커{}와 {C:attention}소모품{}", + "슬롯이 {C:attention}통합됩니다", + "{C:attention}향수{} 블라인드가", + "업데이트된 블라인드를 대체합니다", + }, + }, + sleeve_cry_bountiful_sleeve = { + name = "풍요로운 슬리브", + text = { + "{C:blue}플레이{} 또는 {C:red}버린{} 후,", + "항상 카드 {C:attention}5{}장을 뽑습니다", + }, + }, + sleeve_cry_ccd_sleeve = { + name = "CCD 슬리브", + text = { + "모든 카드가", + "또한 {C:attention}무작위{} 소모품입니다", }, }, sleeve_cry_conveyor_sleeve = { - name = "Conveyor Sleeve", + name = "컨베이어 슬리브", text = { - "Jokers may {C:attention}not{} be moved", - "At start of round,", - "{C:attention}duplicate{} rightmost Joker", - "and {C:attention}destroy{} leftmost Joker", + "조커를 {C:attention}움직일 수 없습니다", + "라운드 시작 시,", + "가장 오른쪽 조커를 {C:attention}복제{}하고", + "가장 왼쪽 조커를 {C:attention}파괴{}합니다", }, }, sleeve_cry_critical_sleeve = { - name = "Critical Sleeve", + name = "치명타 슬리브", text = { - "After each hand played,", - "{C:green}1 in 4{} chance for {X:dark_edition,C:white} ^2 {} Mult", - "{C:green}1 in 8{} chance for {X:dark_edition,C:white} ^0.5 {} Mult", + "핸드를 낼 때마다,", + "{C:green}4분의 1{} 확률로 {X:dark_edition,C:white} 배수 ^2 {}", + "{C:green}8분의 1{} 확률로 {X:dark_edition,C:white} 배수 ^0.5 {}", }, }, sleeve_cry_encoded_sleeve = { - name = "Encoded Sleeve", + name = "인코딩 슬리브", text = { - "Start with a {C:cry_code,T:j_cry_CodeJoker}Code Joker{}", - "and a {C:cry_code,T:j_cry_copypaste}Copy/Paste{}", - "Only {C:cry_code}Code Cards{} appear in shop", + "{C:cry_code,T:j_cry_CodeJoker}코드 조커{}와", + "{C:cry_code,T:j_cry_copypaste}복사/붙여넣기{}를 가지고 시작합니다", + "상점에는 {C:cry_code}코드 카드{}만 나타납니다", }, }, sleeve_cry_equilibrium_sleeve = { - name = "Balanced Sleeve", + name = "균형 슬리브", text = { - "All cards have the", - "{C:attention}same chance{} of", - "appearing in shops,", - "start run with", - "{C:attention,T:v_overstock_plus}+2 Shop Slots", + "모든 카드가 상점에", + "나타날 확률이 {C:attention}동일{}해집니다", + "{C:attention,T:v_overstock_plus}상점 슬롯 +2{}를", + "가지고 런을 시작합니다", + }, + }, + sleeve_cry_glowing_sleeve = { + name = "빛나는 슬리브", + text = { + "보스 블라인드를 이길 때", + "모든 조커의 가치를", + "{X:dark_edition,C:white} X1.25 {} 곱합니다", + "{X:cry_jolly,C:white,s:0.8} 졸리#1#오픈#1#위너#1#-#1#와와#1#사람", }, }, sleeve_cry_infinite_sleeve = { - name = "Unlimited Sleeve", + name = "무제한 슬리브", text = { - "You can select {C:attention}any", - "number of cards", - --someone do the hand size thing for me + "원하는 만큼의", + "카드를 선택할 수 있습니다", }, }, sleeve_cry_misprint_sleeve = { - name = "Misprinted Sleeve", + name = "오타 슬리브", text = { - "Values of cards", - "are {C:attention}randomized", + "카드의 가치가", + "{C:attention}무작위{}로 정해집니다", }, }, sleeve_cry_redeemed_sleeve = { - name = "Redeemed Sleeve", + name = "상환된 슬리브", text = { - "When a {C:attention}Voucher{} is purchased,", - "gain its {C:attention}extra tiers", + "{C:attention}바우처{}를 구매하면,", + "그 {C:attention}추가 등급{}을 얻습니다", + }, + }, + sleeve_cry_spooky_sleeve = { + name = "으스스한 슬리브", + text = { + "{C:eternal}이터널{} {C:attention,T:j_cry_chocolate_dice}초콜릿 주사위{}를 가지고 시작", + "각 {C:attention}앤티{} 이후,", + "{C:cry_candy}사탕{} 또는 {X:cry_cursed,C:white}저주받은{} 조커 생성", + }, + }, + sleeve_cry_very_fair_sleeve = { + name = "아주 공정한 슬리브", + text = { + "매 라운드 {C:blue}핸드 -2{}, {C:red}버리기 -2{}", + "{C:attention}바우처{}는 더 이상", + "상점에 나타나지 않습니다", }, }, sleeve_cry_wormhole_sleeve = { - name = "Wormhole Sleeve", + name = "웜홀 슬리브", text = { - "Start with an {C:cry_exotic}Exotic{C:attention} Joker", - "Jokers are {C:attention}20X{} more", - "likely to be {C:dark_edition}Negative", - "{C:attention}-2{} Joker slots", + "{C:cry_exotic}이그조틱{C:attention} 조커를 가지고 시작", + "조커가 {C:dark_edition}네거티브{}일", + "확률이 {C:attention}20배{} 높아집니다", + "조커 슬롯 {C:attention}-2{}", + }, + }, + sleeve_cry_legendary_sleeve = { + name = "전설 슬리브", + text = { + "{C:legendary}전설{C:legendary} 조커를 가지고 시작", + "보스 블라인드를 이길 때 {C:green}5분의 1{} 확률로 다른 전설 조커 생성", + "{C:inactive}(공간 필요){}", + }, + }, + sleeve_cry_antimatter_sleeve = { + name = "반물질 슬리브", + text = { + "모든 덱 슬리브의 {C:attention}효과{}와", + "{C:attention}특수 효과{}를", + "적용합니다", + "{C:red}개발 중", + }, + }, + sleeve_cry_antimatter_sleeve_balanced = { + name = "반물질 슬리브", + text = { + "{C:gold}골드 스테이크{}에서 승리한", + "{C:attention}모든{} 슬리브의 {C:attention}효과{}와", + "{C:attention}특수 효과{}를 적용합니다", + "{C:red}개발 중", }, }, }, Spectral = { - c_cry_analog = { - name = "Analog", + c_cry_adversary = { + name = "적수", text = { - "Create {C:attention}#1#{} copies of a", - "random {C:attention}Joker{}, destroy", - "all other Jokers, {C:attention}+#2#{} Ante", + "{C:red}모든{} {C:attention}조커{}가 {C:dark_edition}네거티브{}가 되고,", + "상점의 {C:red}모든{} {C:attention}조커{}는 런이 끝날 때까지", + "가격이 {C:red}두 배{}가 됩니다", + }, + }, + c_cry_analog = { + name = "아날로그", + text = { + "무작위 {C:attention}조커{}의 복사본을", + "{C:attention}#1#{}개 생성하고,", + "다른 모든 조커를 파괴하며, {C:attention}앤티 +#2#{}", + }, + }, + c_cry_chambered = { + name = "약실", + text = { + "소지한 무작위 {C:attention}소모품{}의", + "{C:dark_edition}네거티브{} 복사본을", + "{C:attention}#1#{}개 생성합니다", + "{C:inactive,s:0.8}약실은 복사하지 않음{}", + }, + }, + c_cry_conduit = { + name = "도관", + text = { + "선택한 {C:attention}2{}개의 플레잉 카드 또는", + "{C:attention}조커{}의 {C:attention}에디션{}을 교환합니다", }, }, c_cry_gateway = { - name = "Gateway", + name = "관문", text = { - "Create a random", - "{C:cry_exotic,E:1}Exotic{C:attention} Joker{}, destroy", - "all other Jokers", + "무작위 {C:cry_exotic,E:1}이그조틱{C:attention} 조커를", + "생성하고, 다른 모든", + "조커를 파괴합니다", }, }, c_cry_hammerspace = { - name = "Hammerspace", + name = "해머스페이스", text = { - "Apply random {C:attention}consumables{}", - "as if they were {C:dark_edition}Enhancements{}", - "to cards held in hand", + "손에 든 카드에 무작위", + "{C:attention}소모품{}을 {C:dark_edition}강화{}처럼", + "적용합니다", }, }, c_cry_lock = { - name = "Lock", + name = "잠금", text = { - "Remove {C:red}all{} stickers", - "from {C:red}all{} Jokers,", - "then apply {C:purple,E:1}Eternal{}", - "to a random {C:attention}Joker{}", + "{C:red}모든{} 조커에서 {C:red}모든{} 스티커를", + "제거한 다음, 무작위", + "{C:attention}조커{}에 {C:purple,E:1}이터널{}을 적용합니다", }, }, c_cry_pointer = { name = "POINTER://", text = { - "Create a card", - "of {C:cry_code}your choice", - "{C:inactive,s:0.8}(Exotic Jokers #1#excluded)", + "{C:cry_code}원하는{} 카드를", + "생성합니다", + "{C:inactive,s:0.8}(이그조틱 조커 제외)", }, }, c_cry_replica = { - name = "Replica", + name = "복제품", text = { - "Convert all cards", - "held in hand", - "to a {C:attention}random{}", - "card held in hand", + "손에 든 모든", + "카드를 손에 든", + "{C:attention}무작위{} 카드로 변환합니다", + }, + }, + c_cry_ritual = { + name = "의식", + text = { + "손에 든 {C:attention}#1#{}개의 선택된 카드#1#에", + "{C:dark_edition}네거티브{}, {C:dark_edition}모자이크{},", + "또는 {C:dark_edition}아스트랄{}을 적용합니다", }, }, c_cry_source = { - name = "Source", + name = "소스", text = { - "Add a {C:cry_code}Green Seal{}", - "to {C:attention}#1#{} selected", - "card in your hand", + "손에 든 {C:attention}#1#{}개의 선택된", + "카드#1#에 {C:cry_code}녹색 봉인{}을", + "추가합니다", }, }, c_cry_summoning = { - name = "Summoning", + name = "소환", text = { - "Create a random", - "{C:cry_epic}Epic{} {C:joker}Joker{}, destroy", - "one random {C:joker}Joker{}", + "무작위 {V:1}#1#{} {C:joker}조커{}를 생성하고,", + "무작위 {C:joker}조커{} 하나를 파괴합니다", }, }, c_cry_trade = { - name = "Trade", + name = "거래", text = { - "{C:attention}Lose{} a random Voucher,", - "gain {C:attention}2{} random Vouchers", + "무작위 바우처를 {C:attention}잃고{},", + "무작위 바우처 {C:attention}2{}개를 얻습니다", }, }, c_cry_typhoon = { - name = "Typhoon", + name = "태풍", text = { - "Add an {C:cry_azure}Azure Seal{}", - "to {C:attention}#1#{} selected", - "card in your hand", + "손에 든 {C:attention}#1#{}개의 선택된", + "카드#1#에 {C:cry_azure}하늘색 봉인{}을", + "추가합니다", + }, + }, + c_cry_meld = { + name = "융합", + text = { + "{C:attention}조커{} 또는", + "{C:attention}플레잉 카드{}를 선택하여", + "{C:dark_edition}양면{}으로 만듭니다", }, }, c_cry_vacuum = { - name = "Vacuum", + name = "진공", text = { - "Removes {C:red}all {C:green}modifications{}", - "from {C:red}all{} cards held in hand,", - "Earn {C:money}$#1#{} per {C:green}modification{} removed", - "{C:inactive,s:0.7}(ex. Enhancements, Seals, Editions)", + "손에 든 {C:red}모든{} 카드에서 {C:red}모든", + "{C:green}수정 사항{}을 제거하고,", + "제거된 {C:green}수정 사항{}당 {C:money}$#1#{}를 법니다", + "{C:inactive,s:0.7}(예: 강화, 봉인, 에디션)", }, }, c_cry_white_hole = { - name = "White Hole", + name = "화이트홀", text = { - "{C:attention}Remove{} all hand levels,", - "upgrade {C:legendary,E:1}most played{} poker hand", - "by {C:attention}3{} for each removed level", + "가장 많이 플레이한 {C:legendary,E:1}포커 핸드{}를", + "{C:attention}4{}만큼 업그레이드합니다", + "다른 모든 핸드 레벨을 {C:attention}제거{}합니다", }, }, }, Stake = { stake_cry_pink = { - name = "Pink Stake", - colour = "Pink", --this is used for auto-generated sticker localization + name = "핑크 스테이크", + colour = "핑크", text = { - "Required score scales", - "faster for each {C:attention}Ante", + "앤티마다 요구 점수가", + "더 빠르게 증가합니다", }, }, stake_cry_brown = { - name = "Brown Stake", - colour = "Brown", + name = "브라운 스테이크", + colour = "브라운", text = { - "All {C:attention}stickers{} are compatible", - "with each other", + "모든 {C:attention}스티커{}는", + "서로 호환됩니다", }, }, stake_cry_yellow = { - name = "Yellow Stake", - colour = "Yellow", + name = "옐로우 스테이크", + colour = "옐로우", text = { - "{C:attention}Stickers{} can appear on", - "all purchasable items", + "{C:attention}스티커{}는 구매 가능한", + "모든 아이템에 나타날 수 있습니다", }, }, stake_cry_jade = { - name = "Jade Stake", - colour = "Jade", + name = "제이드 스테이크", + colour = "제이드", text = { - "Cards can be drawn {C:attention}face down{}", + "카드가 {C:attention}뒷면으로{} 뽑힐 수 있습니다", }, }, stake_cry_cyan = { - name = "Cyan Stake", - colour = "Cyan", + name = "시안 스테이크", + colour = "시안", text = { - "{C:green}Uncommon{} and {C:red}Rare{} Jokers are", - "less likely to appear", + "{C:green}희귀{}과 {C:red}레어{} 조커는", + "나타날 확률이 낮아집니다", }, }, stake_cry_gray = { - name = "Gray Stake", - colour = "Gray", + name = "그레이 스테이크", + colour = "그레이", text = { - "Rerolls increase by {C:attention}$2{} each", + "리롤 비용이 매번 {C:attention}$2{}씩 증가합니다", }, }, stake_cry_crimson = { - name = "Crimson Stake", - colour = "Crimson", + name = "크림슨 스테이크", + colour = "크림슨", text = { - "Vouchers restock on {C:attention}even{} Antes", + "바우처는 {C:attention}짝수{} 앤티에", + "재입고됩니다", }, }, stake_cry_diamond = { - name = "Diamond Stake", - colour = "Diamond", + name = "다이아몬드 스테이크", + colour = "다이아몬드", text = { - "Must beat Ante {C:attention}10{} to win", + "이기려면 앤티 {C:attention}10{}을 이겨야 합니다", }, }, stake_cry_amber = { - name = "Amber Stake", - colour = "Amber", + name = "앰버 스테이크", + colour = "앰버", text = { - "{C:attention}-1{} Booster Pack slot", + "부스터 팩 슬롯 {C:attention}-1{}", }, }, stake_cry_bronze = { - name = "Bronze Stake", - colour = "Bronze", + name = "브론즈 스테이크", + colour = "브론즈", text = { - "Vouchers are {C:attention}50%{} more expensive", + "바우처가 {C:attention}50%{} 더 비쌉니다", }, }, stake_cry_quartz = { - name = "Quartz Stake", - colour = "Quartz", + name = "쿼츠 스테이크", + colour = "쿼츠", text = { - "Jokers can be {C:attention}Pinned{}", - "{s:0.8,C:inactive}(Stays pinned to the leftmost position){}", + "조커를 {C:attention}고정{}할 수 있습니다", + "{s:0.8,C:inactive}(가장 왼쪽 위치에 고정됩니다){}", }, }, stake_cry_ruby = { - name = "Ruby Stake", - colour = "Ruby", + name = "루비 스테이크", + colour = "루비", text = { - "{C:attention}Big{} Blinds can become", - "{C:attention}Boss{} Blinds", + "{C:attention}빅{} 블라인드가", + "{C:attention}보스{} 블라인드가 될 수 있습니다", }, }, stake_cry_glass = { - name = "Glass Stake", - colour = "Glass", + name = "글래스 스테이크", + colour = "글래스", text = { - "Cards can {C:attention}shatter{} when scored", + "점수를 얻을 때 카드가", + "{C:attention}깨질{} 수 있습니다", }, }, stake_cry_sapphire = { - name = "Sapphire Stake", - colour = "Sapphire", + name = "사파이어 스테이크", + colour = "사파이어", text = { - "Lose {C:attention}25%{} of current money", - "at end of Ante", - "{s:0.8,C:inactive}(Up to $10){}", + "앤티 종료 시 현재 돈의", + "{C:attention}25%{}를 잃습니다", + "{s:0.8,C:inactive}(최대 $10){}", }, }, stake_cry_emerald = { - name = "Emerald Stake", - colour = "Emerald", + name = "에메랄드 스테이크", + colour = "에메랄드", text = { - "Cards, packs, and vouchers", - "can be {C:attention}face down{}", - "{s:0.8,C:inactive}(Unable to be viewed until purchased){}", + "카드, 팩, 바우처가", + "{C:attention}뒷면으로{} 나올 수 있습니다", + "{s:0.8,C:inactive}(구매하기 전까지 볼 수 없음){}", }, }, stake_cry_platinum = { - name = "Platinum Stake", - colour = "Platinum", + name = "플래티넘 스테이크", + colour = "플래티넘", text = { - "Small Blinds are {C:attention}removed{}", + "스몰 블라인드가", + "{C:attention}제거{}됩니다", }, }, stake_cry_twilight = { - name = "Twilight Stake", - colour = "Twilight", + name = "트와일라잇 스테이크", + colour = "트와일라잇", text = { - "Cards can be {C:attention}Banana{}", - "{s:0.8,C:inactive}(1 in 10 chance of being destroyed each round){}", + "카드가 {C:attention}바나나{}가 될 수 있습니다", + "{s:0.8,C:inactive}(매 라운드 10분의 1 확률로 파괴됨){}", }, }, stake_cry_verdant = { - name = "Verdant Stake", - colour = "Verdant", + name = "버던트 스테이크", + colour = "버던트", text = { - "Required score scales", - "faster for each {C:attention}Ante", + "앤티마다 요구 점수가", + "더 빠르게 증가합니다", }, }, stake_cry_ember = { - name = "Ember Stake", - colour = "Ember", + name = "엠버 스테이크", + colour = "엠버", text = { - "All items give no money when sold", + "모든 아이템은 판매 시 돈을 주지 않습니다", }, }, stake_cry_dawn = { - name = "Dawn Stake", - colour = "Dawn", + name = "던 스테이크", + colour = "던", text = { - "Tarots and Spectrals target {C:attention}1", - "fewer card", - "{s:0.8,C:inactive}(Minimum of 1){}", + "타로와 스펙트럴은 {C:attention}1개", + "적은 카드를 대상으로 합니다", + "{s:0.8,C:inactive}(최소 1개){}", }, }, stake_cry_horizon = { - name = "Horizon Stake", - colour = "Horizon", + name = "호라이즌 스테이크", + colour = "호라이즌", text = { - "When blind selected, add a", - "{C:attention}random card{} to deck", + "블라인드 선택 시, 덱에", + "{C:attention}무작위 카드{}를 추가합니다", }, }, stake_cry_blossom = { - name = "Blossom Stake", - colour = "Blossom", + name = "블라썸 스테이크", + colour = "블라썸", text = { - "{C:attention}Final{} Boss Blinds can appear", - "in {C:attention}any{} Ante", + "{C:attention}최종{} 보스 블라인드는", + "{C:attention}어떤{} 앤티에서든 나타날 수 있습니다", }, }, stake_cry_azure = { - name = "Azure Stake", - colour = "Azure", + name = "아주르 스테이크", + colour = "아주르", text = { - "Values on Jokers are reduced", - "by {C:attention}20%{}", + "조커의 가치가", + "{C:attention}20%{} 감소합니다", }, }, stake_cry_ascendant = { - name = "Ascendant Stake", - colour = "Ascendant", + name = "승천 스테이크", + colour = "승천", text = { - "{C:attention}-1{} Shop slot", + "상점 슬롯 {C:attention}-1{}", }, }, }, Tag = { tag_cry_astral = { - name = "Astral Tag", + name = "아스트랄 태그", text = { - "Next base edition shop", - "Joker is free and", - "becomes {C:dark_edition}Astral{}", + "다음 기본 에디션 상점", + "조커는 무료이며", + "{C:dark_edition}아스트랄{}이 됩니다", }, }, tag_cry_banana = { - name = "Banana Tag", + name = "바나나 태그", text = { - "Creates {C:attention}#1#", - "{C:inactive}(Must have room){}", + "{C:attention}#1#를 생성합니다", + "{C:inactive}(공간 필요){}", }, }, tag_cry_bettertop_up = { - name = "Better Top-up Tag", + name = "더 나은 보충 태그", text = { - "Creates up to {C:attention}#1#", - "{C:green}Uncommon{} Jokers", - "{C:inactive}(Must have room){}", + "최대 {C:attention}#1#개의", + "{C:green}희귀{} 조커#1#를 생성합니다", + "{C:inactive}(공간 필요){}", }, }, tag_cry_better_voucher = { - name = "Golden Voucher Tag", + name = "황금 바우처 태그", text = { - "Adds one Tier {C:attention}#1#{} Voucher", - "to the next shop", + "다음 상점에 등급 {C:attention}#1#{}의", + "바우처 하나를 추가합니다", }, }, tag_cry_blur = { - name = "Blurred Tag", + name = "흐릿한 태그", text = { - "Next base edition shop", - "Joker is free and", - "becomes {C:dark_edition}Blurred{}", + "다음 기본 에디션 상점", + "조커는 무료이며", + "{C:dark_edition}흐릿함{}이 됩니다", }, }, tag_cry_booster = { - name = "Booster Tag", + name = "부스터 태그", text = { - "Next {C:cry_code}Booster Pack{} has", - "{C:attention}double{} cards and", - "{C:attention}double{} choices", + "다음 {C:cry_code}부스터 팩{}은", + "카드가 {C:attention}두 배{},", + "선택지도 {C:attention}두 배{}가 됩니다", }, }, tag_cry_bundle = { - name = "Bundle Tag", + name = "묶음 태그", text = { - "Create a {C:attention}Standard Tag{}, {C:tarot}Charm Tag{},", - "{C:attention}Buffoon Tag{}, and {C:planet}Meteor Tag", + "{C:attention}스탠다드 태그{}, {C:tarot}부적 태그{},", + "{C:attention}익살꾼 태그{}, {C:planet}운석 태그{}를 생성합니다", }, }, tag_cry_cat = { - name = "Cat Tag", - text = { "Meow.", "{C:inactive}Level {C:dark_edition}#1#" }, + name = "고양이 태그", + text = { "야옹.", "{C:inactive}레벨 {C:dark_edition}#1#" }, }, tag_cry_console = { - name = "Console Tag", + name = "콘솔 태그", text = { - "Gives a free", - "{C:cry_code}Program Pack", + "무료 {C:cry_code}프로그램 팩{}을", + "줍니다", }, }, tag_cry_double_m = { - name = "Double M Tag", + name = "더블 M 태그", text = { - "Shop has a", - "{C:dark_edition}Jolly {C:legendary}M Joker{}", + "상점에 {C:dark_edition}졸리{}", + "{C:legendary}M 조커{}가 있습니다", }, }, tag_cry_empowered = { - name = "Empowered Tag", + name = "강화된 태그", text = { - "Gives a free {C:spectral}Spectral Pack", - "with {C:legendary,E:1}The Soul{} and {C:cry_exotic,E:1}Gateway{}", + "{C:legendary,E:1}영혼{}과 {C:cry_exotic,E:1}관문{}이 포함된", + "무료 {C:spectral}스펙트럴 팩{}을 줍니다", }, }, tag_cry_epic = { - name = "Epic Tag", + name = "에픽 태그", text = { - "Shop has a half-price", - "{C:cry_epic}Epic Joker", + "상점에 반값", + "{C:cry_epic}에픽 조커{}가 있습니다", }, }, tag_cry_gambler = { - name = "Gambler's Tag", + name = "도박사의 태그", text = { - "{C:green}#1# in #2#{} chance to create", - "an {C:cry_exotic,E:1}Empowered Tag", + "{C:green}#2#분의 #1#{} 확률로", + "{C:cry_exotic,E:1}강화된 태그{}를 생성합니다", }, }, tag_cry_glass = { - name = "Fragile Tag", + name = "깨지기 쉬운 태그", text = { - "Next base edition shop", - "Joker is free and", - "becomes {C:dark_edition}Fragile{}", + "다음 기본 에디션 상점", + "조커는 무료이며", + "{C:dark_edition}깨지기 쉬움{}이 됩니다", }, }, tag_cry_glitched = { - name = "Glitched Tag", + name = "글리치 태그", text = { - "Next base edition shop", - "Joker is free and", - "becomes {C:dark_edition}Glitched{}", + "다음 기본 에디션 상점", + "조커는 무료이며", + "{C:dark_edition}글리치{}가 됩니다", }, }, tag_cry_gold = { - name = "Golden Tag", + name = "황금 태그", text = { - "Next base edition shop", - "Joker is free and", - "becomes {C:dark_edition}Golden{}", + "다음 기본 에디션 상점", + "조커는 무료이며", + "{C:dark_edition}황금{}이 됩니다", }, }, tag_cry_gourmand = { - name = "Gourmand Tag", + name = "미식가 태그", text = { - "Shop has a free", - "{C:attention}Food Joker", + "상점에 무료", + "{C:attention}음식 조커{}가 있습니다", }, }, tag_cry_loss = { - name = "Loss", + name = "상실", text = { - "Gives a free", - "{C:cry_ascendant}Meme Pack", + "무료 {C:cry_ascendant}밈 팩{}을", + "줍니다", }, }, tag_cry_m = { - name = "Jolly Tag", + name = "쾌활한 태그", text = { - "Next base edition shop", - "Joker is free and", - "becomes {C:dark_edition}Jolly{}", + "다음 기본 에디션 상점", + "조커는 무료이며", + "{C:dark_edition}졸리{}가 됩니다", }, }, tag_cry_memory = { - name = "Memory Tag", + name = "기억 태그", text = { - "Create {C:attention}#1#{} copies of", - "the last {C:attention}Tag{} used", - "during this run", - "{s:0.8,C:inactive}Copying Tags excluded", - "{s:0.8,C:inactive}Currently: {s:0.8,C:attention}#2#", + "이번 런에서 사용된 마지막", + "{C:attention}태그{}의 복사본을", + "{C:attention}#1#{}개 생성합니다", + "{s:0.8,C:inactive}복사 태그 제외", + "{s:0.8,C:inactive}현재: {s:0.8,C:attention}#2#", }, }, tag_cry_mosaic = { - name = "Mosaic Tag", + name = "모자이크 태그", text = { - "Next base edition shop", - "Joker is free and", - "becomes {C:dark_edition}Mosaic{}", + "다음 기본 에디션 상점", + "조커는 무료이며", + "{C:dark_edition}모자이크{}가 됩니다", }, }, tag_cry_oversat = { - name = "Oversaturated Tag", + name = "과포화 태그", text = { - "Next base edition shop", - "Joker is free and", - "becomes {C:dark_edition}Oversaturated{}", + "다음 기본 에디션 상점", + "조커는 무료이며", + "{C:dark_edition}과포화{}가 됩니다", }, }, tag_cry_quadruple = { - name = "Quadruple Tag", + name = "쿼드러플 태그", text = { - "Gives {C:attention}#1#{} copies of the", - "next selected {C:attention}Tag", - "{s:0.8,C:inactive}Copying Tags excluded", + "다음으로 선택한 {C:attention}태그{}의", + "복사본을 {C:attention}#1#{}개 줍니다", + "{s:0.8,C:inactive}복사 태그 제외", }, }, tag_cry_quintuple = { - name = "Quintuple Tag", + name = "퀸튜플 태그", text = { - "Gives {C:attention}#1#{} copies of the", - "next selected {C:attention}Tag", - "{s:0.8,C:inactive}Copying Tags excluded", + "다음으로 선택한 {C:attention}태그{}의", + "복사본을 {C:attention}#1#{}개 줍니다", + "{s:0.8,C:inactive}복사 태그 제외", }, }, tag_cry_rework = { - name = "Rework Tag", + name = "재작업 태그", text = { - "Shop has a(n)", - "{C:dark_edition}#1# {C:cry_code}#2#", + "상점에 #3#", + "{C:dark_edition}#1# {C:cry_code}#2#가 있습니다", }, }, tag_cry_schematic = { - name = "Schematic Tag", + name = "개요 태그", text = { - "Shop has a", - "{C:attention}Brainstorm", + "상점에 {C:attention}브레인스톰{}이", + "있습니다", }, }, tag_cry_scope = { - name = "Scope Tag", + name = "스코프 태그", text = { - "{C:attention}+#1# {C:blue}hands{} and", - "{C:red}discards{} next round", + "다음 라운드에 {C:blue}핸드 +#1#{}와", + "{C:red}버리기 +#1#{}", }, }, tag_cry_triple = { - name = "Triple Tag", + name = "트리플 태그", text = { - "Gives {C:attention}#1#{} copies of the", - "next selected {C:attention}Tag", - "{s:0.8,C:inactive}Copying Tags excluded", + "다음으로 선택한 {C:attention}태그{}의", + "복사본을 {C:attention}#1#{}개 줍니다", + "{s:0.8,C:inactive}복사 태그 제외", + }, + }, + tag_cry_clone = { + name = "복제 태그", + text = { + "상점 아이템 비용이 {C:attention}X#1#{}배가 되고,", + "다음에 구매한 카드의 {C:attention}복사본{}을 얻습니다", + }, + }, + tag_cry_lens = { + name = "렌즈 태그", + text = { + "무작위 {C:attention}#1#{}개의", + "소모품#1#에 {C:dark_edition}네거티브{}를", + "적용합니다", + }, + }, + tag_cry_palette_cleanser = { + name = "입가심 태그", + text = { + "무작위 {C:attention}조커{} 또는", + "플레잉 카드에서 {C:attention}무작위{}", + "스티커를 제거합니다", }, }, }, Tarot = { c_cry_automaton = { - name = "The Automaton", + name = "오토마톤", text = { - "Creates up to {C:attention}#1#", - "random {C:cry_code}Code{} card", - "{C:inactive}(Must have room)", + "최대 {C:attention}#1#개의 무작위", + "{C:cry_code}코드{} 카드#1#를 생성합니다", + "{C:inactive}(공간 필요)", }, }, c_cry_eclipse = { - name = "The Eclipse", + name = "일식", text = { - "Enhances {C:attention}#1#{} selected card", - "into an {C:attention}Echo Card", + "선택한 {C:attention}#1#{}개의 카드#1#를", + "{C:attention}메아리 카드{}로 강화합니다", }, }, - c_cry_meld = { - name = "Meld", + c_cry_instability = { + name = "불안정성", text = { - "Select a {C:attention}Joker{} or", - "{C:attention}playing card{} to", - "become {C:dark_edition}Double-Sided", + "선택한 {C:attention}#1#{}개의 카드#1#를", + "{C:attention}추상 카드{}로 강화합니다", }, }, c_cry_theblessing = { - name = "The Blessing", + name = "축복", text = { - "Creates {C:attention}1{}", - "random {C:attention}consumable{}", - "{C:inactive}(Must have room){}", + "{C:attention}1{}개의 무작위", + "{C:attention}소모품{}을 생성합니다", + "{C:inactive}(공간 필요){}", + }, + }, + c_cry_seraph = { + name = "세라프", + text = { + "선택한 {C:attention}#1#{}개의 카드#1#를", + "{C:attention}빛 카드{}로 강화합니다", }, }, }, Voucher = { - v_cry_asteroglyph = { - name = "Asteroglyph", - text = { - "Set Ante to {C:attention}#1#{}", - }, - }, - v_cry_blankcanvas = { - name = "Blank Canvas", - text = { - "{C:attention}+#1#{} hand size", - }, - }, - v_cry_clone_machine = { - name = "Clone Machine", - text = { - "Double Tags become", - "{C:attention}Quintuple Tags{} and", - "are {C:attention}4X{} as common", - }, - }, - v_cry_command_prompt = { - name = "Command Prompt", - text = { - "{C:cry_code}Code{} cards", - "can appear", - "in the {C:attention}shop{}", - }, - }, v_cry_copies = { - name = "Copies", + name = "사본", text = { - "Double Tags become", - "{C:attention}Triple Tags{} and are", - "{C:attention}2X{} as common", - }, - }, - v_cry_curate = { - name = "Curate", - text = { - "All cards", - "appear with", - "an {C:dark_edition}Edition{}", - }, - }, - v_cry_dexterity = { - name = "Dexterity", - text = { - "Permanently", - "gain {C:blue}+#1#{} hand(s)", - "each round", - }, - }, - v_cry_double_down = { - name = "Double Down", - text = { - "After every round,", - "{X:dark_edition,C:white} X1.5 {} to all values", - "on the back of", - "{C:dark_edition}Double-Sided{} cards", - }, - }, - v_cry_double_slit = { - name = "Double Slit", - text = { - "{C:attention}Meld{} can appear", - "in the shop and", - "Arcana Packs", - }, - }, - v_cry_double_vision = { - name = "Double Vision", - text = { - "{C:dark_edition}Double-Sided{} cards appear", - "{C:attention}4X{} more frequently", - }, - }, - v_cry_fabric = { - name = "Universal Fabric", - text = { - "{C:dark_edition}+#1#{} Joker slot(s)", - }, - }, - v_cry_massproduct = { - name = "Mass Production", - text = { - "All cards and packs", - "in shop cost {C:attention}$1{}", - }, - }, - v_cry_moneybean = { - name = "Money Beanstalk", - text = { - "Raise the cap on", - "interest earned in", - "each round to {C:money}$#1#{}", - }, - }, - v_cry_overstock_multi = { - name = "Multistock", - text = { - "{C:attention}+#1#{} card slot(s) and", - "{C:attention}+#1#{} booster pack slot(s)", - "available in shop", - }, - }, - v_cry_pacclimator = { - name = "Planet Acclimator", - text = { - "{C:planet}Planet{} cards appear", - "{C:attention}X#1#{} more frequently", - "in the shop", - "All future {C:planet}Planet{}", - "cards are {C:green}free{}", - }, - }, - v_cry_pairamount_plus = { - name = "Pairamount Plus", - text = { - "{C:attention}Retrigger{} all M Jokers", - "once for every Pair", - "{C:attention}contained{} in played hand", - }, - }, - v_cry_pairing = { - name = "Pairing", - text = { - "{C:attention}Retrigger{} all M Jokers", - "if played hand is a {C:attention}Pair", - }, - }, - v_cry_quantum_computing = { - name = "Quantum Computing", - text = { - "{C:cry_code}Code{} cards can spawn", - "with {C:dark_edition}Negative{} edition", - }, - }, - v_cry_repair_man = { - name = "Repair Man", - text = { - "{C:attention}Retrigger{} all M Jokers", - "if played hand contains a {C:attention}Pair", - }, - }, - v_cry_rerollexchange = { - name = "Reroll Exchange", - text = { - "All rerolls", - "cost {C:attention}$2{}", - }, - }, - v_cry_satellite_uplink = { - name = "Satellite Uplink", - text = { - "{C:cry_code}Code{} cards may", - "appear in any of", - "the {C:attention}Celestial Packs{}", - }, - }, - v_cry_scope = { - name = "Galactic Scope", - text = { - "Create the {C:planet}Planet", - "card for played", - "{C:attention}poker hand{}", - "{C:inactive}(Must have room){}", - }, - }, - v_cry_tacclimator = { - name = "Tarot Acclimator", - text = { - "{C:tarot}Tarot{} cards appear", - "{C:attention}X#1#{} more frequently", - "in the shop", - "All future {C:tarot}Tarot{}", - "cards are {C:green}free{}", + "더블 태그가 {C:attention}트리플 태그{}가 되고", + "등장 확률이 {C:attention}2배{}가 됩니다", }, }, v_cry_tag_printer = { - name = "Tag Printer", + name = "태그 프린터", text = { - "Double Tags become", - "{C:attention}Quadruple Tags{} and", - "are {C:attention}3X{} as common", + "더블 태그가 {C:attention}쿼드러플 태그{}가 되고", + "등장 확률이 {C:attention}3배{}가 됩니다", }, }, - v_cry_threers = { - name = "The 3 Rs", + v_cry_pairing = { + name = "페어링", text = { - "Permanently", - "gain {C:red}+#1#{} discard(s)", - "each round", + "플레이한 핸드가 {C:attention}페어{}이면", + "모든 M 조커를 {C:attention}재발동{}합니다", + }, + }, + v_cry_repair_man = { + name = "수리공", + text = { + "플레이한 핸드에 {C:attention}페어{}가 포함되어 있으면", + "모든 M 조커를 {C:attention}재발동{}합니다", + }, + }, + v_cry_double_vision = { + name = "복시", + text = { + "{C:dark_edition}양면{} 카드가", + "{C:attention}4배{} 더 자주 나타납니다", + }, + }, + v_cry_double_slit = { + name = "이중 슬릿", + text = { + "{C:attention}융합{}이 {C:spectral}스펙트럴{} 팩에", + "나타날 수 있습니다", }, }, v_cry_stickyhand = { - name = "Sticky Hand", + name = "끈끈한 손", text = { - "{C:attention}+#1#{} card", - "selection limit", + "카드 선택 제한 {C:attention}+#1#{}", }, }, v_cry_grapplinghook = { - name = "Grappling Hook", + name = "갈고리", text = { - "{C:attention}+#1#{} card", - "selection limit", - "{C:inactive,s:0.7}NOTE: Will have extra{}", - "{C:inactive,s:0.7}functionality later{}", + "카드 선택 제한 {C:attention}+#1#{}", + "{C:inactive,s:0.7}생각보다 이걸로 할 수 있는 게 많아요.{}", + }, + }, + v_cry_command_prompt = { + name = "명령 프롬프트", + text = { + "{C:cry_code}코드{} 카드가", + "{C:attention}상점{}에", + "나타날 수 있습니다", + }, + }, + v_cry_satellite_uplink = { + name = "위성 업링크", + text = { + "{C:cry_code}코드{} 카드가", + "어떤 {C:attention}천체 팩{}에서든", + "나타날 수 있습니다", + }, + }, + v_cry_overstock_multi = { + name = "멀티스톡", + text = { + "상점에서 사용 가능한 {C:attention}카드 슬롯 +#1#{},", + "{C:attention}부스터 팩 슬롯 +#1#{},", + "및 {C:attention}바우처 슬롯 +#1#{}", + }, + unlock = { + "한 런에서 상점에서", + "{C:attention}1000${} 소비하기", + }, + }, + v_cry_massproduct = { + name = "대량 생산", + text = { + "상점의 모든 카드와 팩이", + "{C:attention}$1{}입니다", + }, + unlock = { + "한 런에서 {C:attention}25개의", + "{C:attention}바우처{} 사용하기", + }, + }, + v_cry_curate = { + name = "큐레이트", + text = { + "모든 카드가 {C:dark_edition}에디션{}을", + "가지고 나타납니다", + }, + unlock = { + "모든 {C:attention}에디션{} 발견하기", + }, + }, + v_cry_rerollexchange = { + name = "리롤 교환", + text = { + "모든 리롤 비용이", + "{C:attention}$2{}입니다", + }, + unlock = { + "한 런에서 상점을", + "총 {C:attention}250회{}", + "{C:attention}리롤{}하기", + }, + }, + v_cry_dexterity = { + name = "민첩성", + text = { + "매 라운드마다", + "영구적으로 {C:blue}핸드 +#1#{}를", + "얻습니다", + }, + unlock = { + "총 {C:attention}5000{}장의", + "{C:attention}플레잉 카드{} 플레이하기", + }, + }, + v_cry_threers = { + name = "3 R", + text = { + "매 라운드마다", + "영구적으로 {C:red}버리기 +#1#{}를", + "얻습니다", + }, + unlock = { + "총 {C:attention}5000{}장의", + "{C:attention}플레잉 카드{} 버리기", + }, + }, + v_cry_tacclimator = { + name = "타로 적응기", + text = { + "{C:tarot}타로{} 카드가 상점에", + "{C:attention}X#1#{}배 더 자주 나타납니다", + "상점의 {C:tarot}타로 비율{}을", + "제어할 수 있습니다", + "{C:inactive}({C:attention}런 정보{C:inactive} 확인)", + }, + unlock = { + "상점에서 총 {C:attention}100{}장의", + "{C:tarot}타로{} 카드 구매하기", + }, + }, + v_cry_pacclimator = { + name = "행성 적응기", + text = { + "{C:planet}행성{} 카드가 상점에", + "{C:attention}X#1#{}배 더 자주 나타납니다", + "상점의 {C:planet}행성 비율{}을", + "제어할 수 있습니다", + "{C:inactive}({C:attention}런 정보{C:inactive} 확인)", + }, + unlock = { + "상점에서 총 {C:attention}100{}장의", + "{C:planet}행성{} 카드 구매하기", + }, + }, + v_cry_moneybean = { + name = "돈콩나무", + text = { + "각 라운드에서 얻는", + "이자 상한선을 {C:money}$#1#{}로 올립니다", + }, + unlock = { + "{C:attention}전체 런{} 동안", + "{C:attention}이자 수익{}을", + "최대화하기", + }, + }, + v_cry_fabric = { + name = "우주의 직물", + text = { + "{C:dark_edition}조커 슬롯 +#1#{}", + }, + unlock = { + "{C:dark_edition}반물질{}을", + "{C:attention}10{}번 사용하기", + }, + }, + v_cry_asteroglyph = { + name = "아스테로글리프", + text = { + "앤티를 {C:attention}#1#{}로 설정합니다", + }, + unlock = { + "앤티 {C:attention}36{}에 도달하기", + }, + }, + v_cry_blankcanvas = { + name = "빈 캔버스", + text = { + "핸드 크기 {C:attention}+#1#{}", + }, + unlock = { + "{C:attention}핸드 크기{}를", + "{C:attention}0{}으로 줄이기", + }, + }, + v_cry_clone_machine = { + name = "복제 기계", + text = { + "더블 태그가 {C:attention}퀸튜플 태그{}가 되고", + "등장 확률이 {C:attention}4배{}가 됩니다", + }, + }, + v_cry_pairamount_plus = { + name = "페어마운트 플러스", + text = { + "플레이한 핸드에 포함된", + "각 페어마다 모든 M 조커를", + "한 번씩 {C:attention}재발동{}합니다", + }, + }, + v_cry_double_down = { + name = "더블 다운", + text = { + "매 라운드 후, {C:dark_edition}양면{} 카드의", + "뒷면에 있는 모든 값에", + "{X:dark_edition,C:white} X1.5 {}", }, }, v_cry_hyperspacetether = { - name = "Hyperspace Tether", + name = "초공간 테더", text = { - "{C:attention}+#1#{} card", - "selection limit", - "{C:inactive,s:0.7}NOTE: Will have extra{}", - "{C:inactive,s:0.7}functionality later{}", + "카드 선택 제한 {C:attention}+#1#{}", + "모든 선택된 카드가 {C:attention}승천 핸드{}에", + "힘을 기여합니다", + }, + }, + v_cry_quantum_computing = { + name = "양자 컴퓨팅", + text = { + "모든 미래의 {C:cry_code}코드{} 카드는", + "각각 {C:cry_code}다중 사용 +#1#{}를 가집니다", }, }, }, Other = { - banana = { - name = "Banana", + alt_wheel_of_fortune = { + name = "운명의 수레바퀴", text = { - "{C:green}#1# in #2#{} chance of being", - "destroyed each round", + "{C:green}#1# / #2#{} 의 확률로", + "{C:dark_edition}포일{}, {C:dark_edition}홀로그래픽{}, 또는", + "{C:dark_edition}폴리크롬{} 에디션을", + "무작위 {C:attention}조커{} 에 추가합니다", + }, + }, + disabled = { + name = "비활성화됨", + text = { + "런 동안 더 이상", + "나타나지 않습니다", + }, + }, + disabled_card_dependency = { + name = "비활성화됨", + text = { + "{C:attention}#1# 필요", + }, + }, + disabled_mod_dependency = { + name = "비활성화됨", + text = { + "필요한 모드:", + "{C:attention}#1#", + }, + }, + disabled_mod_conflict = { + name = "비활성화됨", + text = { + "호환되지 않는 모드:", + "{C:attention}#1#", + }, + }, + banana = { + name = "바나나", + text = { + "매 라운드마다", + "{C:green}#2#분의 #1#{} 확률로 파괴됩니다", + }, + }, + cry_absolute = { + name = "절대적", + text = { + "판매하거나 파괴할 수", + "없습니다", + "{C:attention}제거 불가{}", }, }, cry_rigged = { - name = "Rigged", + name = "조작됨", text = { - "All {C:cry_code}listed{} probabilities", - "are {C:cry_code}guaranteed", + "나열된 모든 {C:cry_code}확률{}은", + "{C:cry_code}보장{}됩니다", }, }, cry_hooked = { - name = "Hooked", + name = "연결됨", text = { - "When this Joker is {C:cry_code}triggered{},", - "trigger {C:cry_code}#1#", + "이 조커가 {C:cry_code}발동{}되면,", + "{C:cry_code}#1#{}을 발동합니다", + "{C:inactive}모든 카드가 이런 식으로 발동될 수는 없지만{}", + "{C:inactive}모든 조커는 다른 조커를 발동시킬 수 있습니다{}", + }, + }, + cry_global_sticker = { + name = "전역", + text = { + "가능하다면, 이 카드를", + "{C:cry_code}다른 카드보다 먼저{} 뽑습니다", + }, + }, + cry_flickering = { + name = "깜빡임", + text = { + "{C:attention}#1#{}번 발동 후", + "파괴됩니다", + "{C:inactive}({C:attention}#2#{C:inactive} 남음)", + }, + }, + cry_flickering_desc = { + name = "깜빡임", + text = { + "{C:attention}#1#{}번 발동 후", + "파괴됩니다", + }, + }, + cry_function_sticker = { + name = "Function://", + text = { + "사용 시", + "{C:cry_code}#1#{}를 생성합니다", + }, + }, + cry_function_sticker_desc = { + name = "Function://", + text = { + "다음 {C:cry_code}Function://{} 소모품을", + "생성합니다", + "{C:inactive}현재 #1#, #2# 및 #3#{}", + }, + }, + cry_possessed = { + name = "빙의됨", + text = { + "효과를 {C:attention}비활성화{}하고", + "{C:attention}반전{}시킵니다 (가능한 경우)", + "{C:attention}유령{}과 함께 파괴됩니다", }, }, food_jokers = { - name = "Food Jokers", + name = "음식 조커", text = { - "{s:0.8}Gros Michel, Egg, Ice Cream, Cavendish,", - "{s:0.8}Turtle Bean, Diet Cola, Popcorn, Ramen,", - "{s:0.8}Seltzer, Pickle, Chili Pepper, Caramel,", - "{s:0.8}Nostalgic Candy, Fast Food M, etc.", + "{s:0.8}그로 미셸, 달걀, 아이스크림, 캐번디시,", + "{s:0.8}터틀 빈, 다이어트 콜라, 팝콘, 라면,", + "{s:0.8}셀처, 피클, 칠리 페퍼, 카라멜,", + "{s:0.8}향수 사탕, 패스트푸드 M 등", + }, + }, + ev_cry_choco0 = { + name = "가능한 이벤트", + text = { + "{T:ev_cry_choco1}1{} {T:ev_cry_choco2}2{} {T:ev_cry_choco3}3{} {T:ev_cry_choco4}4{} {T:ev_cry_choco5}5{}", + "{T:ev_cry_choco6}6{} {T:ev_cry_choco7}7{} {T:ev_cry_choco8}8{} {T:ev_cry_choco9}9{} {T:ev_cry_choco10}10{}", + "{C:inactive}(정보를 보려면 마우스를 올리세요)", + }, + }, + ev_cry_choco1 = { + name = "1: 빙의", + text = { + "{C:attention}조커{}와 플레잉 카드는", + "깜빡임을 얻을 {C:green}3분의 1{} 확률을 가집니다", + "{C:attention}유령{}을 생성합니다", + "{C:inactive,s:0.7}당신은 유령에게 빙의되었고, 당신의", + "{C:inactive,s:0.7}의식이 깜빡이고 있습니다.", + }, + }, + ev_cry_choco2 = { + name = "2: 유령의 집", + text = { + "{C:attention}블라인드{} 스킵을 방지합니다", + "상점당 {C:attention}한 번{}의 리롤만 허용됩니다", + "{C:attention}바우처{} 가격이 두 배가 됩니다", + "{C:inactive,s:0.7}으스스한 영혼들이 점령했습니다! 아무것도", + "{C:inactive,s:0.7}만지지 말고 가능한 한 빨리 나가세요!", + }, + }, + ev_cry_choco3 = { + name = "3: 마녀의 묘약", + text = { + "{C:attention}물약{} 3개를 생성합니다", + "{C:attention}스몰 블라인드{}가 끝나기 전에 하나를 사용하세요,", + "그렇지 않으면 이번 {C:attention}앤티{}에 {C:attention}모든{} 불이익이 적용됩니다", + "{C:inactive,s:0.7}당신은 마녀에게 납치되었습니다!", + "{C:inactive,s:0.7}그녀는 당신에게 세 개의 물약을 제안하며, 당신을 면밀히 지켜봅니다.", + "{C:inactive,s:0.7}하나를 고르세요, 그렇지 않으면 그녀가 대신 결정할 것입니다.", + }, + }, + ev_cry_choco4 = { + name = "4: 달의 심연", + text = { + "플레이한 카드는 {C:green}4분의 1{} 확률로", + "무작위 {C:club}클럽{} 페이스 카드로 변합니다", + "{C:attention}배수{}를 플레이한 페이스 카드 수로 나눕니다", + "{C:inactive,s:0.7}마음이 순수하고 밤에 기도를 하는", + "{C:inactive,s:0.7}사람이라도...", + }, + }, + ev_cry_choco5 = { + name = "5: 흡혈귀", + text = { + "플레이한 모든 카드에서 {C:attention}강화{}를 제거합니다", + "{C:green}3분의 1{} 확률로", + "{C:heart}하트{}와 {C:diamond}다이아몬드{} 카드를 파괴합니다", + "{C:inactive,s:0.7}한밤중에는 조심하세요, 그림자 속의", + "{C:inactive,s:0.7,E:1}그들{C:inactive,s:0.7}이 갈증을 해소하려 하니까요...", + }, + }, + ev_cry_choco6 = { + name = "6: 하나 가져가세요", + text = { + "{C:attention}라운드 종료{} 시,", + "무작위 {C:attention}부스터{} 팩을 엽니다", + "{C:inactive,s:0.7}거리를 거닐다가 다양한 부스터 팩이 담긴", + "{C:inactive,s:0.7}상자를 발견했습니다. 하나쯤 가져가도 괜찮겠죠!", + }, + }, + ev_cry_choco7 = { + name = "7: 축제 분위기", + text = { + "{C:attention}트릭 오어 트릿{} 3개와 {C:attention}사탕 바구니{} 1개를 생성합니다", + "상점은 매 라운드마다 {C:attention}트릭 오어 트릿{}을 가집니다", + "{C:cry_candy}사탕{}은 획득 시 {C:money}$3{}를 줍니다", + "{C:inactive,s:0.7}온 동네가 으스스한 모험을 위해 장식되었습니다,", + "{C:inactive,s:0.7}축제 분위기에 흠뻑 빠져보세요!", + }, + }, + ev_cry_choco8 = { + name = "8: 사탕 비", + text = { + "{C:attention}블라인드{}를 이기면, 남은 핸드당 1개의 {C:cry_candy}사탕{}을 얻습니다;", + "{C:cry_candy}사탕{}이 생성될 때 {C:attention}음식 조커{}를 얻습니다", + "{C:inactive,s:0.7}하늘에서 사탕이 비처럼 내립니다! 빨리,", + "{C:inactive,s:0.7,E:1}최대한 많이 잡으세요!", + }, + }, + ev_cry_choco9 = { + name = "9: 유령의 재물", + text = { + "{C:money}$20{} 획득", + "얻는 모든 {C:money}돈{}은 {C:attention}두 배{}가 됩니다", + "{C:inactive,s:0.7}오래전에 세상을 떠난 친척의 유령이", + "{C:inactive,s:0.7}한밤중에 당신을 찾아옵니다!", + "{C:inactive,s:0.7}아무 말 없이 돈 가방을 당신 손에 쥐여주고,", + "{C:inactive,s:0.7}따뜻하게 미소 지으며 공기 속으로 사라집니다.", + }, + }, + ev_cry_choco10 = { + name = "10: 귀한 골동품", + text = { + "{C:legendary}전설{} {C:attention}조커{}가", + "{C:attention}바우처{} 슬롯에 {C:money}$50{}에 나타납니다", + "상점의 {C:attention}마지막{} 아이템으로만 구매 가능합니다", + "{C:inactive,s:0.7}당신은 유물의 영혼의 주목을 끌었지만,", + "{C:inactive,s:0.7}그것을 달래기는 쉽지 않을 것입니다.", }, }, cry_https_disabled = { name = "M", text = { - "{C:attention,s:0.7}Updating{s:0.7} is disabled by default ({C:attention,s:0.7}HTTPS Module{s:0.7})", + "{C:attention,s:0.7}업데이트{s:0.7}는 기본적으로 비활성화되어 있습니다 ({C:attention,s:0.7}HTTPS 모듈{s:0.7})", }, }, - --i am so sorry for this - --actually some of this needs to be refactored at some point cry_eternal_booster = { - name = "Eternal", + name = "이터널", text = { - "All cards in pack", - "are {C:attention}Eternal{}", + "팩 안의 모든 카드는", + "{C:attention}이터널{}입니다", }, }, cry_perishable_booster = { - name = "Perishable", + name = "소멸성", text = { - "All cards in pack", - "are {C:attention}Perishable{}", + "팩 안의 모든 카드는", + "{C:attention}소멸성{}입니다", }, }, cry_rental_booster = { - name = "Rental", + name = "임대", text = { - "All cards in pack", - "are {C:attention}Rental{}", + "팩 안의 모든 카드는", + "{C:attention}임대{}입니다", }, }, cry_pinned_booster = { - name = "Pinned", + name = "고정됨", text = { - "All cards in pack", - "are {C:attention}Pinned{}", + "팩 안의 모든 카드는", + "{C:attention}고정됨{}입니다", }, }, cry_banana_booster = { - name = "Banana", + name = "바나나", text = { - "All cards in pack", - "are {C:attention}Banana{}", + "팩 안의 모든 카드는", + "{C:attention}바나나{}입니다", }, }, cry_eternal_voucher = { - name = "Eternal", + name = "이터널", text = { - "Can't be traded", + "거래할 수 없습니다", }, }, cry_perishable_voucher = { - name = "Perishable", + name = "소멸성", text = { - "Debuffed after", - "{C:attention}#1#{} rounds", - "{C:inactive}({C:attention}#2#{C:inactive} remaining)", + "{C:attention}#1#{} 라운드 후", + "디버프됩니다", + "{C:inactive}({C:attention}#2#{C:inactive} 남음)", }, }, cry_rental_voucher = { - name = "Rental", + name = "임대", text = { - "Lose {C:money}$#1#{} at", - "end of round", + "라운드 종료 시", + "{C:money}$#1#{}를 잃습니다", }, }, cry_pinned_voucher = { - name = "Pinned", + name = "고정됨", text = { - "Remains in shop", - "until redeemed", + "사용될 때까지", + "상점에 남아 있습니다", }, }, cry_banana_voucher = { - name = "Banana", + name = "바나나", text = { - "{C:green}#1# in #2#{} chance of being", - "unredeemed each round", + "매 라운드마다 사용되지 않을", + "{C:green}#2#분의 #1#{} 확률", }, }, cry_perishable_consumeable = { - name = "Perishable", + name = "소멸성", text = { - "Debuffed at", - "end of round", + "라운드 종료 시", + "디버프됩니다", }, }, cry_rental_consumeable = { - name = "Rental", + name = "임대", text = { - "Lose {C:money}$#1#{} at end of", - "round, and on use", + "라운드 종료 시 및 사용 시", + "{C:money}$#1#{}를 잃습니다", }, }, cry_pinned_consumeable = { - name = "Pinned", + name = "고정됨", text = { - "Can't use other", - "non-{C:attention}Pinned{} consumables", + "{C:inactive}아무것도 하지 않습니다...", + "{C:inactive}지금은 말이죠", }, }, cry_banana_consumeable = { - name = "Banana", + name = "바나나", text = { - "{C:green}#1# in #2#{} chance to do", - "nothing on use", + "사용 시 아무것도 하지 않을", + "{C:green}#2#분의 #1#{} 확률", }, }, p_cry_code_normal_1 = { - name = "Program Pack", + name = "프로그램 팩", text = { - "Choose {C:attention}#1#{} of up to", - "{C:attention}#2#{C:cry_code} Code{} cards", - }, - }, - p_cry_code_normal_2 = { - name = "Program Pack", - text = { - "Choose {C:attention}#1#{} of up to", - "{C:attention}#2#{C:cry_code} Code{} cards", - }, - }, - p_cry_code_jumbo_1 = { - name = "Jumbo Program Pack", - text = { - "Choose {C:attention}#1#{} of up to", - "{C:attention}#2#{C:cry_code} Code{} cards", - }, - }, - p_cry_code_mega_1 = { - name = "Mega Program Pack", - text = { - "Choose {C:attention}#1#{} of up to", - "{C:attention}#2#{C:cry_code} Code{} cards", - }, - }, - p_cry_empowered = { - name = "Spectral Pack [Empowered Tag]", - text = { - "Choose {C:attention}#1#{} of up to", - "{C:attention}#2#{C:spectral} Spectral{} cards", - "{s:0.8,C:inactive}(Generated by Empowered Tag)", + "최대 {C:attention}#2#{}개의 {C:cry_code}코드{} 카드#2# 중", + "{C:attention}#1#{}개를 선택하세요", }, }, p_cry_meme_1 = { - name = "Meme Pack", + name = "밈 팩", text = { - "Choose {C:attention}#1#{} of", - "up to {C:attention}#2# Meme Jokers{}", + "최대 {C:attention}#2#개의 밈 조커#2#{} 중", + "{C:attention}#1#{}개를 선택하세요", }, }, - p_cry_meme_two = { - name = "Meme Pack", + p_cry_baneful_1 = { + name = "유해한 익살꾼 팩", text = { - "Choose {C:attention}#1#{} of", - "up to {C:attention}#2# Meme Jokers{}", - }, - }, - p_cry_meme_three = { - name = "Meme Pack", - text = { - "Choose {C:attention}#1#{} of", - "up to {C:attention}#2# Meme Jokers{}", + "최대 {C:attention}#2#{}개의 {X:cry_cursed,C:white}저주받은{} 조커#2#{} 중", + "{C:attention}#1#{}개를 선택하세요", + "{C:attention}스킵{}하면 가장 오른쪽의", + "소유한 조커를 {C:red}추방{}합니다", }, }, undiscovered_code = { - name = "Not Discovered", + name = "발견되지 않음", text = { - "Purchase or use", - "this card in an", - "unseeded run to", - "learn what it does", + "시드 없는 런에서", + "이 카드를 구매하거나 사용하여", + "무엇을 하는지 알아보세요", + }, + }, + undiscovered_unique = { + name = "발견되지 않음", + text = { + "시드 없는 런에서", + "이 카드를 구매하거나 사용하여", + "무엇을 하는지 알아보세요", }, }, cry_green_seal = { - name = "Green Seal", + name = "녹색 봉인", text = { - "Creates a {C:cry_code}Code{} card", - "when played and unscoring", - "{C:inactive}(Must have room)", + "플레이하고 점수를 얻지 않을 때", + "{C:cry_code}코드{} 카드를 생성합니다", + "{C:inactive}(공간 필요)", }, }, cry_azure_seal = { - name = "Azure Seal", + name = "하늘색 봉인", text = { - "Create {C:attention}#1#{} {C:dark_edition}Negative{}", - "{C:planet}Planets{} for played", - "{C:attention}poker hand{}, then", - "{C:red}destroy{} this card", + "플레이한 {C:attention}포커 핸드{}에 대해", + "{C:attention}#1#{}개의 {C:dark_edition}네거티브{}", + "{C:planet}행성#1#{}을 생성한 다음,", + "이 카드를 {C:red}파괴{}합니다", + }, + }, + cry_multiuse = { + name = "m", + text = { + "{C:inactive}다중 사용: ({C:cry_code}#1#{C:inactive} 남음)", + }, + }, + }, + Unique = { + c_cry_potion = { + name = "물약", + text = { + "사용 시 알려지지 않은", + "{C:attention}불이익{}을 적용합니다", + "{C:inactive,s:0.7}초콜릿 주사위에서 획득", }, }, }, }, misc = { - achievement_names = { - ach_cry_ace_in_crash = "Pocket ACE", - ach_cry_blurred_blurred_joker = "Legally Blind", - ach_cry_bullet_hell = "Bullet Hell", - ach_cry_break_infinity = "Break Infinity", - ach_cry_cryptid_the_cryptid = "Cryptid the Cryptid", - ach_cry_exodia = "Exodia", - ach_cry_freak_house = "Freak House", - ach_cry_googol_play_pass = "Googol Play Pass", - ach_cry_haxxor = "H4xx0r", - ach_cry_home_realtor = "Home Realtor", - ach_cry_jokes_on_you = "Joke's on You, Pal!", - ach_cry_niw_uoy = "!niW uoY", - ach_cry_now_the_fun_begins = "Now the Fun Begins", - ach_cry_patience_virtue = "Patience is a Virtue", - ach_cry_perfectly_balanced = "Perfectly Balanced", - ach_cry_pull_request = "Pull Request", - ach_cry_traffic_jam = "Traffic Jam", - ach_cry_ult_full_skip = "Ultimate Full Skip", - ach_cry_used_crash = "We Told You Not To", - ach_cry_what_have_you_done = "WHAT HAVE YOU DONE?!", + tutorial = { + cry_intro_1 = { + "안녕하세요, 저는 {C:attention}조셉 J. 조커{}입니다!", + "{C:cry_exotic,E:1}크립티드{}에 오신 것을 환영합니다!", + }, + cry_intro_2 = { + "이 프로필로 {C:cry_exotic,E:1}크립티드{}를", + "플레이해 본 적이 없으신 것 같네요.", + "어떻게 작동하는지 보여드리겠습니다!", + }, + cry_intro_3 = { + "*손이 자라남*", + }, + cry_intro_4 = { + "이 모드를 몇 문장으로 요약하기는", + "어렵지만, 한 가지 말씀드리자면", + "{C:cry_exotic,E:1}정신 나간{} 경험을 하게 될 거라는 겁니다!", + "이건 당신이 알던 {C:attention}조커 포커{}가 아니에요...", + }, + cry_intro_5 = { + "이 {C:cry_ascendant}게임 세트{}들을 보면 아시겠지만,", + "저는 글자 {C:attention}M{}을 좋아합니다.", + "제가 설명할 게임 세트를 선택하세요...", + "{s:0.8}참고: 게임 세트 밸런싱은 현재 활발히 개발 중입니다.", + "{s:0.8}자주 바뀔 것으로 예상됩니다!", + }, + cry_modest_1 = { + "바닐라에 가까운 경험을 원하시나요?", + "그렇다면 {C:cry_ascendant}겸손한{} 게임 세트가 당신을 위한 것입니다!", + }, + cry_modest_2 = { + "하지만 크립티드 곳곳에 숨어있는", + "기믹들을 조심하세요! 다음 라운드에", + "무엇을 발견할지 아무도 모르니까요...", + }, + cry_mainline_1 = { + "게임을 {E:1,C:attention}박살{} 내고 싶으신가요? 좋은 소식입니다.", + "정신줄 놓지 않고도 할 수 있어요!", + }, + cry_mainline_2 = { + "여기서도 여전히 정신 나간 일들이 벌어지지만,", + "{C:cry_ascendant}진행{} 시스템을 경험할 기회가", + "있을 겁니다. 너무 편안해지지는 마세요...", + }, + cry_mainline_3 = { + "당신은 분명히 더 강해지겠지만,", + "제가 만든 몇몇 {E:1,C:dark_edition}보스{}들은", + "이 {C:cry_ascendant}게임 세트{}를 선택한 것을 후회하게 만들지도 모릅니다...", + }, + cry_madness_1 = { + "하드 드라이브를 완전히 {C:red,E:1}날려버리고{} 싶으신가요?", + "오, 재밌겠네요! {C:cry_ascendant}광기{} 게임 세트는", + "이렇게 말하죠, '밸런스? {E:1,C:red}그게 뭔데!?{}'", + }, + cry_madness_2 = { + "저는 잠 못 자고 {C:green}마운틴 듀{}로 버티며", + "몇 주를 보내 이 게임 세트가 당신만을 위해", + "{C:cry_ascendant}완벽하게 밸런스{} 잡히도록 작업했습니다!", + }, + cry_madness_3 = { + "모든 것이 잠금 해제된 상태로 시작하므로,", + "크립티드의 {C:red,E:1}진정한 힘{}을 발휘할 수 있습니다!", + "다만 게임이 {C:attention,E:1}충돌{}하지 않도록 조심하세요.", + "아마 지기 전에 그게 먼저 일어날 테니까요...", + }, }, - achievement_descriptions = { - ach_cry_ace_in_crash = 'check_for_unlock({type = "ace_in_crash"})', - ach_cry_blurred_blurred_joker = "Obtain Blurred Blurred Joker", - ach_cry_bullet_hell = "Have 15 AP Jokers", - ach_cry_break_infinity = "Score 1.79e308 Chips in a single hand", - ach_cry_cryptid_the_cryptid = "Use Cryptid on Cryptid", - ach_cry_exodia = "Have 5 Exotic Jokers", - ach_cry_freak_house = "Play a Flush House consisting of 6s and 9s of Hearts whilst possessing Nice", - ach_cry_googol_play_pass = "Rig a Googol Play Card", - ach_cry_haxxor = "Use a cheat code", - ach_cry_home_realtor = "Activate Happy House before Ante 8 (without DoE/Antimatter)", - ach_cry_jokes_on_you = "Trigger The Joke's effect on Ante 1 and win the run", - ach_cry_niw_uoy = "Reach Ante -8", - ach_cry_now_the_fun_begins = "Obtain Canvas", - ach_cry_patience_virtue = "Wait out Lavender Loop for 2 minutes before playing first hand and beat the blind", - ach_cry_perfectly_balanced = "Beat Very Fair Deck on Ascendant Stake", - ach_cry_pull_request = "Have ://COMMIT spawn the same Joker that it destroyed", - ach_cry_traffic_jam = "Beat all Rush Hour challenges", - ach_cry_ult_full_skip = "Win in 1 round", - ach_cry_used_crash = "Use ://CRASH", - ach_cry_what_have_you_done = "Delete or Sacrifice an Exotic Joker", + poker_hands = { + ["cry_Bulwark"] = "보루", + ["cry_Clusterfuck"] = Cryptid_config.family_mode and "클러스터" or "개판", + ["cry_UltPair"] = "얼티밋 페어", + ["cry_WholeDeck"] = Cryptid_config.family_mode and "덱 전체" or "빌어먹을 덱 전체", + ["cry-Cluster Bulwark"] = "클러스터 보루", + ["cry_None"] = "없음", + }, + poker_hand_descriptions = { + ["cry_Bulwark"] = { + "등급과 문양이 없는 카드 5장", + }, + ["cry_Clusterfuck"] = { + "페어, 플러시, 또는 스트레이트를", + "포함하지 않는 8장 이상의 카드", + }, + ["cry_UltPair"] = { + "두 개의 투 페어로, 각 투 페어는", + "단일 문양으로 이루어져 총 두 개의", + "문양을 가짐", + }, + ["cry_WholeDeck"] = { + "52장 카드 덱에 있는 모든", + "카드를 포함하는 핸드.", + "정신 나갔나요?", + }, + ["cry_None"] = { "0장의 카드를 포함하는 핸드" }, + + ["cry_Declare0"] = { "항상 스트레이트로 취급됩니다" }, + ["cry_Declare1"] = { "항상 플러시로 취급됩니다" }, + ["cry_Declare2"] = { "항상 풀 하우스로 취급됩니다" }, + }, + achievement_names = { + ach_cry_ace_in_crash = "포켓 에이스", + ach_cry_blurred_blurred_joker = "법적으로 맹인", + ach_cry_bullet_hell = "탄막 지옥", + ach_cry_break_infinity = "무한을 깨다", + ach_cry_cryptid_the_cryptid = "크립티드 더 크립티드", + ach_cry_exodia = "엑조디아", + ach_cry_freak_house = "프리크 하우스", + ach_cry_googol_play_pass = "구골 플레이 패스", + ach_cry_haxxor = "H4xx0r", + ach_cry_home_realtor = "주택 중개인", + ach_cry_jokes_on_you = "장난은 여기까지다, 친구!", + ach_cry_niw_uoy = "!리승 네당신", + ach_cry_now_the_fun_begins = "이제 재미가 시작됩니다", + ach_cry_patience_virtue = "인내는 미덕", + ach_cry_perfectly_balanced = "완벽하게 균형 잡힌", + ach_cry_pull_request = "풀 리퀘스트", + ach_cry_traffic_jam = "교통 체증", + ach_cry_ult_full_skip = "얼티밋 풀 스킵", + ach_cry_used_crash = "하지 말라고 했잖아요", + ach_cry_what_have_you_done = "무슨 짓을 한 거야?!", + ach_cry_pin = "수치의 핀", + ach_cry_technically_positive = "기술적으로 긍정적", + ach_cry_youre_fucking_kidding = Cryptid_config.family_mode and "장난하는 거죠" or "이런 미친", + ach_cry_stoned = "돌에 취함", + ach_cry_fucked = Cryptid_config.family_mode and "클러스터됨" or "망함", + ach_cry_despaired = "절망함", + ach_cry_decked = "덱을 다 씀", }, challenge_names = { c_cry_ballin = "Ballin'", - c_cry_boss_rush = "Enter the Gungeon", - c_cry_dagger_war = "Dagger War", - c_cry_joker_poker = "Joker Poker", - c_cry_onlycard = "Solo Card", + c_cry_boss_rush = "엔터 더 건전", + c_cry_dagger_war = "단검 전쟁", + c_cry_joker_poker = "조커 포커", + c_cry_onlycard = "솔로 카드", c_cry_rng = "RNG", - c_cry_rush_hour = "Rush Hour I", - c_cry_rush_hour_ii = "Rush Hour II", - c_cry_rush_hour_iii = "Rush Hour III", - c_cry_sticker_sheet = "Sticker Sheet", - c_cry_sticker_sheet_plus = "Sticker Sheet+", + c_cry_rush_hour = "러시 아워 I", + c_cry_rush_hour_ii = "러시 아워 II", + c_cry_rush_hour_iii = "러시 아워 III", + c_cry_sticker_sheet = "스티커 시트", + c_cry_sticker_sheet_plus = "스티커 시트+", }, dictionary = { - --Settings Menu - cry_set_features = "Features", - cry_set_music = "Music", - cry_set_enable_features = "Select features to enable (applies on game restart):", - cry_feat_achievements = "Achievements", - ["cry_feat_antimatter deck"] = "Antimatter Deck", - cry_feat_blinds = "Blinds", - cry_feat_challenges = "Challenges", - ["cry_feat_code cards"] = "Code Cards", - ["cry_feat_misc. decks"] = "Misc. Decks", - ["cry_feat_https module"] = "HTTPS Module", - ["cry_feat_timer mechanics"] = "Timer Mechanics", - ["cry_feat_enhanced decks"] = "Enhanced Decks", - ["cry_feat_epic jokers"] = "Epic Jokers", - ["cry_feat_exotic jokers"] = "Exotic Jokers", - ["cry_feat_m jokers"] = "M Jokers", - cry_feat_menu = "Custom Main Menu", - ["cry_feat_misc."] = "Misc.", - ["cry_feat_misc. jokers"] = "Misc. Jokers", - cry_feat_planets = "Planets", - cry_feat_jokerdisplay = "JokerDisplay (Does Nothing)", - cry_feat_tags = "Tags", - cry_feat_sleeves = "Sleeves", - cry_feat_spectrals = "Spectrals", - ["cry_feat_more stakes"] = "Stakes", - cry_feat_vouchers = "Vouchers", - cry_mus_jimball = "Jimball (Funkytown by Lipps Inc. - Copyrighted)", - cry_mus_code = "Code Cards (://LETS_BREAK_THE_GAME by HexaCryonic)", - cry_mus_exotic = "Exotic Jokers (Joker in Latin by AlexZGreat)", - cry_mus_high_score = "High Score (Final Boss [For Your Computer] by AlexZGreat)", + cry_set_features = "기능", + cry_set_music = "음악", + cry_set_enable_features = "이 섹션을 사용하여 전체 테마 세트를 활성화하거나 비활성화하세요.", + cry_feat_achievements = "업적", + ["cry_feat_code cards"] = "코드 카드", + ["cry_feat_misc. decks"] = "기타 덱", + ["cry_feat_https module"] = "HTTPS 모듈", + ["cry_feat_timer mechanics"] = "타이머 메커니즘", + ["cry_feat_enhanced decks"] = "강화 덱", + ["cry_feat_epic jokers"] = "에픽 조커", + ["cry_feat_exotic jokers"] = "이그조틱 조커", + ["cry_feat_m jokers"] = "M 조커", + cry_feat_menu = "커스텀 메인 메뉴", + ["cry_feat_misc. jokers"] = "기타 조커", + cry_feat_planets = "행성", + cry_feat_tags = "태그", + cry_feat_spectrals = "스펙트럴", + cry_feat_spooky = "으스스한 업데이트", + ["cry_feat_more stakes"] = "스테이크", + cry_feat_vouchers = "바우처", + cry_mus_jimball = "짐볼 (Funkytown by Lipps Inc. - 저작권 있음)", + cry_mus_code = "코드 카드 (://LETS_BREAK_THE_GAME by HexaCryonic)", + cry_mus_exotic = "이그조틱 조커 (Joker in Latin by AlexZGreat)", + cry_mus_high_score = "최고 점수 (Final Boss [For Your Computer] by AlexZGreat)", + cry_mus_alt_bg = "배경 음악 (by MathIsFun_)", + cry_force_tooltips = "툴팁 강제 표시", + cry_family = "가족 친화적 모드", + cry_experimental = "실험 모드", - k_cry_program_pack = "Program Pack", - k_cry_meme_pack = "Meme Pack", + k_cry_program_pack = "프로그램 팩", + k_cry_meme_pack = "밈 팩", + k_cry_baneful_pack = "유해한 익살꾼 팩", + cry_baneful_warning = "스킵하면 가장 오른쪽 조커가 추방됩니다", - cry_critical_hit_ex = "Critical Hit!", - cry_critical_miss_ex = "Critical Miss!", + cry_critical_hit_ex = "치명타!", + cry_critical_miss_ex = "치명적 실수!", - cry_debuff_oldhouse = "No Full Houses", - cry_debuff_oldarm = "Must play 4 or fewer cards", - cry_debuff_oldpillar = "No Straights", - cry_debuff_oldflint = "No Flushes", - cry_debuff_oldmark = "No hands containing a Pair", - cry_debuff_obsidian_orb = "Applies abilities of all defeated bosses", + cry_debuff_oldhouse = "풀 하우스 없음", + cry_debuff_oldarm = "4장 이하의 카드 플레이", + cry_debuff_oldpillar = "스트레이트 없음", + cry_debuff_oldflint = "플러시 없음", + cry_debuff_oldmark = "페어를 포함하는 핸드 없음", + cry_debuff_obsidian_orb = "패배한 모든 보스의 능력 적용", + cry_blind_baneful_pack = "라운드 후, 유해한 익살꾼 팩 열기", - k_code = "Code", - b_code_cards = "Code Cards", - b_pull = "PULL", - cry_hooked_ex = "Hooked!", - k_end_blind = "End Blind", + k_code = "코드", + k_chips = "개의 칩", + k_content_set = "테마 세트", + b_content_sets = "테마 세트", + b_tag = "태그", + b_blind = "블라인드", + rush_hour_reminder = "러시 아워를 플레이하려면 시계와 라벤더 루프를 활성화하세요", + b_tarot_rate = "타로 비율", + b_planet_rate = "행성 비율", + k_unique = "고유", + b_code_cards = "코드 카드", + b_unique_cards = "고유 카드", + b_pull = "당기기", + b_playing_cards = "플레잉 카드", + cry_hooked_ex = "연결됨!", + k_end_blind = "블라인드 종료", - cry_code_rank = "ENTER RANK", - cry_code_enh = "ENTER ENHANCEMENT", - cry_code_hand = "ENTER POKER HAND", - cry_code_enter_card = "ENTER A CARD", - cry_code_apply = "APPLY", - cry_code_apply_previous = "APPLY PREVIOUS", - cry_code_exploit = "EXPLOIT", - cry_code_exploit_previous = "EXPLOIT PREVIOUS", - cry_code_create = "CREATE", - cry_code_create_previous = "CREATE PREVIOUS", - cry_code_execute = "EXECUTE", - cry_code_cancel = "CANCEL", + cry_code_rank = "등급 입력", + cry_code_enh = "강화 입력", + cry_code_hand = "포커 핸드 입력", + cry_code_enter_card = "카드 입력", + cry_code_apply = "적용", + cry_code_exploit = "익스플로잇", + cry_code_create = "생성", + cry_code_execute = "실행", + cry_code_cancel = "취소", + cry_code_enter_hand = "포커 핸드 이름 입력", + cry_code_with_suits = "문양 포함", + cry_code_without_suits = "문양 무시", + cry_code_suitless = "핸드는 특정 문양이 필요 없습니다", + cry_code_empty = "[핸드 선언]", + cry_code_exit = "나가기", + cry_code_antevoucher = "다음 보스 블라인드 및 바우처", + cry_code_nextjokers = "다음 상점 조커", + cry_code_nextcards = "다음에 뽑을 카드", - b_flip = "FLIP", - b_merge = "MERGE", + b_flip = "뒤집기", + b_merge = "병합", + b_store = "보관", - cry_again_q = "Again?", - cry_curse = "Curse", - cry_curse_ex = "Curse!", - cry_sobbing = "Help me...", - cry_gaming = "Gaming", - cry_gaming_ex = "Gaming!", - cry_sus_ex = "Impostor!", - cry_jolly_ex = "Jolly Up!", - cry_m_minus = "m", - cry_m = "M", - cry_m_ex = "M!", - cry_minus_round = "-1 Round", - cry_plus_cryptid = "+1 Cryptid", - cry_no_triggers = "No triggers left!", - cry_unredeemed = "Unredeemed...", - cry_active = "Active", - cry_inactive = "Inactive", + k_disable_music = "음악 비활성화", + k_cry_epic = "에픽", + k_cry_exotic = "이그조틱", + k_cry_candy = "사탕", + k_cry_cursed = "저주받은", - k_disable_music = "Disable Music", + k_planet_disc = "원시성 원반", + k_planet_satellite = "자연 위성", + k_planet_universe = Cryptid_config.family_mode and "우주" or "빌어먹을 우주 전체", + k_planet_nibiru = "없음", - k_cry_epic = "Epic", - k_cry_exotic = "Exotic", + cry_notif_jimball_1 = "짐볼", + cry_notif_jimball_2 = "저작권 공지", + cry_notif_jimball_d1 = '"짐볼"은 저작권이 있는 노래 "Funkytown"을 재생합니다,', + cry_notif_jimball_d2 = "이는 스트리밍과 영상에 사용할 수 없습니다.", - cry_notif_jimball_1 = "Jimball", - cry_notif_jimball_2 = "Copyright Notice", - cry_notif_jimball_d1 = 'Jimball plays the song "Funkytown",', - cry_notif_jimball_d2 = "which is copyrighted and can't be", - cry_notif_jimball_d3 = "used for streams and videos.", + cry_gameset_explanation = { + "이 카드에 적용할 게임 세트 구성", + "옵션을 선택하세요.", + }, + cry_gameset_disabled = "비활성화됨", + cry_gameset_modest = "겸손한", + cry_gameset_mainline = "메인라인", + cry_gameset_madness = "광기", + cry_gameset_custom = "수정됨", + cry_gameset_exp = "실험적", + + cry_circus_generic = "{V:#1#}#2#{}개의 조커가 각각 {X:mult,C:white} 배수 X#3# {}를 줍니다", }, labels = { - food_jokers = "Food Jokers", - banana = "Banana", - code = "Code", - cry_rigged = "Rigged", - cry_hooked = "Hooked", + food_jokers = "음식 조커", + banana = "바나나", + pinned = "고정됨", + cry_absolute = "절대적", + code = "코드", + unique = "고유", + cry_rigged = "조작됨", + cry_hooked = "연결됨", + cry_global_sticker = "전역", + cry_flickering = "깜빡임", + cry_possessed = "빙의됨", - cry_green_seal = "Green Seal", - cry_azure_seal = "Azure Seal", + cry_green_seal = "녹색 봉인", + cry_azure_seal = "하늘색 봉인", - cry_astral = "Astral", - cry_blur = "Blurred", - cry_double_sided = "Double-Sided", - cry_glass = "Fragile", - cry_glitched = "Glitched", - cry_gold = "Golden", - cry_m = "Jolly", - cry_mosaic = "Mosaic", - cry_noisy = "Noisy", - cry_oversat = "Oversaturated", + cry_astral = "아스트랄", + cry_blur = "흐릿함", + cry_double_sided = "양면", + cry_glass = "깨지기 쉬움", + cry_glitched = "글리치", + cry_gold = "황금", + cry_m = "졸리", + cry_mosaic = "모자이크", + cry_noisy = "시끄러움", + cry_oversat = "과포화", - k_cry_epic = "Epic", - k_cry_exotic = "Exotic", - }, - rnj_loc_txts = { - stats = { - plus_mult = { "{C:red}+#2#{} Mult" }, - plus_chips = { "{C:blue}+#2#{} Chips" }, - x_mult = { "{X:red,C:white} X#2#{} Mult" }, - x_chips = { "{X:blue,C:white} X#2#{} Chips" }, - h_size = { "{C:attention}+#2#{} Hand Size" }, - money = { "{C:money}+$#2#{} at payout" }, - }, - stats_inactive = { - plus_mult = { "{C:inactive}(Currently {C:red}+#1#{C:inactive} Mult)" }, - plus_chips = { "{C:inactive}(Currently {C:blue}+#1#{C:inactive} Chips)" }, - x_mult = { "{C:inactive}(Currently {X:red,C:white} X#1# {C:inactive} Mult)" }, - x_chips = { "{C:inactive}(Currently {X:blue,C:white} X#1# {C:inactive} Chips)" }, - h_size = { "{C:inactive}(Currently {C:attention}+#1#{C:inactive} Hand Size)" }, - money = { "{C:inactive}(Currently {C:money}+$#1#{C:inactive})" }, - }, - actions = { - make_joker = { "Create {C:attention}#2# Joker{}" }, - make_tarot = { "Create {C:attention}#2#{C:tarot} Tarot{} card" }, - make_planet = { "Create {C:attention}#2#{C:planet} Planet{} card" }, - make_spectral = { "Create {C:attention}#2#{C:spectral} Spectral{} card" }, - add_dollars = { "Earn {C:money}$#2#{}" }, - }, - contexts = { - open_booster = { "when a {C:attention}Booster{} is opened" }, - buying_card = { "when a card is bought" }, - selling_self = { "when this card is sold" }, - selling_card = { "when a card is sold" }, - reroll_shop = { "on reroll" }, - ending_shop = { "at the end of the {C:attention}shop{}" }, - skip_blind = { "when a {C:attention}blind{} is skipped" }, - skipping_booster = { "when any {C:attention}Booster Pack{} is skipped" }, - playing_card_added = { "every time a {C:attention}playing card{} is added to your deck" }, - first_hand_drawn = { "when round begins" }, - setting_blind = { "when {C:attention}Blind{} is selected" }, - remove_playing_cards = { "when a card is destroyed" }, - using_consumeable = { "when a {C:attention}consumable{} card is used" }, - debuffed_hand = { "if played {C:attention}hand{} is not allowed" }, - pre_discard = { "before each discard" }, - discard = { "for each discarded card" }, - end_of_round = { "at end of {C:attention}round{}" }, - individual_play = { "for each card scored" }, - individual_hand_score = { "for each card held in hand during scoring" }, - individual_hand_end = { "for each card held in hand at end of {C:attention}round{}" }, - repetition_play = { "Retrigger played cards" }, - repetition_hand = { "Retrigger held in hand cards" }, - other_joker = { "per {C:attention}Joker{}" }, - before = { "before each {C:attention}hand{}" }, - after = { "after each {C:attention}hand{}" }, - joker_main = {}, - }, - conds = { - buy_common = { "if it is a {C:blue}Common{} {C:attention}Joker{}" }, - buy_uncommon = { "if it is a {C:green}Uncommon{} {C:attention}Joker{}" }, - tarot = { "if card is a {C:tarot}Tarot{} card" }, - planet = { "if card is a {C:planet}Planet{} card" }, - spectral = { "if card is a {C:spectral}Spectral{} card" }, - joker = { "if card is a {C:attention}Joker{}" }, - suit = { "if card is a {V:1}#3#{}" }, - rank = { "if card is rank {C:attention}#3#{}" }, - face = { "if card is a {C:attention}face{} card" }, - boss = { "if {C:attention}blind{} is a {C:attention}Boss {C:attention}Blind{}" }, - non_boss = { "if {C:attention}blind{} is a {C:attention}Non-Boss {C:attention}Blind{}" }, - small = { "if {C:attention}blind{} is a {C:attention}Small {C:attention}Blind{}" }, - big = { "if {C:attention}blind{} is a {C:attention}Big {C:attention}Blind{}" }, - first = { "if it's the {C:attention}first {C:attention}hand{}" }, - last = { "if it's the {C:attention}last {C:attention}hand{}" }, - common = { "if it is a {C:blue}Common{} {C:attention}Joker{}" }, - uncommon = { "if it is an {C:green}Uncommon{} {C:attention}Joker{}" }, - rare = { "if it is a {C:red}Rare{} {C:attention}Joker{}" }, - poker_hand = { "if hand is a {C:attention}#3#{}" }, - or_more = { "if hand contains {C:attention}#3#{} or more cards" }, - or_less = { "if hand contains {C:attention}#3#{} or less cards" }, - hands_left = { "if #3# {C:blue}hands{} remaining at end of round" }, - discards_left = { "if #3# {C:red}discards{} remaining at end of round" }, - first_discard = { "if it's the {C:attention}first {C:attention}discard{}" }, - last_discard = { "if it's the {C:attention}last {C:attention}discard{}" }, - odds = { "with a {C:green}#4# {C:green}in {C:green}#3#{} chance" }, - }, + k_cry_epic = "에픽", + k_cry_exotic = "이그조틱", + k_cry_candy = "사탕", + k_cry_cursed = "저주받은", }, v_dictionary = { - a_xchips = { "X#1# Chips" }, - a_powmult = { "^#1# Mult" }, - a_powchips = { "^#1# Chips" }, - a_powmultchips = { "^#1# Mult+Chips" }, - a_round = { "+#1# Round" }, - a_xchips_minus = { "-X#1# Chips" }, - a_powmult_minus = { "-^#1# Mult" }, - a_powchips_minus = { "-^#1# Chips" }, - a_powmultchips_minus = { "-^#1# Mult+Chips" }, - a_round_minus = { "-#1# Round" }, + a_xchips = { "칩 X#1#" }, + a_powmult = { "배수 ^#1#" }, + a_powchips = { "칩 ^#1#" }, + a_powmultchips = { "배수+칩 ^#1#" }, + a_round = { "라운드 +#1#" }, + a_candy = { "사탕 +#1#" }, + a_tag = { "태그 +#1#" }, + a_tags = { "태그 +#1#" }, - a_tag = { "#1# Tag" }, - a_tags = { "#1# Tags" }, - - cry_sticker_name = { "#1# Sticker" }, + cry_sticker_name = { "#1# 스티커" }, cry_sticker_desc = { - "Used this Joker", - "to win on #2##1#", - "#2#Stake#3# difficulty", + "#2# 스테이크 난이도에서", + "이 조커를 사용하여", + "#2##1#에서 승리했습니다", }, }, - v_text = { - ch_c_cry_all_perishable = { "All Jokers are {C:eternal}Perishable{}" }, - ch_c_cry_all_rental = { "All Jokers are {C:eternal}Rental{}" }, - ch_c_cry_all_pinned = { "All Jokers are {C:eternal}Pinned{}" }, - ch_c_cry_all_banana = { "All Jokers are {C:eternal}Banana{}" }, - ch_c_all_rnj = { "All Jokers are {C:attention}RNJoker{}" }, - ch_c_cry_sticker_sheet_plus = { "All purchasable items have all stickers" }, - ch_c_cry_rush_hour = { "All Boss Blinds are {C:attention}The Clock{} or {C:attention}Lavender Loop" }, - ch_c_cry_rush_hour_ii = { "All Blinds are {C:attention}Boss Blinds{}" }, - ch_c_cry_rush_hour_iii = { - "{C:attention}The Clock{} and {C:attention}Lavender Loop{} scale {C:attention}twice{} as fast", - }, - ch_c_cry_no_tags = { "Skipping is {C:attention}disabled{}" }, - ch_c_cry_no_vouchers = { "{C:attention}Vouchers{} no longer appear in the shop" }, - ch_c_cry_no_boosters = { "{C:attention}Booster Packs{} no longer appear in the shop" }, - ch_c_cry_no_rerolls = { "Rerolling is {C:attention}disabled{}" }, - ch_c_cry_no_consumables = { "{C:attention}Consumables{} no longer appear" }, - }, - -- Thanks to many members of the community for contributing to all of these quips! - -- There's too many to credit so just go here: https://discord.com/channels/1116389027176787968/1209506360987877408/1237971471146553406 - -- And here: https://discord.com/channels/1116389027176787968/1219749193204371456/1240468252325318667 very_fair_quips = { - { "L", "NO VOUCHERS", "FOR YOU" }, - { "BOZO", "DID YOU THINK I WOULD", "GIVE YOU A VOUCHER?" }, - { "NOPE!", "NO VOUCHERS HERE!", "(SLUMPAGE EDITION)" }, - { "SKILL ISSUE", "IMAGINE BEING GOOD ENOUGH", "FOR A VOUCHER" }, - { "JIMBO", "FROM MANAGEMENT", "FORGOT TO RESTOCK" }, - { "OOPS!", "NO VOUCHERS", "" }, - { "YOU JOKER,", "WHY ARE YOU LOOKING", "OVER HERE? LOL" }, - { "THE VOUCHER", "IS IN", "ANOTHER CASTLE" }, - { "$0", "BLANK VOUCHER", "(GET IT?)" }, - { "ERROR", "CANNOT DO ARITHMETIC ON A NIL VALUE", "(tier4vouchers.lua)" }, - { "100% OFF", "ON ALL VOUCHERS", "(SOMEONE ALREADY BOUGHT THEM)" }, - { "TRY AGAIN LATER", "HINT: YOU WON'T HAVE", "ENOUGH MONEY ANYWAYS" }, - { "HUH?", '"VOUCHER"?', "THAT'S NOT EVEN A WORD..." }, - { 'HOLD "R"', "TO RESTOCK", "ALL VOUCHERS" }, - { "DID YOU KNOW?", "PRESSING ALT+F4", "GIVES FREE VOUCHERS!" }, - { "SORRY,", "THERE ARE NO VOUCHERS", "DUE TO BUDGET CUTS" }, - { "CALL 1-600-JIMBO", "TO RATE YOUR", "VOUCHER EXPERIENCE" }, - { "DEFEAT", "ANTE 39 BOSS BLIND", "TO RESTOCK" }, - { "MAGIC TRICK", "I MADE THIS VOUCHER", "DISAPPEAR" }, - { "WHY IS A", "VOUCHER LIKE", "A WRITING DESK?" }, - { "WE HAVE RETRACTED", "YOUR VOUCHERS, THEY WOULD BE", "BETTER USED IN OTHER RUNS" }, - { "WHY DO THEY CALL IT VOUCHER", "WHEN MULT OUT THE HOT", "IN COLD EAT EAT THE CHIP" }, - { "SORRY", "THE VOUCHERS ARE EXPERIENCING", "VOUCHIFIA ABORTUS" }, - { "UNFORTUNATELY", "THE VOUCHRX REWRITE UPDATE", "HAS BEEN CANCELLED" }, - { "DEFEAT", "BOSS BLIND", "TO CHANGE NOTHING" }, - { "BIRDS ARE SINGING", "FLOWERS ARE BLOOMING", "KIDS LIKE YOU..." }, - { "WE ARE SORRY TO SAY", "ALL VOUCHERS HAVE BEEN RECALLED", "DUE TO SALMONELLA EXPOSURE" }, - { "VOUCHERS COULDN'T ARRIVE", "DUE TO SHOP LAYOUT BEING", "200% OVERBUDGET" }, - { "YOU LIKE", "BUYING VOUCHERS, DON'T YOU", "YOU'RE A VOUCHERBUYER" }, - { "VOUCHERS", "!E", "VOUCHER POOL" }, - { "THERE", "IS NO", "VOUCHER" }, - { "THERE IS", "NO SANTA", "AND THERE ARE NO VOUCHERS" }, - { "", "VOUCHERN'T", "" }, - { "YOU", "JUST LOST", "THE GAME" }, - { "CAN I OFFER YOU", "A NICE EGG", "IN THESE TRYING TIMES?" }, - { "GO TOUCH GRASS", "INSTEAD OF USING", "THIS DECK" }, - { "YOU COULD BE", "PLAYING ON BLUE DECK", "RIGHT NOW" }, - { "FREE EXOTICS", "GET THEM BEFORE ITS", "TOO LATE (sold out)" }, - { "PROVE THEM WRONG", "BUY BUYING AN INVISIBLE", "VOUCHER FOR $10" }, - { "", "no vouchers?", "" }, - { "see this ad?", "if you are, then it's working", "and you could have it for your own" }, - { "YOU'RE MISSING OUT ON", "AT LEAST 5 VOUCHERS RIGHT NOW", "tonktonktonktonktonk" }, - { "10", "20 NO VOUCHER XD", "30 GOTO 10" }, - { "VOUCHERS", "ARE A PREMIUM FEATURE", "$199.99 JOLLARS TO UNLOCK" }, - { "TRUE VOUCHERLESS!?!?", "ASCENDANT STAKE ONLY", "VERY FAIR DECK" }, - { "ENJOYING YOUR", "VOUCHER EXPERIENCE? GIVE US A", "FIVE STAR RATING ON JESTELP" }, - { "FREE VOUCHERS", "HOT VOUCHERS NEAR YOU", "GET VOUCHERS QUICK WITH THIS ONE TRICK" }, - { "INTRODUCING", "THE VERY FIRST TIER 0 VOUCHER!", "(coming to Cryptid 1.0 soon)" }, - { "A VOUCHER!", "IT'S JUST IMAGINARY", "WE IMAGINED YOU WOULD WANT IT, THAT IS" }, - { "TURN OFF ADBLOCKER", "WITHOUT ADS, WE WOULDN'T", "BE ABLE TO SELL YOU VOUCHERS" }, - { "IF YOU HAVE", "A PROBLEM WITH THIS", "EMAIL IT TO US AT NORESPONSE@JMAIL.COM" }, - { "NOT ENOUGH MONEY", "TO BUY THIS VOUCHER", "SO WHY WOULD WE PUT IT HERE?" }, - { "WANT A VOUCHER?", "WELL SHUT UP", "YOU CAN'T HAVE ANY LOL" }, - { "^$%& NO", "VOUCHERS ^%&% %&$^% FOR", "$%&%%$ %&$&*%$^ YOU" }, - { "A VOUCHER (TRUST)", "|\\/|", "|/\\|" }, + { "ㅋ", "바우처는", "없어" }, + { "바보야", "내가 바우처를 줄 거라고", "생각했어?" }, + { "놉!", "여기엔 바우처 없어!", "(폭락 에디션)" }, + { "실력 문제", "바우처 받을 만큼", "잘한다고 생각해?" }, + { "관리부의", "짐보가", "재입고를 잊었어" }, + { "어이쿠!", "바우처 없음", "" }, + { "이 조커야,", "여긴 왜 보고 있어?", "ㅋㅋㅋ" }, + { "바우처는", "다른 성에", "있습니다" }, + { "$0", "빈 바우처", "(이해했지?)" }, + { "오류", "NIL 값에 대한 산술 연산 불가", "(tier4vouchers.lua)" }, + { "모든 바우처", "100% 할인", "(누군가 이미 다 사감)" }, + { "나중에 다시 시도해", "힌트: 어차피 돈도", "부족할걸" }, + { "응?", '"바우처"?', "그런 단어는 없는데..." }, + { '"R" 키를 누르면', "모든 바우처가", "재입고됩니다" }, + { "알고 계셨나요?", "ALT+F4를 누르면", "무료 바우처를 줍니다!" }, + { "죄송합니다,", "예산 삭감으로 인해", "바우처가 없습니다" }, + { "1-600-JIMBO로 전화해서", "바우처 경험을", "평가해주세요" }, + { "앤티 39 보스 블라인드를", "이기면", "재입고됩니다" }, + { "마술", "내가 이 바우처를", "사라지게 했지" }, + { "왜 바우처를", "책상과 같다고", "할까?" }, + { "귀하의 바우처는 회수되었습니다.", "다른 런에서 더 잘", "사용될 것입니다" }, + { + "왜 그들은 바우처라고 부를까", + "차가운 칩을 먹고 뜨거운 배수를", + "내놓을 때", + }, + { "죄송합니다", "바우처가 현재", "바우치피아 아보르투스를 겪고 있습니다" }, + { "안타깝게도", "VOUCHRX 재작성 업데이트는", "취소되었습니다" }, + { "보스 블라인드를 이겨도", "아무것도", "바뀌지 않습니다" }, + { "새들은 노래하고", "꽃들은 피어나고", "너 같은 꼬마들은..." }, + { "유감스럽게도 모든 바우처는", "살모넬라 노출로 인해", "리콜되었습니다" }, + { "상점 레이아웃이 예산을", "200% 초과하여 바우처가", "도착하지 못했습니다" }, + { "너 바우처 사는 거", "좋아하지, 그렇지?", "넌 바우처바이어야" }, + { "바우처", "!E", "바우처 풀" }, + { "여기에는", "바우처가", "없다" }, + { "산타는 없어", "그리고 바우처도", "없지" }, + { "", "바우처없음", "" }, + { "당신은", "방금 게임에서", "졌습니다" }, + { "이 힘든 시기에", "근사한 달걀 하나", "드릴까요?" }, + { "이 덱 쓰는 대신", "나가서 풀이나", "만져" }, + { "지금쯤", "블루 덱으로", "플레이할 수도 있었는데" }, + { "무료 이그조틱", "늦기 전에 가져가세요", "(매진)" }, + { "10달러에 보이지 않는 바우처를", "사서 그들이 틀렸다는 것을", "증명하세요" }, + { "", "바우처 없어?", "" }, + { + "이 광고 보여?", + "보인다면 작동하는 거야", + "너도 가질 수 있어", + }, + { "지금 최소 5개의", "바우처를 놓치고 있어", "통통통통통" }, + { "10", "20 바우처 없음 XD", "30 GOTO 10" }, + { "바우처는", "프리미엄 기능입니다", "잠금 해제하려면 199.99 졸라 필요" }, + { "진정한 바우처리스!?!?", "승천 스테이크 전용", "아주 공정한 덱" }, + { "바우처 경험이", "즐거우셨나요? 제스텔프에서", "별 5개 평점을 주세요" }, + { + "무료 바우처", + "당신 근처의 핫한 바우처", + "이 한 가지 트릭으로 바우처를 빠르게 얻으세요", + }, + { "최초의 0등급 바우처를", "소개합니다!", "(크립티드 1.0에 곧 출시)" }, + { + "바우처다!", + "그냥 상상 속의 것이지만", + "네가 원할 거라고 상상했지", + }, + { "애드블록을 끄세요", "광고 없이는 바우처를", "팔 수 없습니다" }, + { + "이 문제에 대해 불만이", + "있으시다면, 이메일을 보내주세요", + "NORESPONSE@JMAIL.COM", + }, + { "이 바우처를 살 돈이", "부족해서", "여기에 놓지 않았습니다" }, + { "바우처를 원해?", "닥쳐", "넌 가질 수 없어 ㅋ" }, + { "^$%& 없어", "바우처 ^%&% %&$^% 너한테는", "$%&%%$ %&$&*%$^" }, + { "바우처 (믿어줘)", "|\\/|", "|/\\|" }, { "... --- ...", ".--. .-.. .- -.-- . .-. -.. . -.-. --- -.. . -.. -- --- .-. ... .", "-.-. --- -.. . - --- ..-. .. -. -.. .- ...- --- ..- -.-. .... . .-.", }, - { "RUN > NEW", "STARE AT NOTHING", "FOR AN HOUR OR TWO" }, - { "WE'RE VERY SORRY", "THE LAST GUY PANIC BOUGHT", "ALL THE VOUCHERS" }, - { "HOW IT FEELS", "TO BUY NO", "VOUCHERS" }, - { "JIMBO GOT A NAT 1", "AND DUMPED ALL THE", "VOUCHERS IN A DITCH" }, - { "ATTEMPT TO INDEX", "FIELD 'VOUCHER'", "(A NIL VALUE)" }, + { "런 > 새로 만들기", "한두 시간 동안", "허공을 응시하세요" }, { - "OH YOU REALLY THOUGHT THAT READING ALL THESE LINES WOULD BRING YOUR VOUCHERS BACK?", - "SORRY TO TELL YOU, BUT THIS DECK DOESN'T CONTAIN THE VOUCHERS YOU SEEK.", - "THIS ABNORMALLY LONG TEXT IS HERE AND DESIGNED TO WASTE YOUR TIME AND EFFORT WHILE YOU READ IT.", + "정말 죄송합니다", + "마지막 사람이 패닉 바잉으로", + "모든 바우처를 사갔습니다", }, - { "GO TO", "https://youtu.be/p7YXXieghto", "FOR FREE VOUCHERS" }, + { "바우처를", "사지 않는", "기분" }, + { "짐보가 주사위 1 나와서", "모든 바우처를", "도랑에 버렸습니다" }, + { "'바우처' 필드", "인덱싱 시도", "(NIL 값)" }, + { + "이 모든 글을 읽으면 바우처가 돌아올 거라고 정말 생각했어?", + "미안하지만 이 덱에는 네가 찾는 바우처가 없어.", + "이 비정상적으로 긴 텍스트는 네가 읽는 동안 시간과 노력을 낭비하도록 설계되었어.", + }, + { "무료 바우처는", "https://youtu.be/p7YXXieghto", "으로 가세요" }, }, }, } diff --git a/Cryptid/localization/nl.lua b/Cryptid/localization/nl.lua index f64b7bb..dc3fc31 100644 --- a/Cryptid/localization/nl.lua +++ b/Cryptid/localization/nl.lua @@ -1225,7 +1225,7 @@ return { "{C:attention}first discard{} of each round", }, }, - j_cry_Megg = { + j_cry_megg = { name = "Megg", text = { "Sell this card to create", @@ -1239,7 +1239,7 @@ return { "{X:mult,C:white}X#1#{} Mult for each member", "in the {C:attention}Cryptid Discord{}", "{C:inactive}(Currently {X:mult,C:white}X#2#{C:inactive} Mult)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_membershipcardtwo = { @@ -1248,7 +1248,7 @@ return { "{C:chips}+#1#{} Chips for each member", "in the {C:attention}Cryptid Discord{}", "{C:inactive}(Currently {C:chips}+#2#{C:inactive} Chips)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_meteor = { @@ -2049,6 +2049,14 @@ return { "card in your hand", }, }, + c_cry_meld = { + name = "Meld", + text = { + "Select a {C:attention}Joker{} or", + "{C:attention}playing card{} to", + "become {C:dark_edition}Double-Sided", + }, + }, c_cry_vacuum = { name = "Vacuum", text = { @@ -2481,14 +2489,6 @@ return { "into an {C:attention}Echo Card", }, }, - c_cry_meld = { - name = "Meld", - text = { - "Select a {C:attention}Joker{} or", - "{C:attention}playing card{} to", - "become {C:dark_edition}Double-Sided", - }, - }, c_cry_theblessing = { name = "The Blessing", text = { @@ -2720,6 +2720,15 @@ return { }, }, Other = { + alt_wheel_of_fortune = { + name = "Het rad van fortuin", + text = { + "Een kans van {C:green}#1# op #2#{} om", + "{C:dark_edition}folie{}, {C:dark_edition}holografische{} of", + "{C:dark_edition}polychrome{} editie toe te voegen", + "aan een willekeurige {C:attention}Joker", + }, + }, banana = { name = "Banana", text = { @@ -3044,6 +3053,7 @@ return { cry_debuff_obsidian_orb = "Applies abilities of all defeated bosses", k_code = "Code", + k_chips = "fiches", b_code_cards = "Code Cards", b_pull = "PULL", cry_hooked_ex = "Hooked!", diff --git a/Cryptid/localization/pl.lua b/Cryptid/localization/pl.lua index a1b7e39..97527e1 100644 --- a/Cryptid/localization/pl.lua +++ b/Cryptid/localization/pl.lua @@ -52,8 +52,8 @@ return { name = "Krytyczna Talia", text = { "Po każdej zagranej ręce,", - "{C:green}#1# na 4{} szans na mnożnik {X:dark_edition,C:white} ^2 {}", - "{C:green}#1# na 8{} szans na mnożnik {X:dark_edition,C:white} ^0.5 {}", + "{C:green}#1# na #2#{} szans na mnożnik {X:dark_edition,C:white} ^2 {}", + "{C:green}#1# na #3#{} szans na mnożnik {X:dark_edition,C:white} ^0.5 {}", }, }, b_cry_encoded = { @@ -136,7 +136,7 @@ return { name = "Legendarna Talia", text = { "Rozpoczynasz podejście z {C:legendary}legendarnym{C:legendary} jokerem", - "{C:green}1 in 5{} szans na dodanie kolejnego", + "{C:green}#1# in #2#{} szans na dodanie kolejnego", "po pokonaniu przeszkadzajki bossa", "{C:inactive}(wymaga miejsca){}", }, @@ -1426,7 +1426,7 @@ return { "{C:attention}pierwsza zrzutka{} rundy", }, }, - j_cry_Megg = { + j_cry_megg = { name = "M-Jajko", text = { "Sprzedaj tę kartę, aby stworzyć", @@ -1448,7 +1448,7 @@ return { "Mnoż. {X:mult,C:white}X#1#{} za każdego członka", "discordowego serwera {C:attention}Cryptid{}", "{C:inactive}(obecny mnoż.: {X:mult,C:white}X#2#{C:inactive}", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_membershipcardtwo = { @@ -1457,7 +1457,7 @@ return { "{C:chips}+#1#{} za każdego członka", "discordowego serwera {C:attention}Cryptid{}", "{C:inactive}(obecnie: {C:chips}+#2#{C:inactive} żet.)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_meteor = { @@ -2475,6 +2475,14 @@ return { "karty w ręcę", }, }, + c_cry_meld = { + name = "Wtopienie", + text = { + "Wybierz {C:attention}jokera{} lub", + "{C:attention}kartę rozgrywającą{}, aby", + "stała się {C:dark_edition}Dwustronna", + }, + }, c_cry_vacuum = { name = "Próżnia", text = { @@ -2907,14 +2915,6 @@ return { "do: {C:attention}Karta Echa", }, }, - c_cry_meld = { - name = "Wtopienie", - text = { - "Wybierz {C:attention}jokera{} lub", - "{C:attention}kartę rozgrywającą{}, aby", - "stała się {C:dark_edition}Dwustronna", - }, - }, c_cry_theblessing = { name = "Błogosławieństwo", text = { @@ -3141,6 +3141,15 @@ return { }, }, Other = { + alt_wheel_of_fortune = { + name = "Koło Fortuny", + text = { + "{C:green}#1# na #2#{} szans zamiany", + "losowego {C:attention}jokera na jego wersję", + "{C:dark_edition}w folii{}, {C:dark_edition}holograficzną{} lub", + "{C:dark_edition}polichromowaną{}", + }, + }, banana = { name = "Bananowy", text = { @@ -3653,6 +3662,7 @@ return { cry_debuff_obsidian_orb = "Aplikuje zdolności wszystkich pokonanych bossów", k_code = "Kod", + k_chips = "żet", k_unique = "Unikalny", b_code_cards = "Karty Kodowe", b_unique_cards = "Unikalne Karty", diff --git a/Cryptid/localization/pt_BR.lua b/Cryptid/localization/pt_BR.lua index 8ecd762..2786b18 100644 --- a/Cryptid/localization/pt_BR.lua +++ b/Cryptid/localization/pt_BR.lua @@ -65,8 +65,8 @@ return { name = "Baralho Crítico", text = { "Após cada mão jogada,", - "{C:green}#1# em 4{} de chance para {X:dark_edition,C:white} ^2 {} Mult", - "{C:green}#1# em 8{} de chance para {X:dark_edition,C:white} ^0.5 {} Mult", + "{C:green}#1# em #2#{} de chance para {X:dark_edition,C:white} ^2 {} Mult", + "{C:green}#1# em #3#{} de chance para {X:dark_edition,C:white} ^0.5 {} Mult", }, }, b_cry_e_deck = { @@ -188,7 +188,7 @@ return { name = "Baralho Lendário", text = { "Começe com um Curinga {C:legendary}Lendário{C:legendary}", - "{C:green}1 em 5{} de chance para criar outro", + "{C:green}#1# em #2#{} de chance para criar outro", "quando o Blind Chefe é derrotado", "{C:inactive}(precisa ter espaço){}", }, @@ -645,7 +645,7 @@ return { set_cry_poker_hand_stuff = { name = "Poker Hand Stuff", text = { - "Add 4 new {C:attention}poker hands", + "Add 5 new {C:attention}poker hands", "and enable {C:attention}Ascended hands", }, }, @@ -1894,7 +1894,7 @@ return { "{C:attention}primeiro descarte{} de cada rodada", }, }, - j_cry_Megg = { + j_cry_megg = { name = "Movo", text = { "Venda esta carta para criar", @@ -1916,7 +1916,7 @@ return { "{X:mult,C:white}X#1#{} Mult para cada membro", "no {C:attention}Cryptid Discord{}", "{C:inactive}(Atualmente {X:mult,C:white}X#2#{C:inactive} Mult)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_membershipcardtwo = { @@ -1925,7 +1925,7 @@ return { "{C:chips}+#1#{} Fichas#1# para cada menbro", "no {C:attention}Cryptid Discord{}", "{C:inactive}(Atualmente {C:chips}+#2#{C:inactive} Ficha#2#)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_membershipcardtwo_balanced = { @@ -1934,7 +1934,7 @@ return { "{C:chips}+#1#{} Ficha#1# para cada {C:attention}8{} membros", "no {C:attention}Cryptid Discord{}", "{C:inactive}(Atualmente {C:chips}+#2#{C:inactive} Ficha#2#)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_meteor = { @@ -3112,6 +3112,14 @@ return { "em sua mão", }, }, + c_cry_meld = { + name = "Fusão", + text = { + "Selecione um {C:attention}Curinga{} ou", + "{C:attention}carta de jogo{} para", + "se tornar {C:dark_edition}Duas Caras", + }, + }, c_cry_vacuum = { name = "Vácuo", text = { @@ -3555,14 +3563,6 @@ return { "em uma {C:attention}Carta Eco", }, }, - c_cry_meld = { - name = "Fusão", - text = { - "Selecione um {C:attention}Curinga{} ou", - "{C:attention}carta de jogo{} para", - "se tornar {C:dark_edition}Duas Caras", - }, - }, c_cry_theblessing = { name = "A Benção", text = { @@ -3861,6 +3861,15 @@ return { }, }, Other = { + alt_wheel_of_fortune = { + name = "A Roda da Fortuna", + text = { + "Chance de {C:green}#1# em #2#{} de adicionar", + "edição {C:dark_edition}Laminada{}, {C:dark_edition}Holográfica{} ou", + "{C:dark_edition}Policromática{}", + "a um {C:attention}Curinga aleatório", + }, + }, disabled = { name = "Desativado", text = { @@ -4483,6 +4492,7 @@ return { cry_joke_placeholder = "(multiple of 8)", k_code = "Code", + k_chips = "fichas", k_content_set = "Thematic Set", b_content_sets = "Thematic Sets", --Why aren't these in vanilla? diff --git a/Cryptid/localization/ru.lua b/Cryptid/localization/ru.lua index 10565cf..6435c6c 100644 --- a/Cryptid/localization/ru.lua +++ b/Cryptid/localization/ru.lua @@ -73,20 +73,20 @@ return { }, }, b_cry_conveyor = { - name = "Conveyor Deck", + name = "Конвейерная колода", text = { - "Jokers may {C:attention}not{} be moved", - "At start of round,", - "{C:attention}duplicate{} rightmost Joker", - "and {C:attention}destroy{} leftmost Joker", + "Джокеров {C:attention}нельзя{} двигать", + "в начале раунда,", + "{C:attention}дублирует{} самого правого джокера", + "и {C:attention}уничтожает{} самого левого джокера", }, }, b_cry_critical = { name = "Критическая колода", text = { "После каждой сыгранной руки,", - "{C:green}#1# к 4{} шанс для {X:dark_edition,C:white} ^2 {} Множ", - "{C:green}#1# к 8{} шанс для {X:dark_edition,C:white} ^0.5 {} Множ", + "{C:green}#1# к #2#{} шанс для {X:dark_edition,C:white} ^2 {} Множ", + "{C:green}#1# к #3#{} шанс для {X:dark_edition,C:white} ^0.5 {} Множ", }, }, b_cry_encoded = { @@ -108,7 +108,7 @@ return { }, }, b_cry_glowing = { - name = "Glowing Deck", + name = "Светящаяся колода", text = { "Умножает значения всех", "джокеров на {X:dark_edition,C:white} X1.25 {}", @@ -646,21 +646,21 @@ return { j_cry_bonk = { name = "Bonk", text = { - "Each {C:attention}Joker{} gives {C:chips}+#1#{} Chips", - "Increase amount by {C:chips}+#2#{} if", - "{C:attention} poker hand{} is a {C:attention}#3#{}", - "{C:inactive,s:0.8}Jolly Jokers give{} {C:chips,s:0.8}+#4#{} {C:inactive,s:0.8}Chips instead{}", + "Каждый {C:attention}Джокер{} дает {C:chips}+#1#{} фишек", + "Увеличивает значение на {C:chips}+#2#{} если", + "{C:attention}покерная рука{} это {C:attention}#3#{}", + "{C:inactive,s:0.8}Веселые Джокеры вместо этого дают{} {C:chips,s:0.8}+#4#{} {C:inactive,s:0.8}фишек{}", }, }, j_cry_bonusjoker = { - name = "Bonus Joker", + name = "Бонусный Джокер", text = { - "{C:green}#1# in #2#{} chance for each", - "played {C:attention}Bonus{} card to increase", - "{C:attention}Joker{} or {C:attention}Consumable slots", - "by {C:dark_edition}1{} when scored", - "{C:red}Works twice per round", - "{C:inactive,s:0.8}(Equal chance for each){}", + "{C:green}#1# из #2#{} шанс что каждая", + "сыгранная {C:attention}Бонусная{} карта увеличит", + "{C:attention}слоты для {C:attention}джокеров{} или {C:attention}расходников", + "на {C:dark_edition}1{} когда засчитана", + "{C:red}Работает дважды за раунд", + "{C:inactive,s:0.8}(Равный шанс у каждой){}", }, }, j_cry_booster = { @@ -754,11 +754,11 @@ return { }, }, j_cry_coin = { - name = "Crypto Coin", + name = "Крипто Монета", text = { - "Earn between", - "{C:money}$#1#{} and {C:money}$#2#{} for", - "each Joker {C:attention}sold{}", + "Получите между", + "{C:money}$#1#{} и {C:money}$#2#{} за", + "каждого {C:attention}проданного{} джокера", }, }, j_cry_compound_interest = { @@ -771,62 +771,62 @@ return { }, }, j_cry_copypaste = { - name = "Copy/Paste", + name = "Копировать/Вставить", text = { - "When a {C:cry_code}Code{} card is used,", - "{C:green}#1# in #2#{} chance to add a copy", - "to your consumable area", - "{C:inactive}(Must have room)", + "Когда карта {C:cry_code}Кода{} использована,", + "{C:green}#1# из #2#{} шанс создает её копию", + "в вашей зоне расходуемых", + "{C:inactive}(Должно быть место)", }, }, j_cry_crustulum = { name = "Crustulum", text = { - "This Joker gains {C:chips}+#2#{} Chips", - "per {C:attention}reroll{} in the shop", - "{C:green}All rerolls are free{}", - "{C:inactive}(Currently {C:chips}+#1#{C:inactive} chips)", + "Этот джокер дает {C:chips}+#2#{} фишек", + "за каждый {C:attention}переброс{} в лавке", + "{C:green}Все перебросы бесплатные{}", + "{C:inactive}(Сейчас {C:chips}+#1#{C:inactive} фишек)", }, }, j_cry_cryptidmoment = { - name = "M Chain", + name = "Цепь М", text = { - "Sell this card to", - "add {C:money}$#1#{} of {C:attention}sell value{}", - "to every {C:attention}Joker{} card", + "Продайте эту карту", + "чтобы добавить {C:money}$#1#{} {C:attention}к цене продажи{}", + "каждого {C:attention}джокера{}", }, }, j_cry_cube = { - name = "Cube", + name = "Куб", text = { - "{C:chips}+#1#{} Chips", + "{C:chips}+#1#{} фишек", }, }, j_cry_curse_sob = { name = "Sob", text = { - "{C:edition,E:1}you cannot{} {C:cry_ascendant,E:1}run...{}", - "{C:edition,E:1}you cannot{} {C:cry_ascendant,E:1}hide...{}", - "{C:dark_edition,E:1}you cannot escape...{}", - "{C:inactive}(Must have room){}", + "{C:edition,E:1}ты не можешь{} {C:cry_ascendant,E:1}бежать...{}", + "{C:edition,E:1}ты не можешь{} {C:cry_ascendant,E:1}прятаться...{}", + "{C:dark_edition,E:1}ты не можешь...{}", + "{C:inactive}(Должно быть место){}", }, }, j_cry_cursor = { - name = "Cursor", + name = "Курсор", text = { - "This Joker gains {C:chips}+#2#{} Chips", - "for each card {C:attention}purchased{}", - "{C:inactive}(Currently {C:chips}+#1#{C:inactive} Chips)", + "Этот джокер дает {C:chips}+#2#{} фишек", + "за каждую {C:attention}купленную{} карта", + "{C:inactive}(Сейчас {C:chips}+#1#{C:inactive} фишек)", }, }, j_cry_cut = { - name = "Cut", + name = "Разрез", text = { - "This Joker destroys", - "a random {C:cry_code}Code{} card", - "and gains {X:mult,C:white} X#1# {} Mult", - "at the end of the {C:attention}shop{}", - "{C:inactive}(Currently {X:mult,C:white} X#2# {C:inactive} Mult)", + "Этот джокер уничтожает", + "случайную карту {C:cry_code}Кода{}", + "и получает {X:mult,C:white} X#1# {} множ.", + "в конце {C:attention}магазина{}", + "{C:inactive}(Сейчас {X:mult,C:white} X#2# {C:inactive} множ.)", }, }, j_cry_delirious = { @@ -939,10 +939,10 @@ return { }, }, j_cry_exoplanet = { - name = "Exoplanet", + name = "Экзопланета", text = { - "{C:dark_edition}Holographic{} cards", - "each give {C:mult}+#1#{} Mult", + "{C:dark_edition}Голографические{} карты", + "дают {C:mult}+#1#{} множ.", }, }, j_cry_exponentia = { @@ -1027,7 +1027,7 @@ return { }, }, j_cry_giggly = { - name = "Absurd Joker", + name = "Абсурдный джокер", text = { "{C:red}+#1#{} Mult if played", "hand contains", @@ -1035,7 +1035,7 @@ return { }, }, j_cry_goldjoker = { - name = "Gold Joker", + name = "Золотой джокер", text = { "Earn {C:money}#1#%{} of total", "money at end of round", @@ -1062,7 +1062,7 @@ return { }, }, j_cry_happyhouse = { - name = "Happy House", + name = "Счастливый дом", text = { "{X:dark_edition,C:white}^#1#{} Mult only after", "playing {C:attention}114{} hands{}", @@ -1071,11 +1071,11 @@ return { }, }, j_cry_home = { - name = "The Home", + name = "Дом", text = { - "{X:mult,C:white} X#1# {} Mult if played", - "hand contains", - "a {C:attention}#2#", + "{X:mult,C:white} X#1# {} множ. если сыгранная", + "содержит", + "{C:attention}#2#", }, }, j_cry_hunger = { @@ -1105,7 +1105,7 @@ return { }, }, j_cry_jollysus = { - name = "Jolly Joker?", + name = "Веселый джокер?", text = { "Create a {C:dark_edition}Jolly{} Joker", "when a Joker is {C:attention}sold{}", @@ -1115,20 +1115,20 @@ return { }, }, j_cry_kidnap = { - name = "Kidnapping", + name = "Похищение", text = { - "Earn {C:money}$#2#{} at end of round", - "Increase payout by {C:money}$#1#{}", - "when a {C:attention}Type Mult{} or", - "{C:attention}Type Chips{} Joker is sold", + "Получайте {C:money}$#2#{} в конце раунда", + "Выплата увеличивается на {C:money}$#1#{}", + "когда {C:attention}Тип множ.{} или", + "{C:attention}Тип фишек{} джокер продан", }, }, j_cry_kooky = { name = "Kooky Joker", text = { - "{C:red}+#1#{} Mult if played", - "hand contains", - "a {C:attention}#2#", + "{C:red}+#1#{} множ. если сыгранная", + "рука содержит", + "{C:attention}#2#", }, }, j_cry_krustytheclown = { @@ -1141,27 +1141,27 @@ return { }, }, j_cry_kscope = { - name = "Kaleidoscope", + name = "Калейдоскоп", text = { - "Add {C:dark_edition}Polychrome{} to", - "a random {C:attention}Joker{} when", - "{C:attention}Boss Blind{} is defeated", + "Добавляет {C:dark_edition}Полихром{} к", + "случайному {C:attention}джокеру{} когда", + "{C:attention}блайнд босс{} побежден", }, }, j_cry_lightupthenight = { name = "Light Up the Night", text = { - "Each played {C:attention}7{} or {C:attention}2{}", - "gives {X:mult,C:white}X#1#{} Mult when scored", + "Каждая сыгранная {C:attention}7{} или {C:attention}2{}", + "дает {X:mult,C:white}X#1#{} множ. когда подсчитана", }, }, j_cry_longboi = { - name = "Monster", + name = "Монстр", text = { - "Give future copies of", - "this Joker {X:mult,C:white}X#1#{} Mult", - "at end of round", - "{C:inactive}(Currently {X:mult,C:white}X#2#{C:inactive} Mult){}", + "Дает будущим копиям", + "этого джокера {X:mult,C:white}X#1#{} множ.", + "в конце раунда", + "{C:inactive}(Сейчас {X:mult,C:white}X#2#{C:inactive} множ.){}", }, }, j_cry_loopy = { @@ -1175,34 +1175,34 @@ return { }, }, j_cry_lucky_joker = { - name = "Lucky Joker", + name = "Счастливый джокер", text = { - "Earn {C:money}$#1#{} every time a", - "{C:attention}Lucky{} card {C:green}successfully{}", - "triggers", + "Получите {C:money}$#1#{} каждый раз когда", + "{C:attention}Счастливая{} карта {C:green}успешно{}", + "срабатывает", }, }, j_cry_luigi = { - name = "Luigi", + name = "Луиджи", text = { - "All Jokers give", - "{X:chips,C:white} X#1# {} Chips", + "Все джокеры дают", + "{X:chips,C:white} X#1# {} фишек", }, }, j_cry_m = { - name = "m", + name = "м", text = { - "This Joker gains {X:mult,C:white} X#1# {} Mult", - "when {C:attention}Jolly Joker{} is sold", - "{C:inactive}(Currently {X:mult,C:white} X#2# {C:inactive} Mult)", + "Этот джокер получает {X:mult,C:white} X#1# {} множ.", + "когда {C:attention}Веселый Джокер{} продан", + "{C:inactive}(Сейчас {X:mult,C:white} X#2# {C:inactive} множ.)", }, }, j_cry_M = { - name = "M", + name = "М", text = { - "Create a {C:dark_edition}Negative{}", - "{C:attention}Jolly Joker{} when", - "{C:attention}Blind{} is selected", + "Создает {C:dark_edition}Негативного{}", + "{C:attention}Веселого Джокера{} при", + "выборе {C:attention}блайнда{}", }, }, j_cry_macabre = { @@ -1216,11 +1216,11 @@ return { }, }, j_cry_magnet = { - name = "Fridge Magnet", + name = "Магнит на холодильник", text = { - "Earn {C:money}$#1#{} at end of round", - "This earns {X:money,C:white} X#2# {} if there are", - "{C:attention}#3#{} or fewer {C:attention}Joker{} cards", + "Получайте {C:money}$#1#{} в конце раунда", + "Дает {X:money,C:white} X#2# {} если", + "у вас {C:attention}#3#{} или меньше {C:attention}джокеров{}", }, }, j_cry_manic = { @@ -1248,15 +1248,15 @@ return { }, }, j_cry_maze = { - name = "Labyrinth", + name = "Лабиринт", text = { - "All hands are considered the", - "{C:attention}first hand{} of each round,", - "all discards are considered the", - "{C:attention}first discard{} of each round", + "Все руки считаются", + "{C:attention}первыми руками{} каждого раунда,", + "все сбросы считаются", + "{C:attention}первыми сбросами{} каждого раунда", }, }, - j_cry_Megg = { + j_cry_megg = { name = "Megg", text = { "Sell this card to create", @@ -1270,7 +1270,7 @@ return { "{X:mult,C:white}X#1#{} Mult for each member", "in the {C:attention}Cryptid Discord{}", "{C:inactive}(Currently {X:mult,C:white}X#2#{C:inactive} Mult)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_membershipcardtwo = { @@ -1279,14 +1279,14 @@ return { "{C:chips}+#1#{} Chips for each member", "in the {C:attention}Cryptid Discord{}", "{C:inactive}(Currently {C:chips}+#2#{C:inactive} Chips)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_meteor = { - name = "Meteor Shower", + name = "Метеоритный дождь", text = { - "{C:dark_edition}Foil{} cards each", - "give {C:chips}+#1#{} Chips", + "{C:dark_edition}Фольговые{} карты", + "дают {C:chips}+#1#{} фишек", }, }, j_cry_mneon = { @@ -1319,11 +1319,11 @@ return { }, }, j_cry_morse = { - name = "Morse Code", + name = "Код Морзе", text = { - "Earn {C:money}$#2#{} at end of round", - "Increase payout by {C:money}$#1#{} when", - "a card with an {C:attention}Edition{} is sold", + "Получите {C:money}$#2#{} в конце раунда", + "Выплата увеличивается на {C:money}$#1#{} когда", + "когда карта с {C:attention}Выпуском{} продана", }, }, j_cry_mprime = { @@ -1356,9 +1356,9 @@ return { }, }, j_cry_negative = { - name = "Negative Joker", + name = "Негативный джокер", text = { - "{C:dark_edition}+#1#{C:attention} Joker{} slots", + "{C:dark_edition}+#1#{}слотов для {C:attention}джокеров{}", }, }, j_cry_nice = { @@ -1370,12 +1370,12 @@ return { }, }, j_cry_night = { - name = "Night", + name = "Ночь", text = { - "{X:dark_edition,C:white}^#1#{} Mult on final", - "hand of round", - "{E:2,C:red}self destructs{} on", - "final hand of round", + "{X:dark_edition,C:white}^#1#{} множ. в последней", + "руке раунда", + "{E:2,C:red}самоуничтожается{} в", + "последней руке раунда", }, }, j_cry_nosound = { @@ -1386,7 +1386,7 @@ return { }, }, j_cry_notebook = { - name = "Notebook", + name = "Блокнот", text = { "{C:green} #1# in #2#{} chance to gain {C:dark_edition}+1{} Joker", "slot per {C:attention}reroll{} in the shop", @@ -1422,13 +1422,13 @@ return { }, }, j_cry_oldblueprint = { - name = "Old Blueprint", + name = "Старый чертеж", text = { - "Copies ability of", - "{C:attention}Joker{} to the right", - "{C:green}#1# in #2#{} chance this", - "card is destroyed", - "at end of round", + "Копирует способность", + "{C:attention}джокера{} справа", + "{C:green}#1# из #2#{} шанс что", + "эта карта уничтожена", + "в конце раунда", }, }, j_cry_oldcandy = { @@ -1450,22 +1450,22 @@ return { }, }, j_cry_panopticon = { - name = "Panopticon", + name = "Паноптикум", text = { - "All hands are considered the", - "{C:attention}last hand{} of each round", -- +$4 + "Все руки считаются", + "{C:attention}последними руками{} каждого раунда", -- +$4 }, }, j_cry_pickle = { - name = "Pickle", + name = "Огурчик", text = { - "When {C:attention}Blind{} is skipped, create", - "{C:attention}#1#{} Tags, reduced by", - "{C:red}#2#{} when {C:attention}Blind{} is selected", + "Когда {C:attention}блайнд{} пропущен, создает", + "{C:attention}#1#{} тегов, уменьшается на", + "{C:red}#2#{} когда {C:attention}блайнд{} выбран", }, }, j_cry_pirate_dagger = { - name = "Pirate Dagger", + name = "Пиратский кинжал", text = { "When {C:attention}Blind{} is selected,", "destroy Joker to the right", @@ -1475,11 +1475,11 @@ return { }, }, j_cry_pot_of_jokes = { - name = "Pot of Jokes", + name = "Горшок шуток", text = { - "{C:attention}#1#{} hand size,", - "increases by", - "{C:blue}#2#{} every round", + "{C:attention}#1#{} размер руки,", + "увеличивается на", + "{C:blue}#2#{} каждый раунд", }, }, j_cry_primus = { @@ -1570,7 +1570,7 @@ return { }, }, j_cry_sapling = { - name = "Sapling", + name = "Росток", text = { "After scoring {C:attention}#2#{} {C:inactive}[#1#]{} Enhanced", "cards, sell this card to", @@ -1666,10 +1666,10 @@ return { }, }, j_cry_stardust = { - name = "Stardust", + name = "Звездная пыль", text = { - "{C:dark_edition}Polychrome{} cards", - "each give {X:mult,C:white}X#1#{} Mult", + "{C:dark_edition}Полихромные{} карты", + "дают {X:mult,C:white}X#1#{} множ.", }, }, j_cry_stella_mortis = { @@ -1725,10 +1725,10 @@ return { }, }, j_cry_tenebris = { - name = "Tenebris", + name = "Тенебрис", text = { - "{C:dark_edition}+#1#{C:attention} Joker{} slots", - "Earn {C:money}$#2#{} at end of round", + "{C:dark_edition}+#1#{} слотов для {C:attention}джокеров{}", + "Получите {C:money}$#2#{} в конце раунда", }, }, j_cry_translucent = { @@ -1882,18 +1882,18 @@ return { }, }, c_cry_nstar = { - name = "Neutron Star", + name = "Нейтронная Звезда", text = { - "Upgrade a random", - "poker hand by", - "{C:attention}1{} level for each", - "{C:attention}Neutron Star{} used", - "in this run", - "{C:inactive}(Currently{C:attention} #1#{C:inactive}){}", + "Улучшите случайную", + "покерную руку на", + "{C:attention}1{} уровень за каждую", + "{C:attention}Нейтронную Звезду{} использованную", + "в этом забеге", + "{C:inactive}(Сейчас{C:attention} #1#{C:inactive}){}", }, }, c_cry_planetlua = { - name = "Planet.lua", + name = "Планета.lua", text = { "{C:green}#1# in #2#{} chance to", "upgrade every", @@ -2007,11 +2007,11 @@ return { }, }, c_cry_gateway = { - name = "Gateway", + name = "Врата", text = { - "Create a random", - "{C:cry_exotic,E:1}Exotic{C:attention} Joker{}, destroy", - "all other Jokers", + "Создайте случайного", + "{C:cry_exotic,E:1}Экзотического{C:attention} джокера{}, уничтожьте", + "всех других джокеров", }, }, c_cry_hammerspace = { @@ -2023,52 +2023,52 @@ return { }, }, c_cry_lock = { - name = "Lock", + name = "Замок", text = { - "Remove {C:red}all{} stickers", - "from {C:red}all{} Jokers,", - "then apply {C:purple,E:1}Eternal{}", - "to a random {C:attention}Joker{}", + "Уберите {C:red}все{} наклейки", + "со {C:red}всех{} джокеров,", + "затем добавьте {C:purple,E:1}Вечную наклейку{}", + "случайному {C:attention}джокеру{}", }, }, c_cry_pointer = { name = "POINTER://", text = { - "Create a card", - "of {C:cry_code}your choice", - "{C:inactive,s:0.8}(Exotic Jokers #1#excluded)", + "Создает карту", + "{C:cry_code}вашего выбора", + "{C:inactive,s:0.8}(исключая Экзотических джокеров)", }, }, c_cry_replica = { name = "Replica", text = { - "Convert all cards", - "held in hand", - "to a {C:attention}random{}", - "card held in hand", + "Конвертирует все", + "карты в руке", + "в {C:attention}случайную{}", + "карту в вашей руке", }, }, c_cry_source = { - name = "Source", + name = "Исходник", text = { - "Add a {C:cry_code}Green Seal{}", - "to {C:attention}#1#{} selected", - "card in your hand", + "Добавьте {C:cry_code}Зеленую печать{}", + "на {C:attention}#1#{} выбранную", + "карту в вашей руке", }, }, c_cry_summoning = { - name = "Summoning", + name = "Призыв", text = { - "Create a random", - "{C:cry_epic}Epic{} {C:joker}Joker{}, destroy", - "one random {C:joker}Joker{}", + "Создайте случайного", + "{C:cry_epic}Эпического{} {C:joker}джокера{}, уничтожьте", + "одного случайного {C:joker}джокера{}", }, }, c_cry_trade = { - name = "Trade", + name = "Обмен", text = { - "{C:attention}Lose{} a random Voucher,", - "gain {C:attention}2{} random Vouchers", + "{C:attention}Потеряйте{} случайный ваучер,", + "получите {C:attention}2{} случайных ваучера", }, }, c_cry_typhoon = { @@ -2079,6 +2079,14 @@ return { "card in your hand", }, }, + c_cry_meld = { + name = "Meld", + text = { + "Select a {C:attention}Joker{} or", + "{C:attention}playing card{} to", + "become {C:dark_edition}Double-Sided", + }, + }, c_cry_vacuum = { name = "Vacuum", text = { @@ -2099,8 +2107,8 @@ return { }, Stake = { stake_cry_pink = { - name = "Pink Stake", - colour = "Pink", --this is used for auto-generated sticker localization + name = "Розовая ставка", + colour = "Розовая", --this is used for auto-generated sticker localization text = { "Required score scales", "faster for each {C:attention}Ante", @@ -2108,15 +2116,15 @@ return { }, stake_cry_brown = { name = "Brown Stake", - colour = "Brown", + colour = "Коричневая", text = { "All {C:attention}stickers{} are compatible", "with each other", }, }, stake_cry_yellow = { - name = "Yellow Stake", - colour = "Yellow", + name = "Желтая ставка", + colour = "Желтая", text = { "{C:attention}Stickers{} can appear on", "all purchasable items", @@ -2138,22 +2146,22 @@ return { }, }, stake_cry_gray = { - name = "Gray Stake", - colour = "Gray", + name = "Серая ставка", + colour = "Серая", text = { "Rerolls increase by {C:attention}$2{} each", }, }, stake_cry_crimson = { - name = "Crimson Stake", - colour = "Crimson", + name = "Багровая ставка", + colour = "Багровая", text = { "Vouchers restock on {C:attention}even{} Antes", }, }, stake_cry_diamond = { - name = "Diamond Stake", - colour = "Diamond", + name = "Алмазная ставка", + colour = "Алмазная", text = { "Must beat Ante {C:attention}10{} to win", }, @@ -2511,14 +2519,6 @@ return { "into an {C:attention}Echo Card", }, }, - c_cry_meld = { - name = "Meld", - text = { - "Select a {C:attention}Joker{} or", - "{C:attention}playing card{} to", - "become {C:dark_edition}Double-Sided", - }, - }, c_cry_theblessing = { name = "The Blessing", text = { @@ -2750,6 +2750,15 @@ return { }, }, Other = { + alt_wheel_of_fortune = { + name = "Колесо Фортуны", + text = { + "Шанс {C:green}#1# из #2#{} добавить", + "{C:dark_edition}фольговый{}, {C:dark_edition}голографический{} или", + "{C:dark_edition}полихромный{} выпуск", + "к случайному {C:attention}джокеру", + }, + }, banana = { name = "Banana", text = { @@ -3061,7 +3070,7 @@ return { cry_mus_high_score = "High Score (Final Boss [For Your Computer] by AlexZGreat)", k_cry_program_pack = "Program Pack", - k_cry_meme_pack = "Meme Pack", + k_cry_meme_pack = "Мемный пак", cry_critical_hit_ex = "Critical Hit!", cry_critical_miss_ex = "Critical Miss!", @@ -3074,6 +3083,7 @@ return { cry_debuff_obsidian_orb = "Applies abilities of all defeated bosses", k_code = "Code", + k_chips = "шт. фишек", b_code_cards = "Code Cards", b_pull = "PULL", cry_hooked_ex = "Hooked!", @@ -3095,7 +3105,7 @@ return { b_flip = "FLIP", b_merge = "MERGE", - cry_again_q = "Again?", + cry_again_q = "Снова?", cry_curse = "Curse", cry_curse_ex = "Curse!", cry_sobbing = "Help me...", @@ -3106,7 +3116,7 @@ return { cry_m_minus = "m", cry_m = "M", cry_m_ex = "M!", - cry_minus_round = "-1 Round", + cry_minus_round = "-1 Раунд", cry_plus_cryptid = "+1 Cryptid", cry_no_triggers = "No triggers left!", cry_unredeemed = "Unredeemed...", @@ -3285,22 +3295,22 @@ return { { "WHY DO THEY CALL IT VOUCHER", "WHEN MULT OUT THE HOT", "IN COLD EAT EAT THE CHIP" }, { "SORRY", "THE VOUCHERS ARE EXPERIENCING", "VOUCHIFIA ABORTUS" }, { "UNFORTUNATELY", "THE VOUCHRX REWRITE UPDATE", "HAS BEEN CANCELLED" }, - { "DEFEAT", "BOSS BLIND", "TO CHANGE NOTHING" }, + { "ПОБЕДИ", "БОСС БЛАЙНД ЧТОБЫ", "НИЧЕГО НЕ ИЗМЕНИТЬ" }, { "BIRDS ARE SINGING", "FLOWERS ARE BLOOMING", "KIDS LIKE YOU..." }, { "WE ARE SORRY TO SAY", "ALL VOUCHERS HAVE BEEN RECALLED", "DUE TO SALMONELLA EXPOSURE" }, { "VOUCHERS COULDN'T ARRIVE", "DUE TO SHOP LAYOUT BEING", "200% OVERBUDGET" }, { "YOU LIKE", "BUYING VOUCHERS, DON'T YOU", "YOU'RE A VOUCHERBUYER" }, { "VOUCHERS", "!E", "VOUCHER POOL" }, - { "THERE", "IS NO", "VOUCHER" }, + { "ВАУЧЕРЫ", "НЕ", "РЕАЛЬНЫ" }, { "THERE IS", "NO SANTA", "AND THERE ARE NO VOUCHERS" }, { "", "VOUCHERN'T", "" }, - { "YOU", "JUST LOST", "THE GAME" }, + { "ТЫ", "ТОЛЬКО ЧТО", "ПРОИГРАЛ ИГРУ" }, { "CAN I OFFER YOU", "A NICE EGG", "IN THESE TRYING TIMES?" }, { "GO TOUCH GRASS", "INSTEAD OF USING", "THIS DECK" }, { "YOU COULD BE", "PLAYING ON BLUE DECK", "RIGHT NOW" }, { "FREE EXOTICS", "GET THEM BEFORE ITS", "TOO LATE (sold out)" }, { "PROVE THEM WRONG", "BUY BUYING AN INVISIBLE", "VOUCHER FOR $10" }, - { "", "no vouchers?", "" }, + { "", "без ваучеров?", "" }, { "see this ad?", "if you are, then it's working", "and you could have it for your own" }, { "YOU'RE MISSING OUT ON", "AT LEAST 5 VOUCHERS RIGHT NOW", "tonktonktonktonktonk" }, { "10", "20 NO VOUCHER XD", "30 GOTO 10" }, @@ -3309,7 +3319,7 @@ return { { "ENJOYING YOUR", "VOUCHER EXPERIENCE? GIVE US A", "FIVE STAR RATING ON JESTELP" }, { "FREE VOUCHERS", "HOT VOUCHERS NEAR YOU", "GET VOUCHERS QUICK WITH THIS ONE TRICK" }, { "INTRODUCING", "THE VERY FIRST TIER 0 VOUCHER!", "(coming to Cryptid 1.0 soon)" }, - { "A VOUCHER!", "IT'S JUST IMAGINARY", "WE IMAGINED YOU WOULD WANT IT, THAT IS" }, + { "ВАУЧЕР!", "ОН ПРОСТО ВООБРАЖАЕМЫЙ", "WE IMAGINED YOU WOULD WANT IT, THAT IS" }, { "TURN OFF ADBLOCKER", "WITHOUT ADS, WE WOULDN'T", "BE ABLE TO SELL YOU VOUCHERS" }, { "IF YOU HAVE", "A PROBLEM WITH THIS", "EMAIL IT TO US AT NORESPONSE@JMAIL.COM" }, { "NOT ENOUGH MONEY", "TO BUY THIS VOUCHER", "SO WHY WOULD WE PUT IT HERE?" }, diff --git a/Cryptid/localization/tools/find_missing.py b/Cryptid/localization/tools/find_missing.py new file mode 100644 index 0000000..2c484d6 --- /dev/null +++ b/Cryptid/localization/tools/find_missing.py @@ -0,0 +1,22 @@ +""" +This Script searches for missing entries in a given localization lua-file, +comparing its contents to en-us.lua. + +Author: Avery (@onichama) +""" + +vars_en = [] +vars_other = [] + +def read_vars_from_file(filename, into_list): + with open(filename) as file_en: + for line in file_en: + if " = {" in line and "text = {" not in line and "unlock = {" not in line: + into_list.append(line.split(" = {")[0].strip()) + +read_vars_from_file("../en-us.lua", vars_en) # Take EN-US as base language +read_vars_from_file("../de.lua", vars_other) # Change this to the language you want to compare to + +for var in vars_en: + if var not in vars_other: + print(var) diff --git a/Cryptid/localization/tools/find_missing_adv.py b/Cryptid/localization/tools/find_missing_adv.py new file mode 100644 index 0000000..0778e4c --- /dev/null +++ b/Cryptid/localization/tools/find_missing_adv.py @@ -0,0 +1,29 @@ +""" +This Script searches for missing entries in a given localization lua-file, +comparing its contents to en-us.lua. +This version also gives the full "path" to a given entry, and can detect +stuff like missing unlock descriptors. + +Author: Avery (@onichama) +""" + +vars_en = [] +vars_other = [] + +def read_vars_from_file(filename, into_list): + current_var_path = [] + with open(filename) as file_en: + for line in file_en: + if " = {" in line: + current_var = line.split(" = {")[0].strip() + current_var_path.append(current_var) + into_list.append(".".join(current_var_path)) + if ("},\n" in line or "}\n" in line) and len(current_var_path) > 0: + current_var_path.pop(len(current_var_path)-1) + +read_vars_from_file("../en-us.lua", vars_en) # Take EN-US as base language +read_vars_from_file("../de.lua", vars_other) # Change this to the language you want to compare to + +for var in vars_en: + if var not in vars_other: + print(var) diff --git a/Cryptid/localization/vi.lua b/Cryptid/localization/vi.lua index 0da796f..fcaa520 100644 --- a/Cryptid/localization/vi.lua +++ b/Cryptid/localization/vi.lua @@ -59,8 +59,8 @@ return { name = "Bộ Bài Chí Mạng", text = { "Sau mỗi tay bài đã chơi,", - "Xác suất {C:green}#1# trên 4{} cho {X:dark_edition,C:white} ^2 {} Nhân", - "Xác suất {C:green}#1# trên 8{} cho {X:dark_edition,C:white} ^0.5 {} Nhân", + "Xác suất {C:green}#1# trên #2#{} cho {X:dark_edition,C:white} ^2 {} Nhân", + "Xác suất {C:green}#1# trên #3#{} cho {X:dark_edition,C:white} ^0.5 {} Nhân", }, }, b_cry_e_deck = { @@ -181,7 +181,7 @@ return { name = "Bộ Bài Huyền Thoại", text = { "Bắt đầu với một Joker {C:legendary}Huyền Thoại", - "Xác suất {C:green}1 trên 5{} tạo ra thêm một lá nữa", + "Xác suất {C:green}#1# trên #2#{} tạo ra thêm một lá nữa", "khi Boss Blind bị đánh bại {C:inactive}(Phải có ô trống)", }, }, @@ -639,7 +639,7 @@ return { set_cry_poker_hand_stuff = { name = "Tay Poker", text = { - "Thêm 4 {C:attention}tay poker mới", + "Thêm 5 {C:attention}tay poker mới", "và cho phép {C:attention}tay Thăng Thiên", }, }, @@ -1775,7 +1775,7 @@ return { "{C:attention}lượt bỏ đầu tiên{} của mỗi ván", }, }, - j_cry_Megg = { + j_cry_megg = { name = "Mrứng", text = { "Bán lá này để tạo ra", @@ -1797,7 +1797,7 @@ return { "{X:mult,C:white}X#1#{} Nhân cho mỗi thành viên", "ở trong {C:attention}Cryptid Discord{}", "{C:inactive}(Hiện tại là {X:mult,C:white}X#2#{C:inactive} Nhân)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_membershipcardtwo = { @@ -1806,7 +1806,7 @@ return { "{C:chips}+#1#{} Chip cho mỗi thành viên", "ở trong {C:attention}Cryptid Discord{}", "{C:inactive}(Hiện tại là {C:chips}+#2#{C:inactive} Chip)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_meteor = { @@ -2912,6 +2912,14 @@ return { "trên tay", }, }, + c_cry_meld = { + name = "Pha Trộn", + text = { + "Chọn một lá {C:attention}Joker{} hoặc", + "{C:attention}Lá bài thường{} để", + "trở thành {C:dark_edition}Hai Mặt", + }, + }, c_cry_vacuum = { name = "Chân Không", text = { @@ -3352,14 +3360,6 @@ return { "thành một {C:attention}Lá Vang Vọng", }, }, - c_cry_meld = { - name = "Pha Trộn", - text = { - "Chọn một lá {C:attention}Joker{} hoặc", - "{C:attention}Lá bài thường{} để", - "trở thành {C:dark_edition}Hai Mặt", - }, - }, c_cry_theblessing = { name = "Phước Lành", text = { @@ -3655,6 +3655,15 @@ return { }, }, Other = { + alt_wheel_of_fortune = { + name = "Bánh Xe Số Phận", + text = { + "Xác suất {C:green}#1# trên #2#{} để thêm", + "ấn bản {C:dark_edition}Ánh Kim{}, {C:dark_edition}Lấp Lánh", + "hoặc {C:dark_edition}Đa Sắc{} cho một {C:attention}Joker", + "ngẫu nhiên", + }, + }, disabled = { name = "Vô Hiệu", text = { @@ -4274,6 +4283,7 @@ return { cry_joke_placeholder = "(bội số của 8)", k_code = "Code", + k_chips = "chip", k_content_set = "Thiết Lập Chủ Đề", b_content_sets = "Thiết Lập Chủ Đề", --Why aren't these in vanilla? diff --git a/Cryptid/localization/zh_CN.lua b/Cryptid/localization/zh_CN.lua index d50f83d..3474c6f 100644 --- a/Cryptid/localization/zh_CN.lua +++ b/Cryptid/localization/zh_CN.lua @@ -7,11 +7,25 @@ return { "每张牌也是一张{C:attention}随机{}消耗牌", "{C:inactive,s:0.8}{C:attention,s:0.8}(Consume Card Deck){C:inactive,s:0.8}", }, + unlock = { + "使用{C:spectral}次元之袋", + }, }, b_cry_antimatter = { name = "反物质牌组", text = { - "拥有{C:legendary,E:1}所有牌组的{}增益效果", + "拥有{C:attention}所有{}牌组的{C:legendary,E:1}增益效果", + }, + unlock = { + "使用{C:attention}黑色牌组", + "在{C:attention}金注{}中获胜", + }, + }, + b_cry_antimatter_balanced = { + name = "反物质牌组", + text = { + "拥有{C:attention}所有{}在{C:gold}金注{}中获胜过的", + "牌组的{C:legendary,E:1}增益效果", }, }, b_cry_beige = { @@ -20,6 +34,11 @@ return { "{C:attention}普通{}小丑具有", "{C:attention}四倍{}的效果", }, + unlock = { + "在收藏中", + "至少发现", + "{C:attention}200{}个项目", + }, }, b_cry_beta = { name = "怀旧牌组", @@ -28,6 +47,9 @@ return { "{C:attention}合并", "boss底注被替换为它们的怀旧版本", }, + unlock = { + "在{C:attention}粉红注{}中获胜", + }, }, b_cry_blank = { name = "空白牌组", @@ -38,25 +60,35 @@ return { b_cry_bountiful = { name = "丰饶牌组", text = { - "每次{C:attention}出牌{} 或 {C:attention}弃牌{}后", + "每次{C:attention}出牌{}或{C:attention}弃牌{}后", "固定抽五张牌", }, + unlock = { + "不使用{C:red}弃牌", + "击败{C:attention}巨蟒", + }, }, b_cry_conveyor = { name = "传送带牌组", text = { "小丑牌{C:attention}不可{}移动", - "回合开始时,", + "回合开始时", "{C:attention}复制{}最右边的小丑牌", "并且{C:attention}销毁{}最左边的小丑牌", }, + unlock = { + "使用{C:spectral}模拟", + }, }, b_cry_critical = { name = "暴击牌组", text = { - "每打出一手牌后,", - "{C:green}#1#/4{}几率获得{X:dark_edition,C:white}^2{}倍率", - "{C:green}#1#/8{}几率获得{X:dark_edition,C:white}^0.5{}倍率", + "每打出一手牌后", + "{C:green}#1#/#2#{}几率获得{X:dark_edition,C:white}^2{}倍率", + "{C:green}#1#/#3#{}几率获得{X:dark_edition,C:white}^0.5{}倍率", + }, + unlock = { + "拥有一张{C:attention}灌铅{}小丑", }, }, ["b_cry_cry-Blue_deck"] = { @@ -94,8 +126,8 @@ return { ["b_cry_cry-bonus_deck"] = { name = "教皇牌组", text = { - "所有的 {C:attention}手牌{}", - "都是 {C:attention,T:m_bonus}奖励牌{}", + "所有的{C:attention}手牌{}", + "都是{C:attention,T:m_bonus}奖励牌{}", "不能更改增强类型", "{s:0.8,C:inactive}", }, @@ -143,8 +175,8 @@ return { ["b_cry_cry-gold_deck"] = { name = "恶魔牌组", text = { - "所有的 {C:attention}手牌{}", - "都是 {C:attention,T:m_gold}黄金牌{}", + "所有的{C:attention}手牌{}", + "都是{C:attention,T:m_gold}黄金牌{}", "不能更改增强类型", "{s:0.8,C:inactive}", }, @@ -168,8 +200,8 @@ return { ["b_cry_cry-lucky_deck"] = { name = "魔术师牌组", text = { - "所有的 {C:attention}手牌{}", - "都是 {C:attention,T:m_lucky}幸运牌{}", + "所有的{C:attention}手牌{}", + "都是{C:attention,T:m_lucky}幸运牌{}", "不能更改增强类型", "{s:0.8,C:inactive}", }, @@ -177,8 +209,8 @@ return { ["b_cry_cry-mult_deck"] = { name = "皇后牌组", text = { - "所有的 {C:attention}手牌{}", - "都是 {C:attention,T:m_mult}倍率牌{}", + "所有的{C:attention}手牌{}", + "都是{C:attention,T:m_mult}倍率牌{}", "不能更改增强类型", "{s:0.8,C:inactive}", }, @@ -223,8 +255,8 @@ return { ["b_cry_cry-steel_deck"] = { name = "战车牌组", text = { - "所有的 {C:attention}手牌{}", - "都是 {C:attention,T:m_steel}钢铁牌{}", + "所有的{C:attention}手牌{}", + "都是{C:attention,T:m_steel}钢铁牌{}", "不能更改增强类型", "{s:0.8,C:inactive}", }, @@ -232,8 +264,8 @@ return { ["b_cry_cry-stone_deck"] = { name = "石头牌组", text = { - "所有的 {C:attention}手牌{}", - "都是 {C:attention,T:m_stone}石头牌{}", + "所有的{C:attention}手牌{}", + "都是{C:attention,T:m_stone}石头牌{}", "不能更改增强类型", "{s:0.8,C:inactive}", }, @@ -241,8 +273,8 @@ return { ["b_cry_cry-wild_deck"] = { name = "爱人牌组", text = { - "所有的 {C:attention}手牌{}", - "都是 {C:attention,T:m_wild}万能牌{}", + "所有的{C:attention}手牌{}", + "都是{C:attention,T:m_wild}万能牌{}", "不能更改增强类型", "{s:0.8,C:inactive}", }, @@ -358,28 +390,62 @@ return { "{s:0.8,C:inactive}", }, }, + b_cry_e_deck = { + name = "版本牌组", + text = { + "所有牌均为{C:dark_edition}#1#{}", + "卡牌无法更改版本", + "{C:inactive}(点击可编辑)", + }, + unlock = { + "发现所有", + "{C:dark_edition}版本", + }, + }, b_cry_encoded = { name = "编码牌组", text = { "以一张{C:cry_code,T:j_cry_CodeJoker}代码小丑{}和一张{C:cry_code,T:j_cry_copypaste}复制/粘贴{}开始", "商店中只出现{C:cry_code}代码牌{}", }, + unlock = { + "使用{C:spectral}://指针", + }, }, b_cry_equilibrium = { name = "均衡牌组", text = { "所有卡牌在", - "商店中出现的{C:attention}几率相同{},", + "商店中出现的{C:attention}几率相同{}", "以{C:attention,T:v_overstock_plus}库存过剩加强版{}开始游戏", }, + unlock = { + "同时拥有{C:attention}100个小丑", + "{C:inactive,s:0.7}译者注:解锁条件应该不是这个", + "{C:inactive,s:0.7}虽然英文原文是这么写的", + }, + }, + b_cry_et_deck = { + name = "增强牌组", + text = { + "所有{C:attention}扑克牌{}均为{C:attention}#1#{}", + "{C:inactive}(点击可编辑)", + }, + unlock = { + "使用{C:spectral}虚空", + }, }, b_cry_glowing = { name = "发光牌组", text = { - "在击败Boss盲注时,", + "在击败Boss盲注时", "所有小丑牌的数值乘以{X:dark_edition,C:white}X1.25{}", "{X:cry_jolly,C:white,s:0.8} Jolly#1#Open#1#Winner#1#-#1#wawa#1#person", }, + unlock = { + "使用{C:attention}四重卡组", + "赢一局", + }, }, b_cry_infinite = { name = "无限牌组", @@ -387,15 +453,21 @@ return { "你可以选择{C:attention}任意数量的卡牌{}", "{C:attention}+1{}手牌上限", }, + unlock = { + "打出一手牌至少包含{C:attention}6{}张牌", + }, }, b_cry_legendary = { name = "传奇牌组", text = { - "以一张 {C:legendary}传奇{C:legendary} 小丑牌开始", + "以一张{C:legendary}传奇{C:legendary}小丑牌开始", "击败Boss盲注后", - "{C:green}1 / 5{} 几率创建另外一张", + "{C:green}#1# / #2#{} 几率创建另外一张", "{C:inactive}(必须有空间){}", }, + unlock = { + "同时拥有{C:attention}2个传奇小丑", + }, }, b_cry_misprint = { name = "错版牌组", @@ -403,13 +475,19 @@ return { "卡牌价格,手牌的数值", "都是{C:attention}随机{}数值", }, + unlock = { + "拥有一个{C:dark_edition}故障{C:attention}小丑", + }, }, b_cry_redeemed = { name = "赎回牌组", text = { - "购买{C:attention}优惠券{}时,", + "购买{C:attention}优惠券{}时", "获得其{C:attention}额外等级{}", }, + unlock = { + "发现所有{C:attention}优惠券{}", + }, }, b_cry_source_deck = { name = "源代码牌组", @@ -422,9 +500,44 @@ return { b_cry_spooky = { name = "万圣节牌组", text = { - "以一张{C:eternal}永恒{} {C:attention,T:j_cry_chocolate_dice}巧克力骰{}开始", - "每次{C:attention}底注{}之后 ", - "创建一个{C:cry_candy}糖果{}或 {X:cry_cursed,C:white}诅咒{}", + "以一张{C:eternal}永恒{}{C:attention,T:j_cry_chocolate_dice}巧克力骰{}开始", + "每个{C:attention}底注{}结束后", + "创建一个{C:cry_candy}糖果{}或{X:cry_cursed,C:white}诅咒{}", + }, + unlock = { + "拥有一张{C:cry_candy}糖果{C:attention}小丑", + }, + }, + b_cry_sk_deck = { + name = "贴纸牌组", + text = { + "所有牌均为{C:attention}#1#{}", + "{C:inactive}(点击可编辑)", + }, + unlock = { + "使用{C:spectral}锁定", + }, + }, + b_cry_sl_deck = { + name = "蜡封牌组", + text = { + "所有扑克牌均带有{C:dark_edition}#1#{}蜡封", + "卡牌无法更改蜡封", + "{C:inactive}(点击可编辑)", + }, + unlock = { + "使用{C:spectral}台风", + }, + }, + b_cry_st_deck = { + name = "花色牌组", + text = { + "所有扑克牌均为{C:dark_edition}#1#", + "无法更改花色", + "{C:inactive}(点击可编辑)", + }, + unlock = { + "使用{C:spectral}复录", }, }, b_cry_very_fair = { @@ -433,6 +546,10 @@ return { "每回合{C:blue}-2{}手牌,{C:red}-2{}弃牌", "{C:attention}优惠券{}不再出现在商店中", }, + unlock = { + "使用{C:attention}黑色牌组", + "赢一局", + }, }, b_cry_wormhole = { name = "虫洞牌组", @@ -442,6 +559,9 @@ return { "更可能是{C:dark_edition}负片{}", "{C:attention}-2{}小丑牌槽", }, + unlock = { + "拥有一张{C:attention}域外{}小丑", + }, }, }, Blind = { @@ -506,7 +626,7 @@ return { bl_cry_oldflint = { name = "怀旧 燧石", text = { - "包含同花顺的出牌不计分", + "包含同花的出牌不计分", }, }, bl_cry_oldhouse = { @@ -552,6 +672,40 @@ return { "小丑被削弱", }, }, + bl_cry_scorch = { + name = "灼烧", + text = { + "必须出5张牌", + "摧毁打出和弃掉的牌", + }, + }, + bl_cry_greed = { + name = "贪婪", + text = { + "选择时,每拥有$#1#增加#2#盲注要求", + }, + }, + bl_cry_repulsor = { + name = "排斥", + text = { + "重新触发最右侧和最左侧的小丑", + "其他所有小丑不触发", + }, + }, + bl_cry_chromatic = { + name = "彩色", + text = { + "所有奇数次的出牌", + "回合分数会减去手牌得分", + }, + }, + bl_cry_landlord = { + name = "房东", + text = { + "打出手牌时", + "对随机一个小丑添加租用贴纸", + }, + }, bl_cry_pinkbow = { name = "粉红蝴蝶结", text = { @@ -598,6 +752,12 @@ return { "手中的牌", }, }, + bl_cry_trophy = { + name = "柠檬奖杯", + text = { + "倍率不能超过筹码数", + }, + }, bl_cry_vermillion_virus = { name = "朱红病毒", text = { @@ -610,6 +770,13 @@ return { "削弱所有的罕见小丑", }, }, + bl_cry_decision = { + name = "抉择", + text = { + "出牌或弃牌时固定小丑位置", + "回合结束后打开一个诅咒小丑包", + }, + }, }, Code = { c_cry_alttab = { @@ -622,17 +789,24 @@ return { c_cry_class = { name = "://类别", text = { - "将 {C:cry_code}#1#{} 选中的牌", - "转换为 {C:cry_code}指令{} 下的增强", + "将{C:cry_code}#1#{}选中的牌", + "转换为{C:cry_code}指令{}下的增强", "可用指令:{C:cry_code}bonus{},{C:cry_code}mult{},{C:cry_code}wild{},{C:cry_code}glass{}", "{C:cry_code}steel{},{C:cry_code}stone{},{C:cry_code}gold{},{C:cry_code}lucky{},{C:cry_code}echo{},{C:cry_code}light{}", }, }, + c_cry_global = { + name = "://全局", + text = { + "选择一张扑克牌", + "为其添加{C:cry_code}全局{}贴纸", + }, + }, c_cry_commit = { name = "://提交", text = { - "摧毁一张 {C:cry_code}选中的{} 小丑牌,", - "创造一张 {C:cry_code}新的相同 {C:cry_code}稀有度的{} 小丑牌", + "摧毁一张{C:cry_code}选中的{}小丑牌,", + "创造一张{C:cry_code}新的相同{C:cry_code}稀有度的{}小丑牌", }, }, c_cry_crash = { @@ -641,47 +815,49 @@ return { "{C:cry_code,E:1}警告!使用此牌会导致游戏崩溃!", }, }, + c_cry_keygen = { + name = "://密钥", + text = { + "创建一张随机的{C:cry_code}易腐香蕉{}优惠券", + "{C:cry_code}摧毁{}此前以此方式创建的优惠券。", + }, + }, c_cry_ctrl_v = { name = "://CTRL+V", text = { - "复制一张 {C:cry_code}选择的{} 卡牌或消耗牌", + "复制一张{C:cry_code}选择的{}卡牌或消耗牌", }, }, c_cry_delete = { name = "://删除", text = { - "{C:cry_code}永久{} 移除一个", - "{C:cry_code}选中的{} 商店物品", + "{C:cry_code}永久{}移除一个", + "{C:cry_code}选中的{}商店物品", "{C:inactive,s:0.8}本次游戏中该物品不会再出现", }, }, c_cry_divide = { name = "://分割", text = { - "{C:cry_code}减半{} 当前商店中的", + "{C:cry_code}减半{}当前商店中的", "所有标价", }, }, c_cry_exploit = { name = "://利用", text = { - "{C:cry_code}下一{} 手牌", - "", + "{C:cry_code}下一手牌{}", "被计算为", - "", - "{C:cry_code}指令{} 下的牌型", - "", + "{C:cry_code}指令{}下的牌型", "{C:inactive,s:0.8}必须是已发现的手牌类型", - "", "可用指令:{C:cry_code}full house(葫芦){},{C:cry_code}flush(同花){},{C:cry_code}straight flush(同花顺){},{C:cry_code}four of a kind(四条){}", - "", "{C:cry_code}three of a kind(三条){},{C:cry_code}pair(对子){},{C:cry_code}two pair(两对){},{C:cry_code}high(高牌){}", }, }, c_cry_hook = { name = "://钩子", text = { - "选择两张小丑牌,使它们 {C:cry_code}钩住{}", + "选择两张小丑牌,使它们{C:cry_code}钩住{}", "{C:inactive,s:0.8}其中一张被触发时,触发另一张(仅当两个效果的触发时机相同时有效)", }, }, @@ -702,51 +878,72 @@ return { c_cry_malware = { name = "://木马", text = { - "给所有的{C:cry_code}无版本手牌{} ", - "添加 {C:dark_edition}故障{}版本", + "给所有的{C:cry_code}无版本手牌{}", + "添加{C:dark_edition}故障{}版本", + }, + }, + c_cry_nperror = { + name = "://NP错误", + text = { + "将{C:cry_code}上一手打出的牌{}", + "返回你的手牌", }, }, c_cry_merge = { name = "://合并", text = { - "将一张 {C:cry_code}消耗牌", - "与一张 {C:cry_code}手牌{} 合并", + "将一张{C:cry_code}消耗牌", + "与一张{C:cry_code}手牌{}合并", }, }, c_cry_multiply = { name = "://乘法", text = { "选择一张牌,使其所有数值{C:cry_code}翻倍{}", - "直到 {C:cry_code}回合结束{}", + "直到{C:cry_code}回合结束{}", }, }, c_cry_oboe = { - name = "://偏差1", + name = "://偏差", text = { - "打开的下一个 {C:cry_code}补充包{} 有", - "{C:cry_code}#1#{} 张额外卡牌和", - "{C:cry_code}#1#{} 次额外选择", + "打开的下一个{C:cry_code}补充包{}有", + "{C:cry_code}#1#{}张额外卡牌和", + "{C:cry_code}#1#{}次额外选择", "{C:inactive}(当前为 {C:cry_code}+#2#{C:inactive})", }, }, + c_cry_assemble = { + name = "://汇编", + text = { + "为{C:cry_code}选中的手牌牌型{}增加{C:cry_code}倍率{}", + "数值等于拥有的小丑数量", + }, + }, c_cry_patch = { name = "://补丁", text = { - "从当前所有可见的物品中移除", - "贴纸和负面效果", + "从当前所有可见的物品中移除负面效果", + "{C:cry_code}重置{}商店状态", + }, + }, + c_cry_cryupdate = { + name = "://UPDATE", + text = { + "将在未来的{C:cry_code}更新{}中", + "{C:cry_code}确定{}功能", }, }, c_cry_payload = { name = "://载荷", text = { "下一个被击败的盲注", - "给与 {C:cry_code}X#1#{} 利息(乘法叠加)", + "给予{C:cry_code}X#1#{}利息(乘法叠加)", }, }, c_cry_reboot = { name = "://重启", text = { - "补充 {C:blue}手牌{} 和 {C:red}弃牌{} 次数,", + "补充{C:blue}手牌{}和{C:red}弃牌{}次数,", "将{C:cry_code}所有{}牌返回牌堆", "并抽取一组{C:cry_code}新的{}手牌", }, @@ -754,16 +951,23 @@ return { c_cry_revert = { name = "://还原", text = { - "将 {C:cry_code}游戏状态{} 回溯到", + "将{C:cry_code}游戏状态{}回溯到", "{C:cry_code}这一底注的开始时{}", }, }, + c_cry_cryfunction = { + name = "函数://", + text = { + "保存最近使用的3个{C:cry_code}消耗牌{}", + "再次使用此卡时,创建第一个的复制并添加{C:cry_code}函数://{}贴纸", + }, + }, c_cry_rework = { name = "://重制", text = { - "摧毁一张 {C:cry_code}选中的{} 小丑牌,", - "创造该小丑牌的 {C:cry_code}重制标签{},并", - "获得一个 {C:cry_code}升级的{} 版本", + "摧毁一张{C:cry_code}选中的{}小丑牌,", + "创造该小丑牌的{C:cry_code}重制标签{}并", + "获得一个{C:cry_code}升级的{}版本", "{C:inactive,s:0.8}版本通过收藏中的顺序升级{}", "{C:inactive,s:0.8}基础,闪箔,镭射,多彩,负片,故障,马赛克,过曝,{}", "{C:inactive,s:0.8}灰质琉璃,鎏金,模糊,噪声,星界,欢愉,双面,基础{}", @@ -772,40 +976,184 @@ return { c_cry_run = { name = "://运行", text = { - "在 {C:cry_code}盲注", - "期间拜访 {C:cry_code}商店", + "在{C:cry_code}盲注", + "期间拜访{C:cry_code}商店", }, }, c_cry_seed = { name = "://种子", text = { "选择一张小丑牌或手牌", - "使它们获得 {C:cry_code}灌铅{}效果", + "使它们获得{C:cry_code}灌铅{}效果", "概率效果必然被触发", }, }, c_cry_semicolon = { name = ";//", text = { - "结束当前非Boss {C:cry_code}盲注{}", + "结束当前非Boss{C:cry_code}盲注{}", "{C:cry_code}不获得金钱{}", }, }, c_cry_spaghetti = { name = "://意面", text = { - "生成一张 {C:cry_code}故障版本{}的", + "生成一张{C:cry_code}故障版本{}的", "食物小丑牌", }, }, c_cry_variable = { name = "://变量", text = { - "将 {C:cry_code}#1#{} 张选中的牌", - "转换为 {C:cry_code}指令{} 下的牌型", + "将{C:cry_code}#1#{}张选中的牌", + "转换为{C:cry_code}指令{}下的牌型", "可用指令:{C:cry_code}1~13,A,J,Q,K{}", }, }, + c_cry_log = { + name = "://日志", + text = { + "显示以下任一{C:cry_code}读数{}的值:", + "{C:attention}下一个{}底注的{C:attention}Boss盲注{}和{C:attention}优惠券{},", + "接下来商店中的{C:attention}5{}个{C:attention}小丑{},或者", + "接下来{C:attention}10{}张将要被{C:attention}抽取{}的手牌", + "{C:inactive}(如果在盲注中){}", + "{C:inactive,S:0.7}(译者注:在0.5.10~dev3版本中,使用第一个选项会导致attempt to index a nil value报错)", + "{C:inactive,S:0.7}(第二个选项看不到小丑,第三个选项看不到花色)", + "{C:inactive,S:0.7}(但是译者不能完全确定,可以尝试一下)", + }, + }, + c_cry_quantify = { + name = "://量化", + text = { + "将{C:attention}#1#{}张选择的", + "{C:attention}手牌{}或{C:attention}补充包{}", + "放到{C:attention}小丑槽{}槽位中", + }, + }, + c_cry_declare = { + name = "://声明", + text = { + "你{C:attention}现在{}选择的手牌", + "变成一张包含{C:attention}#1#{}的{C:cry_code}新的{}牌型", + "你最多可以创造{C:attention}3{}{C:inactive}[#2#]{}种牌型", + }, + }, + }, + ["Content Set"] = { + set_cry_blind = { + name = "盲注集合", + text = { + "包含Cryptid新增的{C:attention}Boss盲注{}", + }, + }, + set_cry_code = { + name = "代码牌集合", + text = { + "包含{C:cry_code}代码牌{}及", + "相关内容", + }, + }, + set_cry_cursed = { + name = "诅咒小丑集合", + text = { + "带有{X:cry_cursed,C:white}诅咒{}稀有度的有害小丑", + }, + }, + set_cry_deck = { + name = "牌组集合", + text = { + "Cryptid新增的{C:attention}牌组{}", + }, + }, + set_cry_epic = { + name = "史诗小丑集合", + text = { + "带有{C:cry_epic}史诗{}稀有度的小丑", + "{C:inactive,s:0.8}(介于稀有和传奇之间)", + }, + }, + set_cry_exotic = { + name = "域外小丑集合", + text = { + "带有{C:cry_exotic}域外{}稀有度的强力小丑", + }, + }, + set_cry_m = { + name = "M小丑集合", + text = { + "与字母{C:attention}M{}相关的小丑", + "以及{C:attention}开心小丑", + }, + }, + set_cry_meme = { + name = "梗小丑集合", + text = { + "包含多类梗相关内容", + }, + }, + set_cry_misc = { + name = "杂项集合", + text = { + "不适合其他{C:cry_ascendant}主题集合{}的内容", + }, + }, + set_cry_misc_joker = { + name = "杂项小丑集合", + text = { + "不适合其他{C:cry_ascendant}主题集合{}的{C:attention}小丑{}", + }, + }, + set_cry_planet = { + name = "星球牌集合", + text = { + "Cryptid新增的{C:planet}星球{}牌", + }, + }, + set_cry_poker_hand_stuff = { + name = "扑克手牌扩展", + text = { + "新增5种{C:attention}扑克手牌{}", + "并启用{C:attention}晋升手牌", + }, + }, + set_cry_spectral = { + name = "幻灵牌集合", + text = { + "Cryptid新增的{C:spectral}幻灵{}牌", + }, + }, + set_cry_spooky = { + name = "万圣节更新内容", + text = { + "万圣节更新内容", + "包括{C:cry_candy}糖果{}小丑", + }, + }, + set_cry_tag = { + name = "标签集合", + text = { + "Cryptid新增的{C:attention}标签{}", + }, + }, + set_cry_tier3 = { + name = "三阶优惠券", + text = { + "优惠券的额外{C:attention}等级{}", + }, + }, + set_cry_timer = { + name = "计时机制", + text = { + "带有{C:attention}时间相关{}效果的物品及机制", + }, + }, + set_cry_voucher = { + name = "杂项优惠券", + text = { + "Cryptid新增的1阶和2阶{C:attention}优惠券{}", + }, + }, }, Edition = { e_cry_astral = { @@ -825,7 +1173,7 @@ return { e_cry_double_sided = { name = "双面", text = { - "此卡可以被{C:attention}翻转{},", + "此卡可以被{C:attention}翻转{}", "以展示另一张不同的卡牌", }, }, @@ -833,7 +1181,7 @@ return { label = "易碎", name = "灰质琉璃", text = { - "{C:white,X:mult} X#3# {} 倍率", + "{C:white,X:mult} X#3# {}倍率", "触发时{C:green}#1# / #2#{} 的概率不会被摧毁", }, }, @@ -862,13 +1210,13 @@ return { e_cry_mosaic = { name = "马赛克", text = { - "{X:chips,C:white} X#1# {} 筹码", + "{X:chips,C:white} X#1# {}筹码", }, }, e_cry_noisy = { name = "噪声", text = { - " ", + "???", }, }, e_cry_oversat = { @@ -885,7 +1233,7 @@ return { text = { "当计分时", "{C:green}#2# / #3#{} 几率", - "{C:attention}重新触发{} #1# 次", + "{C:attention}重新触发{}#1#次", }, }, m_cry_light = { @@ -897,8 +1245,44 @@ return { "{C:inactive}(当前 {X:mult,C:white}X#2#{C:inactive} 倍率)", }, }, + m_cry_abstract = { + name = "抽象牌", + text = { + "{X:dark_edition,C:white}^#1#{}倍率", + "算作{C:attention}自身{}的点数和花色", + "在{C:attention}回合结束{}或{C:attention}出牌{}时", + "有{C:green}#4#/#5#{}概率{C:red,E:2}摧毁{}此牌", + }, + }, }, Joker = { + j_cry_test_modest = { + name = "测试小丑", + text = { + "{C:chips}+#1#{}筹码", + }, + }, + j_cry_test_mainline = { + name = "测试小丑", + text = { + "{C:chips}+#1#{}筹码", + "在{C:attention}盲注{}开始时获得{C:money}+$44{}", + }, + }, + j_cry_test_madness = { + name = "测试小丑", + text = { + "{C:chips}+#1#{}筹码", + "在{C:attention}盲注{}开始时获得{C:money}+$44444{}", + }, + }, + j_cry_test_cryptid_in_2025 = { + name = "测试小丑", + text = { + "{C:chips}+#1#{}筹码", + "在{C:attention}盲注{}开始时获得{C:money}+$44444{}", + }, + }, j_cry_CodeJoker = { name = "代码小丑", text = { @@ -915,6 +1299,14 @@ return { "{C:inactive,s:0.8}(增长为 +1, +2, +3)", }, }, + ["j_cry_Double Scale_modest"] = { + name = "双重天平", + text = { + "成长性{C:attention}小丑{}", + "以{C:attention}两倍{}速度增长", + '{C:inactive,s:0.8}"这叫双重天平,不是平方天平!"', + }, + }, j_cry_M = { name = "M", text = { @@ -923,12 +1315,12 @@ return { "{C:attention}开心小丑{}", }, }, - j_cry_Megg = { + j_cry_megg = { name = "M蛋", text = { "出售这张小丑来创造", - "{C:attention}#2#{} 张开心小丑", - "在回合结束时增加 {C:attention}#1#{}", + "{C:attention}#2#{}张开心小丑", + "在回合结束时增加{C:attention}#1#{}", }, }, j_cry_Scalae = { @@ -953,10 +1345,18 @@ return { name = "怀旧 Googol 游戏牌", text = { "出售此牌以复制", - "{C:attention}2{} 张最左侧的小丑", + "{C:attention}2{}张最左侧的小丑", "{C:inactive,s:0.8}不会复制怀旧 Googol 游戏牌{}", }, }, + j_cry_altgoogol_balanced = { + name = "怀旧 Googol 游戏牌", + text = { + "出售此卡以复制最左侧小丑{C:attention}#1#{}次", + "{C:inactive,s:0.8}不复制怀旧谷歌牌{}", + "{C:inactive}(必须有空间)", + }, + }, j_cry_antennastoheaven = { name = "7-4 如指向天堂的天线", text = { @@ -969,7 +1369,7 @@ return { j_cry_apjoker = { name = "AP 弹小丑", text = { - "对boss盲注提供{X:mult,C:white} X#1# {} 倍率", + "对boss盲注提供{X:mult,C:white} X#1# {}倍率", }, }, j_cry_arsonist = { @@ -979,23 +1379,39 @@ return { j_cry_astral_bottle = { name = "瓶中星球", text = { - "当出售时, 应用 {C:dark_edition}星界{}", - "和{C:attention}易腐{} 到一张", - "随机的 {C:attention}小丑牌{}", + "当出售时, 应用{C:dark_edition}星界{}", + "和{C:attention}易腐{}到一张", + "随机的{C:attention}小丑牌{}", + }, + }, + j_cry_astral_bottle_mainline = { + name = "瓶中星球", + text = { + "当出售时, 应用{C:dark_edition}星界{}", + "和{C:attention}易腐{}到一张", + "随机的{C:attention}小丑牌{}", + }, + }, + j_cry_astral_bottle_madness = { + name = "瓶中星球", + text = { + "当出售时, 应用{C:dark_edition}星界{}", + "和{C:attention}易腐{}到一张", + "到一张随机的{C:attention}小丑牌{}", }, }, j_cry_big_cube = { name = "大大方块", text = { - "{X:chips,C:white} X#1# {} 筹码", + "{X:chips,C:white} X#1# {}筹码", }, }, j_cry_biggestm = { name = "超大M", text = { - "{X:mult,C:white} X#1# {} 倍率直到本轮结束", - "如果 {C:attention}打出牌型{}", - "是一个 {C:attention}#2#{}", + "{X:mult,C:white} X#1# {}倍率直到本轮结束", + "如果{C:attention}打出牌型{}", + "是一个{C:attention}#2#{}", "{C:inactive}(当前 {C:attention}#3#{}{C:inactive}){}", "{C:inactive,s:0.8}不是胖,只是骨架大。", }, @@ -1004,7 +1420,7 @@ return { name = "黑名单", text = { "当手牌中有或者打出{C:attention}#1#{}时", - "{C:chips}筹码{} 和 {C:mult}倍率{} 变为0", + "{C:chips}筹码{}和{C:mult}倍率{}变为0", "如果牌组中没有{C:attention}#1#{},自毁", "{C:inactive,s:0.8}不会改变牌型等级", }, @@ -1013,7 +1429,7 @@ return { name = "Blender", text = { "使用{C:cry_code}代码牌{}时", - "获得一张 {C:attention}随机{}消耗牌", + "获得一张{C:attention}随机{}消耗牌", }, }, j_cry_blurred = { @@ -1034,7 +1450,7 @@ return { j_cry_bonkers = { name = "癫狂小丑", text = { - "如果出的牌中包含", + "如果打出的牌中包含", "一个 {C:attention}#2#", "{C:red}+#1#{} 倍率", }, @@ -1051,22 +1467,26 @@ return { j_cry_booster = { name = "补充包小丑", text = { - "商店{C:attention}+#1#{} 补充包槽位", + "商店{C:attention}+#1#{}补充包槽位", }, }, j_cry_boredom = { name = "无聊小丑", text = { "{C:green}#1# / #2#{} 概率", - "率重新触发{C:attention}所有小丑牌{}和{C:attention}计分牌{}", + "重新触发{C:attention}所有小丑牌{}和{C:attention}计分牌{}", "{C:inactive,s:0.8}无法触发{C:attention}无聊小丑{}{}", }, + unlock = { + "在标题界面", + "挂机{C:attention}10分钟", + }, }, j_cry_brittle = { name = "脆脆糖", text = { - "之后 {C:attention}#1#{} 次出牌,", - "随机添加 {C:attention}石头{}, {C:attention}黄金{}, 或 {C:attention}钢铁{}增强到最右边的记分牌", + "之后{C:attention}#1#{}次出牌,", + "随机添加{C:attention}石头{},{C:attention}黄金{},或{C:attention}钢铁{}增强到最右边的记分牌", }, }, j_cry_bubblem = { @@ -1081,42 +1501,49 @@ return { name = "巴士司机", text = { "{C:green}#1# / #3#{} 概率 {C:mult}+#2#{} 倍率", - "或{C:green}1 /4{} 概率 {C:mult}-#2#{} 倍率", + "或{C:green}#4# / #3#{} 概率 {C:mult}-#2#{} 倍率", + }, + }, + j_cry_buttercup = { + name = "毛茛", + text = { + "可储存{C:attention}#1#{}个选中的商店物品", + "出售时:将储存的物品添加到下一个商店", }, }, j_cry_candy_basket = { name = "糖果篮子", text = { - "卖掉这张牌获得 {C:attention}#1#{} {C:cry_candy}张糖果", - " 每击败 {C:attention}2{} 个盲注{C:attention}+#2#{} {C:cry_candy}糖果{}", - "击败{C:attention}Boss 盲注{}{C:attention}+#3#{} {C:cry_candy}糖果{}", + "卖掉这张牌获得{C:attention}#1#{}{C:cry_candy}张糖果", + "每击败{C:attention}2{}个盲注{C:attention}+#2#{}{C:cry_candy}糖果{}", + "击败{C:attention}Boss 盲注{}{C:attention}+#3#{}{C:cry_candy}糖果{}", }, }, j_cry_candy_buttons = { name = "纽扣糖", text = { - "之后的 {C:attention}#1#{} 次重掷", - "只花 {C:money}$1{}", + "之后的{C:attention}#1#{}次重掷", + "只花{C:money}$1{}", }, }, j_cry_candy_cane = { name = "拐杖糖", text = { - "之后 {C:attention}#1#{} 回合", - " 打出的牌被{C:attention}重新触发{}时获得{C:money}$#2#", + "之后{C:attention}#1#{}回合", + "打出的牌被{C:attention}重新触发{}时获得{C:money}$#2#", }, }, j_cry_candy_dagger = { name = "糖果匕首", text = { - "选择 {C:attention}盲注{} 后", - "摧毁它左边的小丑,创造一张{C:cry_candy}糖果{}小丑", + "选择{C:attention}盲注{}后", + "摧毁它右边的小丑,创造一张{C:cry_candy}糖果{}小丑", }, }, j_cry_candy_sticks = { name = "棒棒糖", text = { - "直到你打出 {C:attention}#1#{} 手牌", + "直到你打出{C:attention}#1#{}手牌", "下个Boss盲注的效果失效", }, }, @@ -1126,13 +1553,38 @@ return { "右侧每有一张{C:blue}稀有度高于普通{}的小丑", "所有左侧的小丑{C:attention}重新触发{}{C:attention}一次{}", }, + unlock = { + "在一手牌中", + "重新触发{C:attention}小丑{}", + "{C:attention}114次", + }, + }, + j_cry_canvas_balanced = { + name = "画布", + text = { + "右侧每有一张{C:blue}稀有度高于普通{}的小丑", + "所有左侧的小丑{C:attention}重新触发{}{C:attention}一次{}", + "{C:inactive}(最多2次重新触发)", + }, + unlock = { + "在一手牌中", + "重新触发{C:attention}小丑{}", + "{C:attention}114次", + }, }, j_cry_caramel = { name = "焦糖", text = { "每打出一张牌时", - "在得分时获得 {X:mult,C:white}X#1#{} 倍率", - "持续 {C:attention}#2#{} 回合", + "在得分时获得{X:mult,C:white}X#1#{}倍率", + "持续{C:attention}#2#{}回合", + }, + }, + j_cry_cat_owl = { + name = "猫头鹰", + text = { + "{C:attention}幸运牌{}同时算作{C:attention}回响牌", + "{C:attention}回响牌{}同时算作{C:attention}幸运牌", }, }, j_cry_chad = { @@ -1146,7 +1598,7 @@ return { name = "辣椒", text = { "回合结束时", - "这个小丑获得{X:mult,C:white} X#2# {} 倍率", + "这个小丑获得{X:mult,C:white} X#2# {}倍率", "{C:attention}#3#{}回合后自毁", "(当前{X:mult,C:white} X#1# {C:inactive}倍率)", }, @@ -1155,7 +1607,7 @@ return { name = "巧克力十面骰", text = { "击败Boss盲注后", - "投掷一个{C:green}d10{} 的判定", + "投掷一个{C:green}d10{}的判定", "去开始一个{C:cry_ascendant,E:1}事件{}", "{C:inactive}(当前: #1#)", }, @@ -1164,7 +1616,7 @@ return { name = "环形转轮", text = { "{X:dark_edition,C:white}^#1#{} 筹码, {X:dark_edition,C:white}^#1#{} 倍率", - "如果{C:attention}正好{}剩余 #2#", + "如果{C:attention}正好{}剩余#2#", "手牌", }, }, @@ -1176,20 +1628,72 @@ return { "{C:legendary}传奇{}小丑每个提供 {X:mult,C:white} X#3# {} 倍率", "{C:cry_exotic}域外{}小丑每个提供 {X:mult,C:white} X#4# {} 倍率", }, + unlock = { + "在{C:attention}底注9{}前获得", + "{C:red}稀有{}、{C:cry_epic}史诗{}和{C:legendary}传奇{}小丑", + }, }, j_cry_clash = { name = "冲突", text = { "如果打出的手牌包含", - "一个 {C:attention}#2#", - "{X:mult,C:white} X#1# {} 倍率", + "一个{C:attention}#2#", + "{X:mult,C:white} X#1# {}倍率", + }, + unlock = { + "赢得一局游戏", + "且最终打出的牌型为", + "{E:1,C:attention}至尊对子", + }, + }, + j_cry_the = { + name = " ", + text = { + "如果打出的手牌是{C:attention}#2#", + "{X:mult,C:white} X#1# {}倍率", + }, + unlock = { + "赢得一局游戏", + "且最终打出的牌型为", + "{E:1,C:attention}None", }, }, j_cry_clicked_cookie = { name = "被点击的饼干", text = { "{C:chips}+#1#{} 筹码", - "每当该小丑被{C:attention}点击{}时,{C:chips}-#2#{} 筹码", + "每次鼠标{C:attention}点击{}后,{C:chips}-#2#{} 筹码", + }, + }, + j_cry_clockwork = { + name = "发条小丑", + text = { + "每打出{C:attention}#9#{}{C:inactive}(#1#){}手牌重新触发持有的钢铁牌", + "每打出{C:attention}#10#{}{C:inactive}(#2#){}手牌获得{X:mult,C:white}X#6#{}(当前X#5#)倍率", + "每打出{C:attention}#11#{}{C:inactive}(#3#){}手牌将第一张打出的牌变为钢铁牌", + "每打出{C:attention}#12#{}{C:inactive}(#4#){}手牌使持有的钢铁牌提供+{X:mult,C:white}X#8#{}(当前X#7#)倍率", + }, + }, + j_cry_CodeJoker = { + name = "代码小丑", + text = { + "选择{C:attention}盲注{}时", + "创建一张{C:dark_edition}负片{}{C:cry_code}代码牌{}", + }, + unlock = { + "发现所有", + "{C:cry_code}代码牌", + }, + }, + j_cry_CodeJoker_modest = { + name = "代码小丑", + text = { + "选择{C:attention}Boss盲注{}时", + "创建一张{C:dark_edition}负片{}{C:cry_code}代码牌{}", + }, + unlock = { + "发现所有", + "{C:cry_code}代码牌", }, }, j_cry_coin = { @@ -1210,13 +1714,30 @@ return { text = { "使用{C:cry_code}代码牌{}时", "{C:green}#1# / #2#{}概率将其复制回消耗牌槽", + "{C:red}每回合最多一次{}", + "{C:inactive}(必须有空间)", + }, + }, + j_cry_copypaste_modest = { + name = "复制/粘贴", + text = { + "复制拉取的{C:cry_code}代码牌{}", + "{C:inactive}(必须有空间)", + }, + }, + j_cry_copypaste_madness = { + name = "复制/粘贴", + text = { + "使用{C:cry_code}代码牌{}时", + "{C:green}#1# / #2#{}概率将其复制回消耗牌槽", + "{C:inactive}(必须有空间)", }, }, j_cry_cotton_candy = { name = "棉花糖", text = { "出售后相邻的", - "{C:attention}小丑{} 变为 {C:dark_edition}负片{}", + "{C:attention}小丑{}变为{C:dark_edition}负片{}", }, }, j_cry_crustulum = { @@ -1249,6 +1770,10 @@ return { "{C:dark_edition,E:1}你无法逃脱...{}", "{C:inactive}(必须有槽位){}", }, + unlock = { + "获得一个{C:purple}永恒{}的", + "{C:attention}方尖石塔", + }, }, j_cry_cursor = { name = "光标", @@ -1261,23 +1786,37 @@ return { j_cry_cut = { name = "剪切", text = { - "在 {C:attention}离开商店{}时", - "这张小丑随机摧毁一张 {C:cry_code}代码牌{}", - "并且增加 {X:mult,C:white} X#1# {} 倍率", + "在{C:attention}离开商店{}时", + "这张小丑随机摧毁一张{C:cry_code}代码牌{}", + "并且增加 {X:mult,C:white} X#1# {}倍率", "{C:inactive}(当前已提供{X:mult,C:white} X#2# {C:inactive} 倍率)", }, }, j_cry_delirious = { name = "错乱小丑", text = { - "如果出的牌中包含 {C:attention}#2#", + "如果打出的牌中包含{C:attention}#2#", "{C:red}+#1#{} 倍率", }, }, + j_cry_demicolon = { + name = "分号", + text = { + "{C:attention}强制触发{}右侧的小丑", + }, + }, + j_cry_digitalhallucinations = { + name = "数字幻觉", + text = { + "打开{C:attention}补充包{}时", + "有{C:green}#1#/#2#{}概率创建一张", + "与其{C:attention}类型{}对应的随机{C:dark_edition}负片{}牌", + }, + }, j_cry_discreet = { name = "低调小丑", text = { - "如果出的牌中包含 {C:attention}#2#", + "如果打出的牌中包含{C:attention}#2#", "{C:chips}+#1#{} 筹码", }, }, @@ -1285,38 +1824,49 @@ return { name = "涂鸦 M", text = { "当{C:attention}选择盲注{}时", - "创造2个随机{C:dark_edition}负片{} {C:attention}消耗牌{}", + "创造2个随机{C:dark_edition}负片{}{C:attention}消耗牌{}", "每有1个{C:attention}开心小丑{}创造1个额外的{C:attention}消耗牌", }, }, j_cry_dropshot = { name = "一杆入洞", text = { - "出牌时,每有一张 {C:attention}不计分{}的 {V:1}#2#{}牌", - "这张小丑牌增加 {X:mult,C:white} X#1# {} 倍率", + "出牌时,每有一张{C:attention}不计分{}的{V:1}#2#{}牌", + "这张小丑牌增加{X:mult,C:white} X#1# {}倍率", "花色每回合改变", "{C:inactive}(当前 {X:mult,C:white} X#3# {C:inactive} 倍率)", }, + unlock = { + "打出一手{C:attention}高牌{}", + "其中包含{C:attention}4张{}", + "同花色的牌", + }, }, j_cry_dubious = { name = "可疑小丑", text = { - "如果出的牌中包含 {C:attention}#2#", + "如果打出的牌中包含{C:attention}#2#", "{C:chips}+#1#{} 筹码", }, }, j_cry_duos = { name = "双重奏", text = { - "{X:mult,C:white} X#1# {} 倍率如果出牌", + "{X:mult,C:white} X#1# {}倍率如果出牌", "手牌包含{C:attention}#2#", }, + unlock = { + "赢一局", + "且不打出", + "{C:attention}两对{}", + }, }, j_cry_duplicare = { name = "复制", text = { - "每张{C:attention}小丑牌{}给予", - "{X:dark_edition,C:white}^#1#{} 倍率", + "当一张{C:attention}小丑{}或手牌计分时", + "这个小丑获得{X:mult,C:white} X#2# {}倍率", + "{C:inactive}(当前{X:mult,C:white} X#1# {C:inactive}倍率)", }, }, j_cry_effarcire = { @@ -1324,7 +1874,7 @@ return { text = { "选择{C:attention}盲注{}时", "将{C:green}整副牌{}抽入手牌", - "{C:inactive,s:0.8}如果你在一倍速时无法掌控我,", + "{C:inactive,s:0.8}如果你在一倍速时无法掌控我", "{C:inactive,s:0.8}你就不配在二倍速时拥有我", }, }, @@ -1341,7 +1891,7 @@ return { name = "王牌均衡", text = { "小丑牌以{C:attention}收藏{}中的顺序出现", - "出牌时创造{C:attention}#1#{} {C:dark_edition}负片{}小丑", + "出牌时创造{C:attention}#1#{}张{C:dark_edition}负片{}小丑", "不会出现{C:cry_exotic,s:0.8}域外{C:inactive,s:0.8}或更稀有的小丑", "{s:0.8}最后生成的小丑: {C:attention,s:0.8}#2#", }, @@ -1349,29 +1899,37 @@ return { j_cry_error = { name = "{C:dark_edition}E{}{C:red}错误{}{C:dark_edition}O{}{C:red}R{}", text = { - "nan", + "", }, }, j_cry_eternalflame = { name = "永恒之火", text = { - "每出售一张牌,", - "这张小丑获得{X:mult,C:white} X#1# {} 倍率", + "每{C:attention}出售{}一张售价至少为{C:money}$3{}的牌", + "这张小丑获得{X:mult,C:white} X#1# {}倍率", + "(当前{X:mult,C:white} X#2# {C:inactive}倍率)", + }, + }, + j_cry_eternalflame2 = { + name = "永恒之火", + text = { + "每{C:attention}出售{}一张牌", + "这张小丑获得{X:mult,C:white} X#1# {}倍率", "(当前{X:mult,C:white} X#2# {C:inactive}倍率)", }, }, j_cry_exoplanet = { name = "系外行星", text = { - "每张{C:dark_edition}镭射{}卡提供{C:mult}+#1#{} 倍率", + "每张{C:dark_edition}镭射{}卡提供{C:mult}+#1#{}倍率", }, }, j_cry_exponentia = { name = "指数", text = { - "触发 {X:red,C:white} X 倍率 {} 时", - "这张小丑获得 {X:dark_edition,C:white} ^#1# {} 倍率", - "{C:inactive}(当前 {X:dark_edition,C:white} ^#2# {C:inactive} 倍率)", + "触发{X:red,C:white}X倍率{}时", + "这张小丑获得{X:dark_edition,C:white} ^#1# {}倍率", + "{C:inactive}(当前 {X:dark_edition,C:white} ^#2# {C:inactive}倍率)", }, }, j_cry_exposed = { @@ -1379,31 +1937,68 @@ return { text = { "重新触发{C:attention}非人头牌{} ", "额外{C:attention}#1#{}次", - "所有 {C:attention}人头牌{} 都被削弱", + "所有{C:attention}人头牌{}都被削弱", + }, + }, + j_cry_eyeofhagane = { + name = "叶钢之眼", + text = { + "所有打出的{C:attention}人头牌{}", + "计分时变为{C:attention}钢铁{}牌", + }, + }, + j_cry_highfive = { + name = "击掌", + text = { + "如果最高{C:attention}计分点数{}是{C:attention}5{}", + "将所有计分牌转换为{C:attention}5{}", + "{s:0.8,C:inactive}A算作1", }, }, j_cry_facile = { name = "简易", text = { - "{C:attention}#2#{} 张及以下的牌得分", - "{X:dark_edition,C:white}^#1#{} 倍率", + "如果打出的牌被计分{C:attention}#2#{}次及以下", + "{X:dark_edition,C:white}^#1#{}倍率", "(重复触发算作多张)", }, }, + j_cry_fading_joker = { + name = "褪色小丑", + text = { + "当一张{C:attention}易腐{}牌被削弱时", + "此小丑获得{X:mult,C:white}X#1#{}倍率", + "{C:inactive}(当前{} {X:mult,C:white}X#2#{} {C:inactive}倍率){}", + }, + }, + j_cry_familiar_currency = { + name = "熟悉货币", + text = { + "回合结束时创建一张{C:attention}梗小丑{}", + "消耗{C:money}$#1#{}(如果可能)", + "{C:inactive}(必须有空间)", + }, + }, j_cry_filler = { name = "填充物", text = { "", - "如果出的牌中包含{C:attention}#2# 提供{X:mult,C:white} X#1# {} 倍率", + "如果打出的牌中包含{C:attention}#2#", + "提供{X:mult,C:white} X#1# {}倍率", + }, + unlock = { + "赢一局", + "且不打出", + "{C:attention}高牌{}", }, }, j_cry_fleshpanopticon = { name = "血肉监牢", text = { - "{C:attention}Boss 盲注{} 得分需求 {C:red}X#1#{}", - "当 {C:attention}Boss 盲注{} 被击败后,", + "{C:attention}Boss 盲注{}得分需求{C:red}X#1#{}", + "当{C:attention}Boss 盲注{}被击败后,", "{C:red}自毁{}, 然后创建", - "一张 {C:dark_edition}负片{} {C:spectral}真理之门{} ", + "一张{C:dark_edition}负片{}{C:spectral}真理之门{} ", "{C:inactive,s:0.8}此等监牢……囚禁于吾?", }, }, @@ -1419,7 +2014,7 @@ return { name = "M当劳", text = { "{C:mult}+#1#{} 倍率", - "在 {C:attention}#2#{} 回合中{C:red,E:2}自毁{}", + "在 {C:attention}#2#{}回合中{C:red,E:2}自毁{}", "当{C:attention}开心小丑{}被{C:attention}出售{}时增加{C:attention}#3#{}回合", "{C:inactive,s:0.8}2 双层芝士,2 麦香鸡{}", "{C:inactive,s:0.8}1 大薯条,20 大蛋糕{}", @@ -1429,30 +2024,41 @@ return { name = "鲁莽小丑", text = { "如果打出的手牌包含", - "一个 {C:attention}#2#", - "{C:red}+#1#{} 倍率", + "一个{C:attention}#2#", + "{C:red}+#1#{}倍率", + }, + }, + j_cry_undefined = { + name = "未定义小丑", + text = { + "{C:red}+#1#{}倍率", + "如果出牌是{C:attention}#2#", }, }, j_cry_formidiulosus = { name = "驱邪", text = { - "获得 {X:cry_cursed,C:white}诅咒{} 小丑时,将其摧毁", - "离开商店时创造 {C:attention}#1#{}张 {C:dark_edition}负片{C:cry_candy}糖果{} ", - "每有一张 {C:cry_candy}糖果{}小丑,{X:dark_edition,C:white}+^#2#{} 倍率", + "获得{X:cry_cursed,C:white}诅咒{}小丑时,将其摧毁", + "离开商店时创造{C:attention}#1#{}张{C:dark_edition}负片{C:cry_candy}糖果{} ", + "每有一张{C:cry_candy}糖果{}小丑,{X:dark_edition,C:white}+^#2#{} 倍率", "{C:inactive}(当前 {X:dark_edition,C:white}^#3#{C:inactive} 倍率)", }, }, j_cry_foxy = { name = "奸猾小丑", text = { - "如果出的牌中包含 {C:attention}#2#", - "{C:chips}+#1#{} 筹码", + "如果打出的牌中包含{C:attention}#2#", + "{C:chips}+#1#{}筹码", }, }, j_cry_fractal = { name = "分形手指", text = { - "{C:attention}+#1#{} 手牌选择上限", + "{C:attention}+#1#{}手牌选择上限", + }, + unlock = { + "打出一手{C:attention}同花顺{}", + "但该{C:attention}顺子{}不是{C:attention}同花", }, }, j_cry_fspinner = { @@ -1467,15 +2073,15 @@ return { name = "烂逼小丑", text = { "如果打出的手牌包含", - "一个 {C:attention}#2#", + "一个{C:attention}#2#", "{C:red}+#1#{} 倍率", }, }, j_cry_gardenfork = { name = "7-1 小径分岔的花园", text = { - "打出的{C:attention} A{} 和{C:attention} 7{}", - "会在被计分时+{C:money}$#1#{} 块钱", + "打出的{C:attention}A{}和{C:attention}7{}", + "会在被计分时+{C:money}$#1#{}块钱", "{C:inactive,s:0.8}(一本书名,同时也捏他ultrakill关卡名)", }, }, @@ -1493,14 +2099,14 @@ return { text = { "回合结束后", "{C:green}#1# / #2#{} 几率 ", - "{C:attention}作祟{} 一张随机的 {C:attention}小丑", - "{C:green}#1# / #3#{} 几率{E:2,C:red}自毁 {}", + "{C:attention}作祟{}一张随机的{C:attention}小丑", + "{C:green}#1# / #3#{} 几率{E:2,C:red}自毁{}", }, }, j_cry_giggly = { name = "荒谬小丑", text = { - "如果出的牌中包含 {C:attention}#2#", + "如果打出的牌中包含{C:attention}#2#", "{C:red}+#1#{} 倍率", }, }, @@ -1516,7 +2122,11 @@ return { name = "Googol 游戏牌", text = { "{C:green}#1# / #2#{} 概率提供", - "{X:red,C:white} X#3# {} 倍率", + "{X:red,C:white} X#3# {}倍率", + }, + unlock = { + "在一次出牌中", + "获得至少{C:attention}1.0e100{}筹码", }, }, j_cry_happy = { @@ -1532,7 +2142,7 @@ return { name = "快乐之家", text = { "{X:dark_edition,C:white}^#1#{} 倍率当", - " {C:attention}114{} 次出牌{}后", + " {C:attention}114{}次出牌{}后", "{C:inactive}(当前 #2#/114){}", "{C:inactive,s:0.8}没有地方能比得上家!{}", }, @@ -1540,10 +2150,15 @@ return { j_cry_home = { name = "家园", text = { - "{X:mult,C:white} X#1# {} 倍率", + "{X:mult,C:white} X#1# {}倍率", "如果打出的手牌包含", "一个{C:attention}#2#", }, + unlock = { + "赢一局", + "且不打出", + "{C:attention}葫芦{}", + }, }, j_cry_hunger = { name = "消耗之牌", @@ -1552,17 +2167,24 @@ return { "获得{C:money}$#1#{}", }, }, + j_cry_huntingseason = { + name = "狩猎季节", + text = { + "如果打出的手牌正好有{C:attention}3张{}牌", + "计分后{C:red}摧毁{}中间的牌", + }, + }, j_cry_iterum = { name = "再触", text = { "已经出过的牌重新触发{C:attention}#2#{}次", - "并且每张牌提供{X:mult,C:white} X#1# {} 倍率", + "并且每张牌提供{X:mult,C:white} X#1# {}倍率", }, }, j_cry_jawbreaker = { name = "硬糖", text = { - "击败 {C:attention}Boss 盲注后{} ,", + "击败{C:attention}Boss 盲注后{},", "让所有小丑数值变为{C:attention}两倍{} ", "{E:2,C:red}自毁{}", }, @@ -1572,9 +2194,13 @@ return { text = { "{C:attention}连续{}打出", "{C:attention}使用次数最多的牌型{}时", - "获得 {X:mult,C:white} X#1# {} 倍率", + "获得{X:mult,C:white} X#1# {}倍率", "{C:inactive}(当前{X:mult,C:white} X#2# {C:inactive}倍率)", }, + unlock = { + "仅使用{C:attention}单一类型的{}", + "{C:attention}扑克手牌{}赢得一局", + }, }, j_cry_jollysus = { name = "欢愉小丑…吗?", @@ -1585,19 +2211,33 @@ return { "{C:inactive}#1#{}", }, }, + j_cry_jtron = { + name = "吉姆波创9000", + text = { + "每个默认{C:attention}小丑{}使此小丑获得{X:dark_edition,C:white}^#1#{}倍率", + "{C:inactive}(当前{X:dark_edition,C:white}^#2#{}倍率)", + }, + }, j_cry_kidnap = { name = "绑架", text = { - "{C:red}Outdated Description{}", "每回合结尾获得{C:money}$#2#{}", - "每卖掉一张{C:attention}倍率{}或者{C:attention}筹码{}小丑时", + "每卖掉一张不同的{C:attention}倍率{}或者{C:attention}筹码{}小丑时", "增加{C:money}$#1#{}", }, }, + j_cry_kittyprinter = { + name = "猫咪打印机", + text = { + "{X:mult,C:white}X#1#{}倍率", + "所有{C:attention}跳过{}标签", + "变为{C:attention}猫咪标签{}", + }, + }, j_cry_kooky = { name = "怪诞小丑", text = { - "如果出的牌中包含 {C:attention}#2#", + "如果打出的牌中包含{C:attention}#2#", "{C:red}+#1#{} 倍率", }, }, @@ -1615,11 +2255,26 @@ return { "当击败{C:attention}Boss 盲注{}时", "使一张随机{C:attention}小丑{}获得{C:dark_edition}多彩{}版本", }, + unlock = { + "击败一个{C:attention}Boss盲注{}", + "同时拥有{C:attention}5{}张或更多", + "{C:attention}特殊版本卡牌{}或", + "{C:attention}小丑牌{}", + }, + }, + j_cry_lebaron_james = { + name = "勒布朗·詹姆斯", + text = { + "打出并计分的{C:attention}K{}会使本回合", + "手牌上限增加{C:attention}+#1#{}", + "并触发{C:attention}留在手牌中{}的效果", + "{C:inactive}(当前为{}{C:attention}+#2#{}{C:inactive})", + }, }, j_cry_lightupthenight = { name = "7-2 掌灯破暗", text = { - "每张 {C:attention}7 {}或 {C:attention}2{},", + "每张 {C:attention}7{}或{C:attention}2{}", "在计分时提供{X:mult,C:white}X#1#{}倍率", "{C:inactive,s:0.8}(捏他ultrakill关卡名)", }, @@ -1629,7 +2284,7 @@ return { text = { "在回合结束时", "给未来的", - "这张小丑牌 {X:mult,C:white}X#1#{} 倍率", + "这张小丑牌{X:mult,C:white}X#1# {}倍率", "{C:inactive}(当前 {X:mult,C:white}X#2#{C:inactive} 倍率){}", }, }, @@ -1646,22 +2301,22 @@ return { name = "幸运小丑", text = { "{C:attention}幸运牌{}成功触发时", - "+ {C:money}$#1#{}", + "+{C:money}$#1#{}", }, }, j_cry_luigi = { name = "路易吉", text = { "所有小丑提供", - "{X:chips,C:white} X#1# {} 筹码", + "{X:chips,C:white} X#1# {}筹码", }, }, j_cry_m = { name = "m", text = { "当{C:attention}开心小丑{}被售出时", - "这张小丑获得 {X:mult,C:white} X#1# {} 倍率", - "{C:inactive}(当前 {X:mult,C:white} X#2# {C:inactive} 倍率)", + "这张小丑获得 {X:mult,C:white} X#1# {}倍率", + "{C:inactive}(当前 {X:mult,C:white} X#2# {C:inactive}倍率)", }, }, j_cry_macabre = { @@ -1675,14 +2330,14 @@ return { name = "冰箱磁铁", text = { "回合结束时获得{C:money}$#1#{} ", - "如果有少于或等于{C:attention}#3#{} 张小丑牌,获得 {X:money,C:white} X#2# {}", + "如果有少于或等于{C:attention}#3#{}张小丑牌,获得{X:money,C:white} X#2#{}", "", }, }, j_cry_manic = { name = "狂躁小丑", text = { - "如果出的牌中包含 {C:attention}#2#", + "如果打出的牌中包含{C:attention}#2#", "{C:red}+#1#{} 倍率", }, }, @@ -1696,15 +2351,19 @@ return { j_cry_mask = { name = "面具", text = { - "{C:attention}人头牌{}额外触发 {C:attention}#1#{} 次", + "{C:attention}人头牌{}额外触发{C:attention}#1#{}次", "所有{C:attention}非人头牌{}被削弱", }, }, j_cry_maximized = { name = "速度拉满", text = { - "所有{C:attention}人头牌{}都当作是{C:attention}K{},", - "所有{C:attention}数字牌{}都当作是{C:attention}10s{},", + "所有{C:attention}人头牌{}都当作是{C:attention}K{}", + "所有{C:attention}数字牌{}都当作是{C:attention}10s{}", + }, + unlock = { + "打出一手{C:attention}五张同花{}", + "且都是{C:attention}K{}", }, }, j_cry_maze = { @@ -1718,24 +2377,33 @@ return { name = "南瓜糖", text = { "卖掉这张牌", - "所有的{C:attention}消耗牌{} 售价 {C:attention}X#1#倍", + "所有的{C:attention}消耗牌{}售价{C:attention}X#1#倍", }, }, j_cry_membershipcard = { name = "会员卡", text = { - "Cryptid Discord{}中的每个成员提供{X:mult,C:white}X#1#{} {C:attention}倍率", - "{C:inactive}(当前{X:mult,C:white}X#2#{C:inactive} 倍率)", - "{C:blue,s:0.7}https://discord.gg/unbalanced{}", + "Cryptid Discord{}中的每个成员提供{X:mult,C:white}X#1#{} {C:attention}倍率", + "{C:inactive}(当前{X:mult,C:white}X#2#{C:inactive}倍率)", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_membershipcardtwo = { - name = "老旧会员卡", + name = "老旧会员卡", --Could probably have a diff Name imo text = { "在{C:attention}Cryptid Discord{}中的每个成员", - "提供{C:chips}+#1#{} Chips", - "{C:inactive}(当前 {C:chips}+#2#{C:inactive} 筹码)", - "{C:blue,s:0.7}https://discord.gg/unbalanced{}", + "提供{C:chips}+#1#{}筹码", + "{C:inactive}(当前 {C:chips}+#2#{C:inactive}筹码)", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", + }, + }, + j_cry_membershipcardtwo_balanced = { + name = "老旧会员卡", --Could probably have a diff Name imo + text = { + "每有{C:attention}8{}名{C:attention}Cryptid Discord{}成员", + "获得{C:chips}+#1#{}筹码", + "{C:inactive}(当前为{C:chips}+#2#{C:inactive}筹码)", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_meteor = { @@ -1757,14 +2425,14 @@ return { name = "蒙德里安", text = { "若回合结束没有使用弃牌", - "该小丑获得{X:mult,C:white} X#1# {} 倍率", - "{C:inactive}(当前{X:mult,C:white} X#2# {C:inactive} 倍率)", + "该小丑获得{X:mult,C:white} X#1# {}倍率", + "{C:inactive}(当前{X:mult,C:white} X#2# {C:inactive}倍率)", }, }, j_cry_monkey_dagger = { name = "猴子匕首", text = { - "当选择{C:attention}盲注{}时,", + "当选择{C:attention}盲注{}时", "摧毁左边的小丑", "并永久增加其售价的{C:attention}十倍{}", "到这张{C:chips}筹码{}", @@ -1776,14 +2444,14 @@ return { text = { "{C:green}#1# / #2#{} 几率", "{C:attention}摧毁{}购买的牌", - "并且售出时 {C:attention}金钱减半", + "并且售出时{C:attention}金钱减半", }, }, j_cry_morse = { name = "摩尔斯电码", text = { - "在回合结尾获得 {C:money}$#2#{}", - "每卖掉一张 {C:attention}增强卡牌{}增加 {C:money}$#1#{}", + "在回合结尾获得{C:money}$#2#{}", + "每卖掉一张{C:attention}增强卡牌{}增加{C:money}$#1#{}", }, }, j_cry_mprime = { @@ -1791,16 +2459,16 @@ return { text = { "每回合结束时", "创造一张{C:attention}M 小丑{}", - "每个 {C:attention}开心小丑{}或者{C:attention}M 小丑{} 提供 {X:dark_edition,C:white}^#1#{} 倍率", - "每 {C:attention}卖出{}一张 {C:attention}开心小丑{}", - "额外提供 {X:dark_edition,C:white}^#2#{}倍率", + "每个{C:attention}开心小丑{}或者{C:attention}M 小丑{}提供{X:dark_edition,C:white}^#1#{}倍率", + "每{C:attention}卖出{}一张{C:attention}开心小丑{}", + "额外提供{X:dark_edition,C:white}^#2#{}倍率", "{C:inactive,s:0.8}(使徒·十三 除外)", }, }, j_cry_mstack = { name = "堆叠 M", text = { - "每出售{C:attention}#2#{} {C:inactive}[#3#]{} {C:attention}开心小丑{}", + "每出售{C:attention}#2#{}{C:inactive}[#3#]{}张{C:attention}开心小丑{}", "重新触发所有已打出的牌", "{C:inactive}(当前{}{C:attention:} #1#{}{C:inactive} 次重新触发){}", }, @@ -1817,21 +2485,21 @@ return { j_cry_necromancer = { name = "死灵法师", text = { - "当{C:attention}售出{}一张小丑且其售价大于 {C:attention}$0{} 时", - "获得一张 {C:attention}本局游戏售出过的{} {C:attention}随机小丑牌{} ", - "并将其 {C:attention}售价{} 变为 {C:attention}$0{}", + "当{C:attention}售出{}一张小丑且其售价大于{C:attention}$0{}时", + "获得一张{C:attention}本局游戏售出过的{}{C:attention}随机小丑牌{} ", + "并将其{C:attention}售价{}变为{C:attention}$0{}", }, }, j_cry_negative = { name = "负片小丑", text = { - "{C:dark_edition}+#1#{C:attention} 小丑{} 槽", + "{C:dark_edition}+#1#{C:attention} 小丑{}槽", }, }, j_cry_nice = { name = "nice", text = { - "如果出牌包含 {C:attention}6{} 和 {C:attention}9{}", + "如果出牌包含{C:attention}6{}和{C:attention}9{}", "筹码{C:chips}+#1#{}", "{C:inactive,s:0.8}nice{}", "", @@ -1863,24 +2531,29 @@ return { j_cry_number_blocks = { name = "数字块", text = { - "在回合结束时获得 {C:money}$#1#{}", + "在回合结束时获得{C:money}$#1#{}", "每持有一张{C:attention}#3#{}手牌", - "增加{C:money}$#2#{}的奖励,", + "增加{C:money}$#2#{}的奖励", "每回合卡牌变化", }, }, j_cry_nuts = { name = "坚果", text = { - "{X:mult,C:white} X#1# {} 倍率如果出牌", + "{X:mult,C:white} X#1# {}倍率如果出牌", "手牌包含", "一个{C:attention}#2#", }, + unlock = { + "赢得一局游戏", + "且未打出过", + "{E:1,C:attention}同花顺", + }, }, j_cry_nutty = { name = "疯癫小丑", text = { - "如果出的牌中包含 {C:attention}#2#", + "如果打出的牌中包含{C:attention}#2#", "{C:red}+#1#{} 倍率", }, }, @@ -1888,7 +2561,7 @@ return { name = "油灯", text = { "回合结束后", - "右边 {C:attention}小丑牌{}的数值 {C:attention}x#1#{}", + "右边{C:attention}小丑牌{}的数值{C:attention}x#1#{}", }, }, j_cry_oldblueprint = { @@ -1903,13 +2576,13 @@ return { name = "怀旧糖果", text = { "售出这张牌可以永久获得", - "{C:attention}+#1#{} 手牌上限", + "{C:attention}+#1#{}手牌上限", }, }, j_cry_oldinvisible = { name = "怀旧隐形小丑", text = { - "每卖出 {C:attention} 4 {}张小丑牌,随机复制 {C:attention}一张{}小丑牌", + "每卖出{C:attention} 4 {}张小丑牌,随机复制{C:attention}一张{}小丑牌", "无法复制{s:0.8}怀旧隐形小丑{}(当前 #1#/4)", "", }, @@ -1920,6 +2593,13 @@ return { "所有出牌都视为本回合{C:attention}最后一次出牌{}", }, }, + j_cry_paved_joker = { + name = "铺路小丑", + text = { + "石头牌可以填补", + "{C:attention}顺子{}和{C:attention}同花{}中{C:attention}#1#{}点的间隔", + }, + }, j_cry_penetrating = { name = "渗透小丑", text = { @@ -1931,14 +2611,14 @@ return { j_cry_pickle = { name = "腌黄瓜", text = { - "当跳过 {C:attention}盲注{} 时,创造{C:attention}#1#{} 个标签", - "当选择 {C:attention}盲注{} 时,则减少{C:red}#2#{} ", + "当跳过{C:attention}盲注{}时,创造{C:attention}#1#{}个标签", + "当选择{C:attention}盲注{}时,则减少{C:red}#2#{} ", }, }, j_cry_pirate_dagger = { name = "海盗匕首", text = { - "当选择{C:attention}盲注{}时,", + "当选择{C:attention}盲注{}时", "摧毁右边的小丑", "并获得其售价的{C:attention}四分之一{}", "作为{X:chips,C:white} X筹码 {}", @@ -1948,23 +2628,73 @@ return { j_cry_pity_prize = { name = "遗憾奖", text = { - "当你跳过 {C:attention}补充包{} 获得一个随机的 {C:attention}标签{}", + "当你跳过{C:attention}补充包{}时", + "获得一个随机的{C:attention}标签{}", + }, + }, + j_cry_pity_prize_modest = { + name = "遗憾奖", + text = { + "当跳过一个{C:attention}补充包{}时", + "获得一个随机{C:attention}标签{}", + "{C:red,E:2}自毁{}", + }, + }, + j_cry_pizza = { + name = "披萨", + text = { + "在{C:attention}#1#{} {C:inactive}[#2#]{}回合之后", + "出售这个小丑可以创建{C:attention}#3#{}个披萨片", + }, + }, + j_cry_pizza_slice = { + name = "披萨片", + text = { + "当一个{C:attention}披萨片{}被出售时", + "这张小丑获得{X:mult,C:white}X#1#{} 倍率", + "{C:inactive}(当前 {X:mult,C:white}X#2#{}{C:inactive} 倍率){}", }, }, j_cry_pot_of_jokes = { name = "小丑之壶", text = { "{C:attention}#1#{}手牌上限,", - "每回合增加{C:blue}#2#{} ", + "每回合增加{C:blue}#2#{}", + }, + unlock = { + "将你的{C:attention}手牌上限{}", + "提升至{C:attention}12", + }, + }, + j_cry_poor_joker = { + name = "贫穷小丑", + text = { + "当一张{C:attention}租用{}牌扣除金钱时", + "此小丑获得{C:mult}+#1#{}倍率", + "{C:inactive}(当前{} {C:mult}+#2#{} {C:inactive}倍率){}", }, }, j_cry_primus = { name = "素数", text = { - "这张小丑获得 {X:dark_edition,C:white} ^#1# {} 倍率", + "这张小丑获得 {X:dark_edition,C:white} ^#1# {}倍率", "如果手中打出的所有牌都是", "{C:attention}A{}、{C:attention}2{}、{C:attention}3{}、{C:attention}5{} 或 {C:attention}7{}", - "{C:inactive}(当前 {X:dark_edition,C:white} ^#2# {C:inactive} 倍率)", + "{C:inactive}(当前 {X:dark_edition,C:white} ^#2# {C:inactive}倍率)", + }, + }, + j_cry_pumpkin = { + name = "南瓜", + text = { + "如果得分筹码至少达到所需筹码的{C:attention}50%{},则不会死亡", + "被{C:red}摧毁{}时变为{C:attention}雕刻南瓜", + }, + }, + j_cry_carved_pumpkin = { + name = "雕刻南瓜", + text = { + "接下来的{C:attention}#1#{}个Boss盲注", + "其能力将被{C:attention}禁用", }, }, j_cry_python = { @@ -1986,10 +2716,15 @@ return { j_cry_quintet = { name = "五重奏", text = { - "{X:mult,C:white} X#1# {} 倍率如果出牌", + "{X:mult,C:white} X#1# {}倍率如果出牌", "手牌包含", "一个{C:attention}#2#", }, + unlock = { + "赢得一局游戏", + "且最终打出的牌型为", + "{E:1,C:attention}五条", + }, }, j_cry_redbloon = { name = "红色气球", @@ -2000,8 +2735,8 @@ return { j_cry_redeo = { name = "回溯", text = { - "当花费{C:money}$#2#{} {C:inactive}($#3#){} 时", - "{C:attention}-#1#{} 底注", + "当花费{C:money}$#2#{}{C:inactive}($#3#){}时", + "{C:attention}-#1#{}底注", "每次使用{C:attention,s:0.8}指数增加{}花费", "{C:money,s:0.8}下次增加:{s:1,c:money}$#4#", }, @@ -2030,6 +2765,19 @@ return { text = { "每次{C:attention}底注{}时随机能力", }, + unlock = { + "{C:green}1 / 20{}的概率", + "在{C:attention}游戏结束{}时解锁此卡", + }, + }, + j_cry_rotten_egg = { + name = "臭鸡蛋", + text = { + "获得时,将所有当前和未来小丑的售价设置为{C:attention}$#1#{}", + "所有{C:attention}小丑{}的售价降低{C:attention}$#2#{}", + "回合结束时,从出售{C:attention}小丑{}中获得{C:attention}$#3#{} {C:inactive}[#4#]{}后", + "{C:red}自毁{}", + }, }, j_cry_sacrifice = { name = "献祭", @@ -2047,50 +2795,50 @@ return { text = { "当{C:attention}#2#{} {C:inactive}[#1#]{} 张{C:attention}增强牌{}计分后", "卖掉此牌", - "以获得一张{C:cry_epic}史诗{} {C:attention}小丑{}", + "以获得一张{C:cry_epic}史诗{}{C:attention}小丑{}", }, }, j_cry_savvy = { name = "精明小丑", text = { - "如果出的牌中包含 {C:attention}#2#", + "如果打出的牌中包含{C:attention}#2#", "{C:chips}+#1#{} 筹码", }, }, j_cry_scrabble = { name = "拼M游戏", text = { - "当打出手牌时,", + "当打出手牌时", "会有{C:green}#1#/#2#{}几率生成一张", - "{C:dark_edition}欢愉 {C:green}罕见{}小丑", + "{C:dark_edition}欢愉{C:green}罕见{}小丑", }, }, j_cry_seal_the_deal = { name = "契约已成", text = { - "打出本回合{C:attention}最后一手牌{}时,", + "打出本回合{C:attention}最后一手牌{}时", "每张计分的卡获得{C:attention}随机蜡封{}", }, }, j_cry_shrewd = { name = "敏锐小丑", text = { - "如果出的牌中包含 {C:attention}#2#", + "如果打出的牌中包含{C:attention}#2#", "{C:chips}+#1#{} 筹码", }, }, j_cry_silly = { name = "傻傻小丑", text = { - "如果出的牌中包含 {C:attention}#2#", + "如果打出的牌中包含{C:attention}#2#", "{C:red}+#1#{} 倍率", }, }, j_cry_smallestm = { name = "超小M", text = { - "打出 {C:attention}#1#{} 时", - "创造一个 {C:cry_jolly}M 标签{}", + "打出{C:attention}#1#{}时", + "创造一个{C:cry_jolly}M 标签{}", "{C:inactive,s:0.8}好吧,基本上我很小", }, }, @@ -2102,6 +2850,48 @@ return { "{C:attention}+#1#{} 手牌上限", "{C:attention}+#1#{} 消耗牌槽位", "{C:attention}+#1#{} 商店栏位", + "{C:attention}+#1#{} 优惠券槽位", + }, + unlock = { + "仅使用{C:attention}高牌{}", + "赢得一局游戏", + }, + }, + j_cry_soccer_balanced = { + name = "合众为一", + text = { + "{C:attention}+#1#{} 补充包槽位", + "{C:attention}+#1#{} 手牌上限", + "{C:attention}+#1#{} 消耗牌槽位", + "{C:attention}+#1#{} 商店栏位", + "{C:attention}+#1#{} 优惠券槽位", + }, + unlock = { + "仅使用{C:attention}高牌{}", + "赢得一局游戏", + }, + }, + j_cry_sock_and_sock = { + name = "袜子配袜子", + text = { + "重新触发所有打出的", + "{C:attention}抽象{}牌{C:attention}#1#{}次", + }, + }, + j_cry_brokenhome = { + name = "破碎家园", + text = { + "{X:mult,C:white}X#1#{}倍率", + "回合结束时", + "有{C:green}#2#/#3#{}的概率", + "摧毁此牌", + }, + }, + j_cry_yarnball = { + name = "毛线球", + text = { + "将最高等级{C:attention}猫咪标签{}的等级", + "添加到所有{C:green}列出的概率{}中", }, }, j_cry_spaceglobe = { @@ -2131,7 +2921,7 @@ return { j_cry_spy = { name = "间谍", text = { - "{X:mult,C:white} X#2# {} 倍率, {C:dark_edition}+1{C:attention} 小丑槽{} ", + "{X:mult,C:white} X#2# {}倍率, {C:dark_edition}+1{C:attention}小丑槽{} ", "{C:inactive} #1# 是间谍!", }, }, @@ -2142,12 +2932,19 @@ return { "每张提供{X:mult,C:white}X#1#{} 倍率", }, }, + j_cry_starfruit = { + name = "杨桃", + text = { + "{X:dark_edition,C:white}^#1#{} 倍率", + "商店中每{C:attention}重掷{}一次,失去{X:dark_edition,C:white}^#2#{} 倍率", + }, + }, j_cry_stella_mortis = { name = "星逝", text = { "{C:attention}商店{}结束时", "摧毁一张随机{C:planet}星球{}牌", - "并在获得 {X:dark_edition,C:white} ^#1# {} 倍率", + "并在获得 {X:dark_edition,C:white} ^#1# {}倍率", "{C:inactive}(当前 {X:dark_edition,C:white} ^#2# {C:inactive} 倍率)", }, }, @@ -2156,13 +2953,18 @@ return { text = { "如果打出的手牌包含", "一个 {C:attention}#2#", - "{X:mult,C:white} X#1# {} 倍率", + "{X:mult,C:white} X#1# {}倍率", + }, + unlock = { + "赢得一局游戏", + "且最终打出的牌型为", + "{E:1,C:attention}碉堡", }, }, j_cry_subtle = { name = "微妙小丑", text = { - "如果出的牌中包含 {C:attention}#2#", + "如果打出的牌中包含{C:attention}#2#", "{C:chips}+#1#{} 筹码", }, }, @@ -2174,6 +2976,13 @@ return { "在回合结束时获得 {C:money}$#3#{}", }, }, + j_cry_supercell_balanced = { + name = "Supercell", + text = { + "{X:chips,C:white}X#2#{} 筹码, {X:mult,C:white}X#2#{} 倍率", + "在回合结束时获得 {C:money}$#3#{}", + }, + }, j_cry_sus = { name = "sus小丑", text = { @@ -2185,15 +2994,20 @@ return { j_cry_swarm = { name = "虫群", text = { - "{X:mult,C:white} X#1# {} 倍率如果出牌", + "{X:mult,C:white} X#1# {}倍率如果出牌", "手牌包含", "一个{C:attention}#2#", }, + unlock = { + "赢得一局游戏", + "且最终打出的牌型为", + "{E:1,C:attention}同花五条", + }, }, j_cry_sync_catalyst = { name = "同步催化剂", text = { - "平衡 {C:chips}筹码{} 和 {C:mult}倍率{}", + "平衡{C:chips}筹码{}和{C:mult}倍率{}", "{C:inactive,s:0.8}嘿!我之前见过这个!(等离子牌组效果)", }, }, @@ -2201,15 +3015,15 @@ return { name = "逃税", text = { "回合结束后", - "每有一个 {C:attention}租用小丑{}", - "获得 {C:attention}$#1#{}", + "每有一个{C:attention}租用小丑{}", + "获得{C:attention}$#1#{}", }, }, j_cry_tenebris = { name = "暗黑", text = { - "{C:dark_edition}+#1#{C:attention} 小丑{}槽", - "在回合结束时获得 {C:money}$#2#{}", + "{C:dark_edition}+#1#{C:attention}小丑{}槽", + "在回合结束时获得{C:money}$#2#{}", }, }, j_cry_translucent = { @@ -2224,23 +3038,59 @@ return { name = "诡谲小丑", text = { "如果打出的手牌包含", - "一个 {C:attention}#2#", + "一个{C:attention}#2#", "{C:chips}+#1#{} 筹码", }, }, + j_cry_nebulous = { + name = "朦胧小丑", + text = { + "如果打出的手牌是{C:attention}#2#{}", + "获得{C:chips}+#1#{}筹码", + }, + }, + j_cry_words_cant_even = { + name = "言语甚至无法描述的小丑", + text = { + "如果打出的手牌包含", + "一个{C:attention}#2#{}", + "获得{X:mult,C:white}X#1#{}倍率", + }, + }, + j_cry_many_lost_minds = { + name = "无数人因试图理解他而发狂的小丑", + text = { + "如果打出的手牌包含", + "一个{C:attention}#2#{}", + "获得{C:chips}+#1#{}筹码", + }, + }, + j_cry_annihalation = { + name = "彻底摧毁 Balatro 神圣的终极小丑", + text = { + "如果打出的手牌包含", + "一个{C:attention}#2#{}", + "获得{X:dark_edition,C:white}^#1#{}倍率", + }, + unlock = { + "赢得一局游戏", + "且最终打出的牌型为", + "{E:1,C:attention}#1#", + }, + }, j_cry_trick_or_treat = { name = "不给糖就捣蛋", text = { " {C:attention}出售时{}:", - "{C:green}#1# / #2#{} 几率创建 {C:attention}2{}个 {C:cry_candy}糖果", - "否则 创建一个 {X:cry_cursed,C:white}诅咒小丑{} ", + "{C:green}#1# / #2#{} 几率创建 {C:attention}2{}个{C:cry_candy}糖果", + "否则创建一个{X:cry_cursed,C:white}诅咒小丑{} ", "{C:inactive}(可以溢出)", }, }, j_cry_tricksy = { name = "诡诈小丑", text = { - "如果出的牌中包含 {C:attention}#2#", + "如果打出的牌中包含{C:attention}#2#", "{C:chips}+#1#{} 筹码", }, }, @@ -2249,7 +3099,7 @@ return { text = { "计分牌中刚好有", " {C:attention}3 张 3 {}时", - "提供{X:mult,C:white} X#1# {} 倍率", + "提供{X:mult,C:white} X#1# {}倍率", }, }, j_cry_tropical_smoothie = { @@ -2262,29 +3112,34 @@ return { j_cry_unity = { name = "团结", text = { - "{X:mult,C:white} X#1# {} 倍率如果出牌", + "{X:mult,C:white} X#1# {}倍率如果出牌", "手牌包含", "一个{C:attention}#2#", }, + unlock = { + "赢得一局游戏", + "且最终打出的牌型为", + "{E:1,C:attention}同花葫芦", + }, }, j_cry_universe = { name = "宇宙", text = { - "每张{C:dark_edition}星界{} ", - "提供 {X:dark_edition,C:white}^#1#{} 倍率", + "每张{C:dark_edition}星界{}", + "提供{X:dark_edition,C:white}^#1#{} 倍率", }, }, j_cry_universum = { name = "寰宇", text = { "{C:attention}牌型{}升级时获得", - "{X:red,C:white} X#1# {} 倍率和 {X:blue,C:white} X#1# {} 筹码", + "{X:red,C:white} X#1# {}倍率和{X:blue,C:white} X#1# {}筹码", }, }, j_cry_unjust_dagger = { name = "不公匕首", text = { - "当选择{C:attention}盲注{}时,", + "当选择{C:attention}盲注{}时", "摧毁左边的小丑", "并获得其售价的{C:attention}五分之一{}", "作为{X:mult,C:white} X倍率 {}", @@ -2295,8 +3150,8 @@ return { name = "虚实", text = { "当任何概率", - "{C:green}成功{}触发时,", - "这张小丑获得{X:red,C:white}X 倍率{}", + "{C:green}成功{}触发时", + "这张小丑获得{X:red,C:white}X倍率{}", "等于其列出的{C:attention}概率", "{C:inactive}(当前 {X:mult,C:white} X#1# {C:inactive} 倍率)", }, @@ -2304,17 +3159,17 @@ return { j_cry_virgo = { name = "室女座", text = { - "如果 {C:attention}果出牌牌型{} 包含一个 {C:attention}#2#{}", - "该小丑增加 {C:money}$#1#{} {C:attention}售价{}", + "如果{C:attention}果出牌牌型{}包含一个{C:attention}#2#{}", + "该小丑增加{C:money}$#1#{}{C:attention}售价{}", "出售这张牌时", - "每 {C:money}$4{} 的 {C:attention}出售价值{}{C:dark_edition}创造一张多彩{} {C:attention}开心小丑{},", + "每{C:money}$4{}的{C:attention}出售价值{}{C:dark_edition}创造一张多彩{}{C:attention}开心小丑{}", " {C:inactive}(至少 1){}", }, }, j_cry_wacky = { name = "搞怪小丑", text = { - "如果出的牌中包含 {C:attention}#2#", + "如果打出的牌中包含{C:attention}#2#", "{C:red}+#1#{} 倍率", }, }, @@ -2322,7 +3177,7 @@ return { name = "瓦路易吉", text = { "所有小丑提供", - "{X:mult,C:white} X#1# {} 倍率", + "{X:mult,C:white} X#1# {}倍率", }, }, j_cry_wario = { @@ -2336,7 +3191,7 @@ return { name = "微波那契数列", text = { "这个小丑获得", - "{C:mult}+#2#{} 倍率,当打出的每张", + "{C:mult}+#2#{}倍率,当打出的每张", "{C:attention}A{}, {C:attention}2{}, {C:attention}3{}, {C:attention}5{}, 或 {C:attention}8{}", "计分时", "{C:inactive}(当前 {C:mult}+#1#{C:inactive} 倍率)", @@ -2346,31 +3201,38 @@ return { name = "2D", text = { "每张计分的2", - "重新触发 {C:attention:}#1#{} 次", - "{C:inactive,s:0.8}我们身处游戏中吗 {}", + "重新触发{C:attention:}#1#{}次", + "{C:inactive,s:0.8}我们身处游戏中吗{}", }, }, j_cry_wheelhope = { name = "希望之轮", text = { "当{C:attention}命运之轮{}效果失败", - "这张牌获得{X:mult,C:white} X#1# {} 倍率", + "这张牌获得{X:mult,C:white} X#1# {}倍率", "{C:inactive}(当前{X:mult,C:white} X#2# {C:inactive} 倍率)", }, }, j_cry_whip = { name = "长鞭", text = { - "这张小丑获得 {X:mult,C:white} X#1# {} 倍率", - "如果 {C:attention}出牌手牌{} 包含", - "不同花色的{C:attention}2{} 和 {C:attention}7{}", + "这张小丑获得{X:mult,C:white} X#1# {}倍率", + "如果{C:attention}出牌手牌{}包含", + "不同花色的{C:attention}2{}和{C:attention}7{}", "{C:inactive}(当前 {X:mult,C:white} X#2# {C:inactive} 倍率)", }, }, + j_cry_wonka_bar = { + name = "Wonka 巧克力", + text = { + "出售此卡以永久获得", + "{C:attention}+#1#{}卡牌选择上限", + }, + }, j_cry_wrapped = { name = "包裹糖果", text = { - "{C:attention}#1#{} 回合后", + "{C:attention}#1#{}回合后", "创建一个随机的{C:attention}食物小丑{}", "{C:red,E:2}自毁{}", }, @@ -2379,14 +3241,19 @@ return { name = "我操!?", text = { "如果打出的手牌包含", - "一个 {C:attention}#2#", - "{X:mult,C:white} X#1# {} 倍率", + "一个{C:attention}#2#", + "{X:mult,C:white} X#1# {}倍率", + }, + unlock = { + "赢得一局游戏", + "且最终打出的牌型为", + "{E:1,C:attention}#1#", }, }, j_cry_zooble = { name = "祖波", text = { - "打出并计分的牌中,", + "打出并计分的牌中", "每有一个{C:attention}不同点数{},获得{C:mult}+#2#{}倍率", "{C:inactive}(当前{C:mult}+#1#{C:inactive}倍率)", "{C:inactive}(包含顺子的出牌不触发)", @@ -2394,6 +3261,15 @@ return { }, }, Other = { + alt_wheel_of_fortune = { + name = "命运之轮", + text = { + "有{C:green}#1#/#2#{}几率", + "给一张随机{C:attention}小丑牌", + "添加{C:dark_edition}闪箔{}、{C:dark_edition}镭射{}", + "或{C:dark_edition}多彩{}版本", + }, + }, banana = { name = "香蕉", text = { @@ -2407,12 +3283,20 @@ return { "{C:inactive,s:0.8}我讨厌这张牌- SDM_0, 2024{}", }, }, + cry_absolute = { + name = "绝对", + text = { + "不能出售", + "或被摧毁", + "{C:attention}不可移除{}", + }, + }, cry_azure_seal = { name = "蔚蓝蜡封", text = { "打出附带该蜡封的牌时", "{C:red}摧毁{}这张牌", - "之后创造 {C:attention}#1#{} 张 {C:dark_edition}负片{}{C:planet}对应牌型的星球牌{}", + "之后创造{C:attention}#1#{}张{C:dark_edition}负片{}{C:planet}对应牌型的星球牌{}", }, }, cry_banana_booster = { @@ -2452,28 +3336,50 @@ return { cry_flickering = { name = "闪烁", text = { - "{C:attention}#1#{} 次触发后摧毁", + "{C:attention}#1#{}次触发后摧毁", "{C:inactive}(剩余{C:attention}#2#{C:inactive} 次)", }, }, cry_flickering_desc = { name = "闪烁", text = { - "{C:attention}#1#{} 次触发后摧毁", + "{C:attention}#1#{}次触发后摧毁", + }, + }, + cry_function_sticker = { + name = "函数://", + text = { + "使用后按顺序依次创建", + "{C:cry_code}#1#{}、{C:cry_code}#2#{}和{C:cry_code}#3#{}", + }, + }, + cry_function_sticker_desc = { + name = "函数://", + text = { + "创建一张", + "带有{C:cry_code}函数://{}贴纸的消耗牌", + "{C:inactive}当前:#1#、#2#和#3#{}", + }, + }, + cry_global_sticker = { + name = "全局", + text = { + "尽可能在其他牌之前", + "{C:cry_code}抽到此卡{}", }, }, cry_green_seal = { name = "秩绿蜡封", text = { "仅当被打出且不计分时", - "创造一张 {C:cry_code}代码{} 卡牌", + "创造一张{C:cry_code}代码{}卡牌", "{C:inactive}(必须有空间)", }, }, cry_hooked = { name = "连锁", text = { - "当这个小丑被{C:cry_code}触发{}时,", + "当这个小丑被{C:cry_code}触发{}时", "触发{C:cry_code}#1#{}", }, }, @@ -2483,6 +3389,12 @@ return { "{C:attention,s:0.7}更新{s:0.7} 默认情况下被禁用 ({C:attention,s:0.7}HTTPS模块{s:0.7})", }, }, + cry_multiuse = { + name = "多次使用", + text = { + "{C:inactive}可多次使用: ({C:inactive}剩余{C:cry_code}#1#{C:inactive}次)", + }, + }, cry_perishable_booster = { name = "易腐", text = { @@ -2499,7 +3411,7 @@ return { cry_perishable_voucher = { name = "易腐优惠券", text = { - "{C:attention}#1#{} 回合后被削弱", + "{C:attention}#1#{}回合后被削弱", "{C:inactive}({C:attention}#2#{C:inactive} 剩余)", }, }, @@ -2527,9 +3439,9 @@ return { cry_possessed = { name = "作祟", text = { - "{C:attention}禁用{} 此牌效果", + "{C:attention}禁用{}此牌效果", "如果可能的话{C:attention}反转{}此牌的效果", - "随着 {C:attention}幽灵{}的摧毁而摧毁", + "随着{C:attention}幽灵{}的摧毁而摧毁", }, }, cry_rental_booster = { @@ -2542,13 +3454,13 @@ return { cry_rental_consumeable = { name = "租赁消耗牌", text = { - "回合结束时和使用时失去 {C:money}$#1#{}", + "回合结束时和使用时失去{C:money}$#1#{}", }, }, cry_rental_voucher = { name = "租赁优惠券", text = { - "回合结束时失去 {C:money}$#1#{}", + "回合结束时失去{C:money}$#1#{}", }, }, cry_rigged = { @@ -2558,19 +3470,44 @@ return { "都{C:cry_code}必定触发", }, }, + disabled = { + name = "Disabled", + text = { + "不再在本局游戏中出现", + }, + }, + disabled_card_dependency = { + name = "Disabled", + text = { + "需要{C:attention}#1#", + }, + }, + disabled_mod_dependency = { + name = "Disabled", + text = { + "需要mod: {C:attention}#1#", + }, + }, + disabled_mod_conflict = { + name = "Disabled", + text = { + "与以下mod冲突:", + "{C:attention}#1#", + }, + }, ev_cry_choco0 = { name = "", text = { "激活事件后", - "{C:cry_ascendant,E:1}事件{} 的具体信息将会出现", + "{C:cry_ascendant,E:1}事件{}的具体信息将会出现", }, }, ev_cry_choco1 = { name = "1: 恶灵附身", text = { - "{C:attention}小丑牌{} 和打出的牌有", + "{C:attention}小丑牌{}和打出的牌有", "{C:green}1 / 3{} 几率获得闪烁", - "创造一张 {C:attention}幽灵", + "创造一张{C:attention}幽灵", "{C:inactive,s:0.7}你被幽灵附身了", "{C:inactive,s:0.7}意识时而清醒,时而模糊", }, @@ -2578,19 +3515,19 @@ return { ev_cry_choco10 = { name = "10: 珍贵古董", text = { - "一张售价{C:money}$50{}的 {C:legendary}传奇{} {C:attention}小丑{} ", - "出现在商店 {C:attention}优惠券{}槽位", - "只有作为商店 {C:attention}最后一件物品{} 时才能购买", - "{C:inactive,s:0.7}你已经引起了遗物之灵的注意,", + "一张售价{C:money}$50{}的{C:legendary}传奇{}{C:attention}小丑{} ", + "出现在商店{C:attention}优惠券{}槽位", + "只有作为商店{C:attention}最后一件物品{}时才能购买", + "{C:inactive,s:0.7}你已经引起了遗物之灵的注意", "{C:inactive,s:0.7}但想要平息它,可没那么简单", }, }, ev_cry_choco2 = { name = "2: 鬼屋", text = { - "不能跳过 {C:attention}盲注{}", - "商店中只能 {C:attention}重掷{} 一次", - "{C:attention}优惠券{} 售价翻倍", + "不能跳过{C:attention}盲注{}", + "商店中只能{C:attention}重掷{}一次", + "{C:attention}优惠券{}售价翻倍", "{C:inactive,s:0.7}幽灵们已经占领这里!", "{C:inactive,s:0.7}千万别碰任何东西,快点逃出去!", }, @@ -2598,9 +3535,9 @@ return { ev_cry_choco3 = { name = "3: 女巫药剂", text = { - "创造3个 {C:attention}魔药", + "创造3个{C:attention}魔药", "在{C:attention}小盲注{}结束前使用其中之一", - "否则 {C:attention}所有的{} 减益效果都会在这个{C:attention}底注{}生效", + "否则{C:attention}所有的{}减益效果都会在这个{C:attention}底注{}生效", "{C:inactive,s:0.7}你被女巫绑架了!", "{C:inactive,s:0.7}她盯着你,递上三瓶药剂", "{C:inactive,s:0.7}选一个吧,不然她可要替你做决定了。", @@ -2609,9 +3546,9 @@ return { ev_cry_choco4 = { name = "4: 月之深渊", text = { - "打出的牌有 {C:green}1 / 4{} 几率", - "变为随机的 {C:club}梅花{} 人头牌", - "将 {C:attention}倍率{} 除以打出人头牌的数量", + "打出的牌有{C:green}1 / 4{} 几率", + "变为随机的{C:club}梅花{}人头牌", + "将{C:attention}倍率{}除以打出人头牌的数量", "{C:inactive,s:0.7}即便是心地善良、", "{C:inactive,s:0.7}夜晚虔诚祈祷之人……", }, @@ -2619,11 +3556,11 @@ return { ev_cry_choco5 = { name = "5: 吸血鬼", text = { - "移除所有打出的牌的 {C:attention}增强{} ", + "移除所有打出的牌的{C:attention}增强{} ", "并有{C:green}1 / 3{} 几率摧毁", - "{C:heart}红桃{} 和 {C:diamond}方块{} 卡牌", - "{C:inactive,s:0.7}夜深人静时,你必须更加谨慎,", - "{C:inactive,s:0.7,E:1}因为它们在阴影中{C:inactive,s:0.7} 伺机满足自己的饥渴……", + "{C:heart}红桃{}和{C:diamond}方块{}卡牌", + "{C:inactive,s:0.7}夜深人静时,你必须更加谨慎", + "{C:inactive,s:0.7,E:1}因为它们在阴影中{C:inactive,s:0.7}伺机满足自己的饥渴……", }, }, ev_cry_choco6 = { @@ -2637,9 +3574,9 @@ return { ev_cry_choco7 = { name = "7: 节日气氛", text = { - "创建三个 {C:attention}不给糖就捣蛋{} 和一个 {C:attention}糖果篮子", - "每回合商店有一个 {C:attention}不给糖就捣蛋{}", - "获得{C:cry_candy}糖果{} 时,得到{C:money}$3{}", + "创建三个{C:attention}不给糖就捣蛋{}和一个{C:attention}糖果篮子", + "每回合商店有一个{C:attention}不给糖就捣蛋{}", + "获得{C:cry_candy}糖果{}时,得到{C:money}$3{}", "{C:inactive,s:0.7}整个社区都为恐怖的盛会装饰一新,", "{C:inactive,s:0.7}快来享受这节日气氛吧!", }, @@ -2647,8 +3584,8 @@ return { ev_cry_choco8 = { name = "8: 糖果雨", text = { - "击败 {C:attention}盲注{} 后, 每剩余一次出牌获得 1 个{C:cry_candy}糖果{}", - "当获得一个{C:cry_candy}糖果{}后,获得一个 {C:attention}食物小丑{}", + "击败{C:attention}盲注{}后, 每剩余一次出牌获得 1 个{C:cry_candy}糖果{}", + "当获得一个{C:cry_candy}糖果{}后,获得一个{C:attention}食物小丑{}", "{C:inactive,s:0.7}糖果从天而降!", "{C:inactive,s:0.7,E:1}快点,抓住你能抓到的所有糖果!", }, @@ -2656,85 +3593,94 @@ return { ev_cry_choco9 = { name = "9: 鬼魅财富", text = { - "获得 {C:money}$20", - "所有赚到的 {C:money}钱{} 都变为 {C:attention}双倍", + "获得{C:money}$20", + "所有赚到的{C:money}钱{}都变为{C:attention}双倍", "{C:inactive,s:0.7}你已故亲戚的幽灵在午夜时分来访!", - "{C:inactive,s:0.7}他们默默地将一袋钱放在你的手中,", + "{C:inactive,s:0.7}他们默默地将一袋钱放在你的手中", "{C:inactive,s:0.7}温暖一笑,随即化为虚影消散在空气中~", }, }, food_jokers = { name = "食物小丑", text = { - "{s:0.8}Gros Michel,鸡蛋,冰淇淋,卡文迪许,", - "{s:0.8}乌龟豆,饮料可乐,爆米花,拉面,", - "{s:0.8}苏打水,泡菜,辣椒,焦糖,", - "{s:0.8}怀旧糖果,M当劳,", - "{s:0.8}切奶酪,咖啡馆美食,樱桃,", - "{s:0.8}全糖可乐,星果,火锅,", - "{s:0.8}幸运饼干,瑞士小丑,塔利亚费罗,", - "{s:0.8}皇家佳丽,优质葡萄酒,神秘苏打水,", - "{s:0.8}爆米花袋,火鸡晚餐,咖啡,", - "{s:0.8}蜡烛服务,燃烧的西瓜,", - "{s:0.8}燃烧的樱桃,软玉米饼,脆玉米饼,", + "{s:0.8}Gros Michel,鸡蛋,冰淇淋,卡文迪许", + "{s:0.8}乌龟豆,饮料可乐,爆米花,拉面", + "{s:0.8}苏打水,泡菜,辣椒,焦糖", + "{s:0.8}怀旧糖果,M当劳", + "{s:0.8}切奶酪,咖啡馆美食,樱桃", + "{s:0.8}全糖可乐,星果,火锅", + "{s:0.8}幸运饼干,瑞士小丑,塔利亚费罗", + "{s:0.8}皇家佳丽,优质葡萄酒,神秘苏打水", + "{s:0.8}爆米花袋,火鸡晚餐,咖啡", + "{s:0.8}蜡烛服务,燃烧的西瓜", + "{s:0.8}燃烧的樱桃,软玉米饼,脆玉米饼", "{s:0.8}玉米片,幽灵可乐,汉堡,披萨", }, }, + p_cry_baneful_1 = { + name = "诅咒小丑包", + text = { + "从最多{C:attention}#2#张{X:cry_cursed,C:white}诅咒{}小丑中", + "选择{C:attention}#1#张{}", + "{C:attention}跳过{}将{C:red}移除{}", + "最右侧拥有的小丑", + }, + }, p_cry_code_jumbo_1 = { name = "巨型代码包", text = { - "选择 {C:attention}#1#{} 张最多", - "{C:attention}#2#{C:cry_code} 代码{} 卡牌", + "选择{C:attention}#1#{}张最多", + "{C:attention}#2#{C:cry_code}代码{}卡牌", }, }, p_cry_code_mega_1 = { name = "超级代码包", text = { - "选择 {C:attention}#1#{} 张最多", - "{C:attention}#2#{C:cry_code} 代码{} 卡牌", + "选择{C:attention}#1#{}张最多", + "{C:attention}#2#{C:cry_code}代码{}卡牌", }, }, p_cry_code_normal_1 = { name = "代码补充包", text = { - "选择 {C:attention}#1#{} 张最多", - "{C:attention}#2#{C:cry_code} 代码{} 卡牌", + "选择{C:attention}#1#{}张最多", + "{C:attention}#2#{C:cry_code}代码{}卡牌", }, }, p_cry_code_normal_2 = { name = "代码补充包", text = { - "选择 {C:attention}#1#{} 张最多", - "{C:attention}#2#{C:cry_code} 代码{} 卡牌", + "选择{C:attention}#1#{}张最多", + "{C:attention}#2#{C:cry_code}代码{}卡牌", }, }, p_cry_empowered = { name = "究极幻灵包", text = { - "选择 {C:attention}#1#{} 张,最多", - "{C:attention}#2#{C:spectral} 幻灵{}牌", + "选择{C:attention}#1#{}张,最多", + "{C:attention}#2#{C:spectral}幻灵{}牌", "{s:0.8,C:inactive}(由强化标签生成)", }, }, p_cry_meme_1 = { name = "玩梗包1", text = { - "选择 {C:attention}#1#{} 张,最多", - "可达 {C:attention}#2# 张玩梗的小丑{}", + "选择{C:attention}#1#{}张,最多", + "可达{C:attention}#2#张玩梗的小丑{}", }, }, p_cry_meme_three = { name = "玩梗包3", text = { - "选择 {C:attention}#1#{} 张,最多", - "可达 {C:attention}#2# 张玩梗的小丑{}", + "选择{C:attention}#1#{}张,最多", + "可达{C:attention}#2#张玩梗的小丑{}", }, }, p_cry_meme_two = { name = "玩梗包2", text = { - "选择 {C:attention}#1#{} 张,最多", - "可达 {C:attention}#2# 张玩梗的小丑{}", + "选择{C:attention}#1#{}张,最多", + "可达{C:attention}#2#张玩梗的小丑{}", }, }, undiscovered_code = { @@ -2758,7 +3704,7 @@ return { c_cry_Kaikki = { name = "Kaikki", text = { - "({V:1}等级.#4#{})({V:2}等级.#5#{})({V:3}等级.#6#{})", + "({V:1}等级#4#{})({V:2}等级#5#{})({V:3}等级#6#{})", "升级", "{C:attention}#1#{},", "{C:attention}#2#{},", @@ -2769,7 +3715,7 @@ return { c_cry_Klubi = { name = "Klubi", text = { - "({V:1}等级.#4#{})({V:2}等级.#5#{})({V:3}等级.#6#{})", + "({V:1}等级#4#{})({V:2}等级#5#{})({V:3}等级#6#{})", "升级", "{C:attention}#1#{},", "{C:attention}#2#{},", @@ -2780,7 +3726,7 @@ return { c_cry_Lapio = { name = "Lapio", text = { - "({V:1}等级.#4#{})({V:2}等级.#5#{})({V:3}等级.#6#{})", + "({V:1}等级#4#{})({V:2}等级#5#{})({V:3}等级#6#{})", "升级", "{C:attention}#1#{},", "{C:attention}#2#{},", @@ -2791,7 +3737,7 @@ return { c_cry_Sydan = { name = "Sydan", text = { - "({V:1}等级.#4#{})({V:2}等级.#5#{})({V:3}等级.#6#{})", + "({V:1}等级#4#{})({V:2}等级#5#{})({V:3}等级#6#{})", "升级", "{C:attention}#1#{},", "{C:attention}#2#{},", @@ -2799,10 +3745,10 @@ return { "(芬兰语Heart)", }, }, - c_cry_Timantti = { - name = "Timantti", + c_cry_Timantii = { + name = "Timantii", text = { - "({V:1}等级.#4#{})({V:2}等级.#5#{})({V:3}等级.#6#{})", + "({V:1}等级#4#{})({V:2}等级#5#{})({V:3}等级#6#{})", "升级", "{C:attention}#1#{},", "{C:attention}#2#{},", @@ -2813,7 +3759,7 @@ return { c_cry_asteroidbelt = { name = "小行星带", text = { - "{S:0.8}({S:0.8,V:1}等级.#1#{S:0.8}){} 升级", + "{S:0.8}({S:0.8,V:1}等级#1#{S:0.8}){} 升级", "{C:attention}#2#", "{C:mult}+#3#{} 倍率和", "{C:chips}+#4#{} 筹码", @@ -2822,7 +3768,7 @@ return { c_cry_marsmoons = { name = "火卫一和土卫二", text = { - "{S:0.8}({S:0.8,V:1}等级.#1#{S:0.8}){} 升级", + "{S:0.8}({S:0.8,V:1}等级#1#{S:0.8}){} 升级", "{C:attention}#2#", "{C:mult}+#3#{} 倍率和", "{C:chips}+#4#{} 筹码", @@ -2837,6 +3783,15 @@ return { "{C:inactive}(当前{C:attention} #1#{C:inactive}){}", }, }, + c_cry_nibiru = { + name = "尼比鲁", + text = { + "{S:0.8}({S:0.8,V:1}等级#1#{S:0.8}){} 升级", + "{C:attention}#2#", + "{C:mult}+#3#{} 倍率和", + "{C:chips}+#4#{} 筹码", + }, + }, c_cry_planetlua = { name = "星球.lua", text = { @@ -2848,7 +3803,7 @@ return { c_cry_universe = { name = "TM的整个宇宙!", text = { - "{S:0.8}({S:0.8,V:1}等级.#1#{S:0.8}){} 升级", + "{S:0.8}({S:0.8,V:1}等级#1#{S:0.8}){} 升级", "{C:attention}#2#", "{C:mult}+#3#{} 倍率和", "{C:chips}+#4#{} 筹码", @@ -2857,16 +3812,27 @@ return { c_cry_void = { name = "虚空", text = { - "{S:0.8}({S:0.8,V:1}等级.#1#{S:0.8}){} 升级", + "{S:0.8}({S:0.8,V:1}等级#1#{S:0.8}){} 升级", "{C:attention}#2#", "{C:mult}+#3#{} 倍率和", "{C:chips}+#4#{} 筹码", }, }, + c_cry_voxel = { + name = "Voxel", + text = { + "({V:1}等级#4#{})({V:2}等级#5#{})({V:3}等级#6#{})", + "升级", + "{C:attention}#1#{},", + "{C:attention}#2#{},", + "以及{C:attention}#3#{}", + "{C:inactive,S:0.8}(译者注:升级的为{C:cry_code}://声明{}创建的牌型)", + }, + }, c_cry_sunplanet = { name = "太阳", text = { - "{S:0.8}({S:0.8,V:1}等级.#1#{S:0.8}){}", + "{S:0.8}({S:0.8,V:1}等级#1#{S:0.8}){}", "使{C:attention}晋升{}牌型的指数", "增加{X:gold,C:white}#2#{}", "{C:inactive}(目前指数 {X:gold,C:white}X(#3#^晋升数){C:inactive})", @@ -2874,10 +3840,32 @@ return { }, }, Sleeve = { + sleeve_cry_beige_sleeve = { + name = "四重牌套", + text = { + "{C:attention}普通{}小丑具有", + "{C:attention}四倍{}的效果", + }, + }, + sleeve_cry_beige_sleeve_alt = { + name = "四重牌套", + text = { + "{C:attention}罕见{}小丑具有", + "{C:attention}四倍{}的效果", + }, + }, + sleeve_cry_beta_sleeve = { + name = "怀旧牌套", + text = { + "{C:attention}小丑牌槽{}和{C:attention}消耗牌槽{}", + "{C:attention}合并", + "boss底注被替换为它们的怀旧版本", + }, + }, sleeve_cry_bountiful_sleeve = { name = "丰饶牌套", text = { - "每次{C:attention}出牌{} 或 {C:attention}弃牌{}后", + "每次{C:attention}出牌{}或{C:attention}弃牌{}后", "固定抽五张牌", }, }, @@ -2885,32 +3873,32 @@ return { name = "CCD 牌套", text = { "每张卡牌也是", - "一张 {C:attention}随机{} 消耗牌", + "一张{C:attention}随机{}消耗牌", }, }, sleeve_cry_conveyor_sleeve = { name = "传送带牌套", text = { - "{C:attention}不能{} 移动小丑卡", - "回合开始时,", - "{C:attention}复制{} 最右边的小丑卡", - "并且 {C:attention}销毁{} 最左边的小丑卡", + "{C:attention}不能{}移动小丑卡", + "回合开始时", + "{C:attention}复制{}最右边的小丑卡", + "并且{C:attention}销毁{}最左边的小丑卡", }, }, sleeve_cry_critical_sleeve = { name = "暴击牌套", text = { - "每打出一手牌后,", - "{C:green}四分之一{} 的几率获得 {X:dark_edition,C:white} ^2 {} 倍", - "{C:green}八分之一{} 的几率获得 {X:dark_edition,C:white} ^0.5 {} 倍", + "每打出一手牌后", + "{C:green}1/4{}几率获得{X:dark_edition,C:white} ^2 {}倍率", + "{C:green}1/8{}几率获得{X:dark_edition,C:white} ^0.5 {}倍率", }, }, sleeve_cry_encoded_sleeve = { name = "编码牌套", text = { - "开始时获得一张 {C:cry_code,T:j_cry_CodeJoker}代码小丑卡{}", - "和一张 {C:cry_code,T:j_cry_copypaste}复制/粘贴卡{}", - "商店中只出现 {C:cry_code}代码牌{}", + "开始时获得一张{C:cry_code,T:j_cry_curse_sob}代码小丑卡{}", + "和一张{C:cry_code,T:j_cry_copypaste}复制/粘贴{}", + "商店中只出现{C:cry_code}代码牌{}", }, }, sleeve_cry_equilibrium_sleeve = { @@ -2922,17 +3910,26 @@ return { "{C:attention,T:v_overstock_plus}+2 商店栏位", }, }, + sleeve_cry_glowing_sleeve = { + name = "发光牌组", + text = { + "在击败Boss盲注时", + "所有小丑牌的数值乘以{X:dark_edition,C:white}X1.25{}", + "{X:cry_jolly,C:white,s:0.8} Jolly#1#Open#1#Winner#1#-#1#wawa#1#person", + }, + }, + sleeve_cry_infinite_sleeve = { name = "无限牌套", text = { - "你可以选择 {C:attention}任意数量", + "你可以选择{C:attention}任意数量", "的卡牌", }, }, sleeve_cry_legendary_sleeve = { name = "传奇牌套", text = { - "以一张 {C:legendary}传奇{C:legendary} 小丑牌开始", + "以一张{C:legendary}传奇{C:legendary}小丑牌开始", "击败Boss盲注后", "{C:green}1 / 5{} 几率创建另外一张", "{C:inactive}(必须有空间){}", @@ -2942,31 +3939,53 @@ return { name = "错印牌套", text = { "卡牌的数值", - "是 {C:attention}随机{} 的", + "是{C:attention}随机{}的", }, }, sleeve_cry_redeemed_sleeve = { name = "赎回牌套", text = { - "当购买{C:attention}优惠券{} 时,", - "会获得对应 {C:attention}高级{} 版", + "当购买{C:attention}优惠券{}时", + "会获得对应{C:attention}高级{}版", }, }, sleeve_cry_spooky_sleeve = { name = "万圣节牌套", text = { - "以一张{C:eternal}永恒{} {C:attention,T:j_cry_chocolate_dice}巧克力骰{}开始", - "每次{C:attention}底注{}之后 ", - "创建一个{C:cry_candy}糖果{}或 {X:cry_cursed,C:white}诅咒{}", + "以一张{C:eternal}永恒{}{C:attention,T:j_cry_chocolate_dice}巧克力骰{}开始", + "每个{C:attention}底注{}结束后,", + "创建一个{C:cry_candy}糖果{}或{X:cry_cursed,C:white}诅咒{}", + }, + }, + sleeve_cry_very_fair_sleeve = { + name = "超平衡的牌组", + text = { + "每回合{C:blue}-2{}手牌,{C:red}-2{}弃牌", + "{C:attention}优惠券{}不再出现在商店中", }, }, sleeve_cry_wormhole_sleeve = { name = "虫洞牌套", text = { - "开始时获得一张 {C:cry_exotic}域外{C:attention} 小丑卡", - "小丑卡 {C:attention}20倍{} 更有可能", - "成为 {C:dark_edition}负片{} 卡", - "{C:attention}-2{} 小丑卡插槽", + "开始时获得一张{C:cry_exotic}域外{C:attention}小丑卡", + "小丑牌{C:attention}20倍{}更有可能成为{C:dark_edition}负片{}", + "{C:attention}-2{}小丑牌槽位", + }, + }, + sleeve_cry_antimatter_sleeve = { + name = "反物质牌套", + text = { + "拥有{C:attention}所有{}牌套的", + "{C:attention}增益{}和{C:attention}特殊增益{}效果", + "{C:red}WIP", + }, + }, + sleeve_cry_antimatter_sleeve_balanced = { + name = "Antimatter Sleeve", + text = { + "拥有{C:attention}所有{}在{C:gold}金注{}中获胜过的", + "牌组的{C:attention}增益{}和{C:attention}特殊增益{}效果", + "{C:red}WIP", }, }, }, @@ -2974,36 +3993,35 @@ return { c_cry_adversary = { name = "敌手", text = { - "拥有的{C:red}所有{} {C:attention}小丑牌{} 变为 {C:dark_edition}负片{},", + "拥有的{C:red}所有{}{C:attention}小丑牌{}变为{C:dark_edition}负片{},", "本局游戏的小丑牌购买价格{C:red}翻倍{}", }, }, c_cry_analog = { name = "模拟", text = { - "复制 {C:attention}#1#{} 张", - "随机 {C:attention}小丑{}", - "摧毁所有其他小丑,{C:attention}+#2#{} 底注", + "为一个随机{C:attention}小丑{}生成{C:attention}#1#{}张复制", + "摧毁所有其他小丑,{C:attention}+#2#{}底注", }, }, c_cry_chambered = { name = "腔室", text = { - "随机复制 {C:attention}#1#{}张 {C:dark_edition}负片{}版本", + "随机复制{C:attention}#1#{}张{C:dark_edition}负片{}版本", "的{C:attention}持有{}的消耗牌", }, }, c_cry_conduit = { name = "渠道", text = { - "交换两张所选择的小丑或手牌的 {C:attention}版本{}", + "交换两张所选择的小丑或手牌的{C:attention}版本{}", }, }, c_cry_gateway = { name = "真理之门", text = { "生成一张随机的", - "{C:cry_exotic,E:1}域外{C:attention} 小丑{}", + "{C:cry_exotic,E:1}域外{C:attention}小丑{}", "摧毁所有其他小丑", }, }, @@ -3017,16 +4035,16 @@ return { c_cry_lock = { name = "锁定", text = { - "从 {C:red}所有{} 小丑中,", - "移除 {C:red}所有{} 贴纸", - "然后随机给一张小丑牌增加 {C:purple,E:1}永恒{}贴纸", + "从{C:red}所有{}小丑中", + "移除{C:red}所有{}贴纸", + "然后随机给一张小丑牌增加{C:purple,E:1}永恒{}贴纸", }, }, c_cry_pointer = { name = "://指针", text = { "创造一张", - "任选 {C:cry_code}卡牌", + "任选{C:cry_code}卡牌", "{C:inactive,s:0.8}(域外小丑 #1# 排除)", "(输入对应名字)", }, @@ -3035,77 +4053,91 @@ return { name = "复录", text = { "转换所有手牌", - "为一张 {C:attention}随机{}", + "为一张{C:attention}随机{}", "手牌", }, }, c_cry_ritual = { name = "仪典", text = { - "增强 {C:attention}#1#{} 张选定的卡牌", - "为 {C:dark_edition}负片{}, {C:dark_edition}马赛克{}", - "或 {C:dark_edition}星界{} ", + "增强{C:attention}#1#{}张选定的卡牌", + "为{C:dark_edition}负片{}, {C:dark_edition}马赛克{}", + "或{C:dark_edition}星界{}", }, }, c_cry_source = { name = "源码", text = { - "向你手中的", - "{C:attention}#1#{} 选定卡牌", - "添加一个 {C:cry_code}绿色蜡封{}", + "向你手中的{C:attention}#1#{}张选定的牌", + "添加{C:cry_code}绿色蜡封{}", }, }, c_cry_summoning = { name = "召唤", text = { "创造一张随机的", - "{C:cry_epic}史诗{} {C:joker}小丑{},摧毁", - "一张随机 {C:joker}小丑{}", + "{C:cry_epic}史诗{}{C:joker}小丑{},摧毁", + "一张随机{C:joker}小丑{}", }, }, c_cry_trade = { name = "交易", text = { - "{C:attention}失去{} 一张随机优惠券,", - "获得 {C:attention}2{} 张随机优惠券", + "{C:attention}失去{}1张随机优惠券", + "获得{C:attention}2{}张随机优惠券", }, }, c_cry_typhoon = { name = "台风", text = { - "向手中 {C:attention}#1#{} 选择的", - "牌中添加 {C:cry_azure}蔚蓝蜡封{}", + "向你手中的{C:attention}#1#{}张选定的牌", + "添加{C:cry_azure}蔚蓝蜡封{}", + }, + }, + c_cry_meld = { + name = "融合", + text = { + "选择一张{C:attention}小丑{}或", + "{C:attention}扑克牌{}将其变成", + "{C:dark_edition}双面{}", }, }, c_cry_vacuum = { name = "虚空", text = { - "从 {C:red}所有{} 手中的牌,", - "移除 {C:red}所有 {C:green}修改{}", - "每移除一个 {C:green}修改{},获得 {C:money}$#1#{}", + "从{C:red}所有{}手中的牌", + "移除{C:red}所有{C:green}修改{}", + "每移除一个{C:green}修改{},获得{C:money}$#1#{}", "{C:inactive,s:0.7}(例如: 强化、蜡封、版本)", }, }, c_cry_white_hole = { name = "白洞", text = { - "{C:attention}移除{} 所有手牌等级,", - "升级 {C:legendary,E:1}最常用{} 扑克牌型", + "升级{C:legendary,E:1}最常用{}扑克牌型{C:attention}4{}级", + "{C:attention}移除{}所有其他手牌等级", + }, + }, + c_cry_white_hole2 = { + name = "白洞", + text = { + "{C:attention}移除{}所有手牌等级", + "升级{C:legendary,E:1}最常用{}扑克牌型", "每移除1级,最常用牌型升{C:attention}3{}级", }, }, }, Stake = { stake_cry_amber = { - colour = "Amber", + colour = "琥珀", name = "琥珀注", text = { - "商店的{C:attention}补充包-1{} ", + "商店的{C:attention}补充包-1{}", "{s:0.8,C:inactive}之前所有赌注也都起效{}", }, }, stake_cry_ascendant = { - colour = "Ascendant", + colour = "飞升", name = "飞升注", text = { "商店栏位{C:attention}-1{}", @@ -3113,7 +4145,7 @@ return { }, }, stake_cry_azure = { - colour = "Azure", + colour = "蔚蓝", name = "蔚蓝注", text = { "所有小丑牌的数值降低", @@ -3122,59 +4154,58 @@ return { }, }, stake_cry_blossom = { - colour = "Blossom", + colour = "花锦", name = "花锦注", text = { "{C:attention}最终{}Boss版盲注可以出现在", "{C:attention}任何{}底注中", "{s:0.8,C:inactive}之前所有赌注也都起效{}", - "", }, }, stake_cry_bronze = { - colour = "Bronze", + colour = "青铜", name = "青铜注", text = { - "优惠券价格增加 {C:attention}50%{}", + "优惠券价格增加{C:attention}50%{}", "{s:0.8,C:inactive}之前所有赌注也都起效{}", }, }, stake_cry_brown = { - colour = "Brown", + colour = "棕色", name = "棕色注", text = { - "所有的 {C:attention}贴纸(如永恒,易腐,租赁){} 互相兼容", + "所有的{C:attention}贴纸(如永恒,易腐,租赁){}互相兼容", "{s:0.8,C:inactive}之前所有赌注也都起效{}", }, }, stake_cry_crimson = { - colour = "Crimson", + colour = "猩红", name = "猩红注", text = { - "优惠券只会在 {C:attention}双数{} 底注 时刷新", + "优惠券只会在{C:attention}双数{}底注时刷新", "{s:0.8,C:inactive}之前所有赌注也都起效{}", }, }, stake_cry_cyan = { - colour = "Cyan", + colour = "靛青", name = "靛青注", text = { - "{C:green}罕见的{} 和 {C:red}稀有的{} 小丑牌出现概率", - "减少", + "{C:green}罕见{}和{C:red}稀有{}小丑牌出现", + "概率降低", "{s:0.8,C:inactive}之前所有赌注也都起效{}", }, }, stake_cry_dawn = { - colour = "Dawn", + colour = "黎明", name = "黎明注", text = { - "塔罗牌和幻灵牌的选择目标 {C:attention}减 1{}", + "塔罗牌和幻灵牌的选择目标{C:attention}减 1{}", "{s:0.8,C:inactive}(最少 1 张){}", "{s:0.8,C:inactive}之前所有赌注也都起效{}", }, }, stake_cry_diamond = { - colour = "Diamond", + colour = "钻石", name = "钻石注", text = { "获胜的底注变成{C:attention}10{}", @@ -3182,7 +4213,7 @@ return { }, }, stake_cry_ember = { - colour = "Ember", + colour = "余烬", name = "余烬注", text = { "所有卡牌出售时不再产生金钱", @@ -3190,65 +4221,65 @@ return { }, }, stake_cry_emerald = { - colour = "Emerald", + colour = "翡翠", name = "翡翠注", text = { - "卡牌、包和优惠券可以是 {C:attention}面朝下{} 的", + "卡牌、包和优惠券可以是{C:attention}面朝下{}的", "{s:0.8,C:inactive}(购买前无法查看)", "{s:0.8,C:inactive}之前所有赌注也都起效{}", }, }, stake_cry_glass = { - colour = "Glass", + colour = "玻璃", name = "玻璃注", text = { - "卡牌在得分时可能会被 {C:attention}摧毁", + "卡牌在得分时可能会被{C:attention}摧毁", "{}{s:0.8,C:inactive}之前所有赌注也都起效{}", }, }, stake_cry_gray = { - colour = "Gray", + colour = "灰色", name = "灰色注", text = { - "重新投掷的费用每次增加 {C:attention}$2{}", + "重新投掷的费用每次增加{C:attention}$2{}", "{s:0.8,C:inactive}之前所有赌注也都起效{}", }, }, stake_cry_horizon = { - colour = "Horizon", + colour = "地平线", name = "地平线注", text = { "选择盲注时,增加一张", - "{C:attention}随机卡牌{} 到牌堆", + "{C:attention}随机卡牌{}到牌堆", " {s:0.8,C:inactive}之前所有赌注也都起效{}", }, }, stake_cry_jade = { - colour = "Jade", + colour = "碧玉", name = "碧玉注", text = { - "抽取手牌时有概率是 {C:attention}面朝下{} 的", + "抽取手牌时有概率是{C:attention}面朝下{}的", "{s:0.8,C:inactive}之前所有赌注也都起效{}", }, }, stake_cry_pink = { - colour = "Pink", + colour = "粉红", name = "粉红注", text = { - " {C:attention}底注 {}提升时,过关需求分数再次增速", + "{C:attention}底注{}提升时,过关需求分数再次增速", "{s:0.8,C:inactive}之前所有赌注也都起效{}", }, }, stake_cry_platinum = { - colour = "Platinum", + colour = "铂金", name = "铂金注", text = { - "小盲注 {C:attention}不会出现{}", + "小盲注{C:attention}不会出现{}", "{s:0.8,C:inactive}之前所有赌注也都起效{}", }, }, stake_cry_quartz = { - colour = "Quartz", + colour = "石英", name = "石英注", text = { "商店有可能出现{C:attention}固定{}小丑牌", @@ -3257,25 +4288,25 @@ return { }, }, stake_cry_ruby = { - colour = "Ruby", + colour = "红玉", name = "红玉注", text = { - "{C:attention}大{} 盲注有可能变为", - "{C:attention}Boss{} 盲注", + "{C:attention}大{}盲注有可能变为", + "{C:attention}Boss{}盲注", "{s:0.8,C:inactive}之前所有赌注也都起效{}", }, }, stake_cry_sapphire = { - colour = "Sapphire", + colour = "蓝晶", name = "蓝晶注", text = { - "在 底注 结束时,失去当前总资金的 {C:attention}25%{} ", - "{s:0.8,C:inactive}(最高失去至 $10)", + "在底注结束时,失去当前总资金的{C:attention}25%{}", + "{s:0.8,C:inactive}(最高失去至$10)", "{s:0.8,C:inactive}之前所有赌注也都起效{}", }, }, stake_cry_twilight = { - colour = "Twilight", + colour = "暮光", name = "暮光注", text = { "商店有可能出现{C:attention}香蕉{}小丑牌", @@ -3284,15 +4315,15 @@ return { }, }, stake_cry_verdant = { - colour = "Verdant", + colour = "翠绿", name = "翠绿注", text = { - "所需分数会随每个 {C:attention}底注加速增加", + "所需分数会随每个{C:attention}底注加速增加", "{s:0.8,C:inactive}之前所有赌注也都起效{}", }, }, stake_cry_yellow = { - colour = "Yellow", + colour = "灿黄", name = "灿黄注", text = { "{C:attention}永恒,易腐,租赁等贴纸{}", @@ -3306,7 +4337,7 @@ return { name = "星界标签", text = { "下一张在商店里的小丑", - "增加 {C:dark_edition}星界版本{}并且免费", + "增加{C:dark_edition}星界版本{}并且免费", }, }, tag_cry_banana = { @@ -3325,7 +4356,7 @@ return { tag_cry_bettertop_up = { name = "进阶充值标签", text = { - "创造 {C:attention}#1#张{C:green}罕见{}小丑", + "创造{C:attention}#1#张{C:green}罕见{}小丑", "{C:inactive}(必须有空间){}", }, }, @@ -3339,16 +4370,16 @@ return { tag_cry_booster = { name = "增强包标签", text = { - "下一个 {C:cry_code}增强包{} 有", - "{C:attention}双倍{} 卡牌数量", - "{C:attention}双倍{} 选择次数", + "下一个{C:cry_code}增强包{}有", + "{C:attention}双倍{}卡牌数量", + "{C:attention}双倍{}选择次数", }, }, tag_cry_bundle = { name = "组合标签", text = { - "创造一个 {C:attention}标准标签{},{C:tarot}吊饰标签{},", - "{C:attention}小丑标签{},和 {C:planet}流星标签", + "创造一个{C:attention}标准标签{},{C:tarot}吊饰标签{}", + "{C:attention}小丑标签{},和{C:planet}流星标签", }, }, tag_cry_cat = { @@ -3365,17 +4396,24 @@ return { "{C:cry_code}代码包", }, }, + tag_cry_clone = { + name = "克隆标签", + text = { + "商店物品价格为原来的{C:attention}X#1#{}倍", + "获得下一张购买卡牌的{C:attention}复制{}", + }, + }, tag_cry_double_m = { name = "M标签", text = { - "商店增加一张 {C:legendary}M系列小丑{}", + "商店增加一张{C:legendary}M系列小丑{}", }, }, tag_cry_empowered = { name = "强化标签", text = { - "给予一个 {C:spectral}究极幻灵{} 包", - "包括 {C:legendary,E:1}灵魂{} 和 {C:cry_exotic,E:1}传送门{}", + "给予一个{C:spectral}究极幻灵{}包", + "包括{C:legendary,E:1}灵魂{}和{C:cry_exotic,E:1}真理之门{}", }, }, tag_cry_epic = { @@ -3389,14 +4427,14 @@ return { name = "赌徒标签", text = { "{C:green}#1# / #2#{} 的几率", - "创造一个 {C:cry_exotic,E:1}强化{} 标签", + "创造一个{C:cry_exotic,E:1}强化{}标签", }, }, tag_cry_glass = { name = "琉璃标签", text = { "下一张在商店里的小丑", - "增加 {C:dark_edition}灰质琉璃{}版本并且免费", + "增加{C:dark_edition}灰质琉璃{}版本并且免费", }, }, tag_cry_glitched = { @@ -3410,7 +4448,7 @@ return { name = "鎏金标签", text = { "下一张在商店里的小丑", - "增加 {C:dark_edition}鎏金版本{}并且免费", + "增加{C:dark_edition}鎏金版本{}并且免费", }, }, tag_cry_gourmand = { @@ -3427,18 +4465,25 @@ return { "的{C:cry_ascendant}玩梗{}包", }, }, + tag_cry_lens = { + name = "透镜标签", + text = { + "将{C:dark_edition}负片{}效果", + "添加至{C:attention}#1#{}个随机消耗牌上", + }, + }, tag_cry_m = { name = "欢愉~标签", text = { "下一张在商店里的小丑", - "增加 {C:dark_edition}欢愉{}版本并且免费", + "增加{C:dark_edition}欢愉{}版本并且免费", }, }, tag_cry_memory = { name = "记忆标签", text = { - "创造 {C:attention}#1#{} 份", - "本局游戏上一次使用的 {C:attention}标签{}", + "创造{C:attention}#1#{}份", + "本局游戏上一次使用的{C:attention}标签{}", "{s:0.8,C:inactive}复制类标签除外", "{s:0.8,C:inactive}当前: {s:0.8,C:attention}#2#", }, @@ -3447,29 +4492,36 @@ return { name = "马赛克标签", text = { "下一张在商店里的小丑", - "增加 {C:dark_edition}马赛克版本{}并且免费", + "增加{C:dark_edition}马赛克版本{}并且免费", }, }, tag_cry_oversat = { name = "过曝标签", text = { "下一张在商店里的小丑", - "增加 {C:dark_edition}过曝版本{}并且免费", + "增加{C:dark_edition}过曝版本{}并且免费", + }, + }, + tag_cry_palette_cleanser = { + name = "清洁标签", + text = { + "从{C:attention}随机{}一个小丑或扑克牌上", + "移除一个{C:attention}随机{}贴纸", }, }, tag_cry_quadruple = { name = "四方标签", text = { - "给予 {C:attention}#1#{} 份", - "下一个选择的 {C:attention}标签", + "给予{C:attention}#1#{}份", + "下一个选择的{C:attention}标签", "{s:0.8,C:inactive}复制类标签除外", }, }, tag_cry_quintuple = { name = "五重标签", text = { - "给予 {C:attention}#1#{} 份", - "下一个选择的 {C:attention}标签", + "给予{C:attention}#1#{}份", + "下一个选择的{C:attention}标签", "{s:0.8,C:inactive}复制类标签除外", }, }, @@ -3477,14 +4529,14 @@ return { name = "重制标签", text = { "商店有一张", - "{C:dark_edition}#1# {C:cry_code}#2#", + "{C:dark_edition}#1#{C:cry_code}#2#", }, }, tag_cry_schematic = { name = "原理图标签", text = { "下个商店有一张", - "{C:attention}头脑风暴{} ", + "{C:attention}头脑风暴{}", }, }, tag_cry_scope = { @@ -3497,8 +4549,8 @@ return { tag_cry_triple = { name = "三连标签", text = { - "给予 {C:attention}#1#{} 份", - "下一个选择的 {C:attention}标签", + "给予{C:attention}#1#{}份", + "下一个选择的{C:attention}标签", "{s:0.8,C:inactive}复制类标签除外", }, }, @@ -3507,39 +4559,38 @@ return { c_cry_automaton = { name = "机械人", text = { - "创造 {C:attention}#1#", - "随机 {C:cry_code}代码{} 卡", + "创造{C:attention}#1#", + "随机{C:cry_code}代码{}卡", "{C:inactive}(必须有空间)", }, }, c_cry_eclipse = { name = "日食", text = { - "增强 {C:attention}#1#{} 张选定的卡牌", - "为 {C:attention}回响卡", + "增强{C:attention}#1#{}张选定的卡牌", + "为{C:attention}回响卡", }, }, - c_cry_meld = { - name = "融合", + c_cry_instability = { + name = "不稳定性", text = { - "选择一张 {C:attention}小丑{} 或", - "{C:attention}扑克牌{} 将其变成", - "{C:dark_edition}双面{} ", + "将{C:attention}#1#{}张选定卡牌", + "增强为{C:attention}抽象牌", }, }, c_cry_theblessing = { name = "祝福", text = { - "创造 {C:attention}1{}", - "随机 {C:attention}消耗牌{}", + "创造{C:attention}1{}", + "随机{C:attention}消耗牌{}", "{C:inactive}(必须有空间){}", }, }, c_cry_seraph = { name = "六翼天使", text = { - "增强 {C:attention}#1#{} 张选定的手牌", - "为 {C:attention}明亮牌", + "增强{C:attention}#1#{}张选定的手牌", + "为{C:attention}明亮牌", }, }, }, @@ -3547,7 +4598,7 @@ return { c_cry_potion = { name = "魔药", text = { - "使用后获取一种未知的 ", + "使用后获取一种未知的", "{C:attention}魔力{}", "{C:inactive,s:0.7}从巧克力骰子中获取", }, @@ -3557,13 +4608,21 @@ return { v_cry_asteroglyph = { name = "星象文字", text = { - "设置底注为 {C:attention}#1#{}", + "设置底注为{C:attention}#1#{}", + }, + unlock = { + "到达底注", + "{C:attention}36", }, }, v_cry_blankcanvas = { name = "空白画布", text = { - "{C:attention}+#1#{} 手牌上限", + "{C:attention}+#1#{}手牌上限", + }, + unlock = { + "将你的{C:attention}手牌上限", + "降至{C:attention}0", }, }, v_cry_clone_machine = { @@ -3571,13 +4630,13 @@ return { text = { "双倍标签变成", "{C:attention}五重标签{},并且", - " {C:attention}4X{} 常见", + " {C:attention}4X{}常见", }, }, v_cry_command_prompt = { name = "命令提示符", text = { - "{C:cry_code}代码{} 牌可以", + "{C:cry_code}代码{}牌可以", "出现在 {C:attention}商店{}", }, }, @@ -3586,34 +4645,43 @@ return { text = { "双倍标签变成", "{C:attention}三连标签{},并且", - "是 {C:attention}2X{} 常见", + "是 {C:attention}2X{}常见", }, }, v_cry_curate = { name = "策展", text = { "所有牌出现时均", - "带有 {C:dark_edition}版本{}", + "带有{C:dark_edition}版本{}", + }, + unlock = { + "发现所有", + "{C:attention}版本", }, }, v_cry_dexterity = { name = "灵巧", text = { "永久", - "每回合获得 {C:blue}+#1#{} 手牌", + "每回合获得{C:blue}+#1#{}出牌", + }, + unlock = { + "累计打出", + "{C:attention}5000张{}", + "{C:attention}扑克牌{}", }, }, v_cry_double_down = { name = "双倍下注", text = { - "每轮之后,", - " {C:dark_edition}双面{} 牌背面的所有数值 {X:dark_edition,C:white} X1.5 {}", + "每轮之后", + " {C:dark_edition}双面{}牌背面的所有数值{X:dark_edition,C:white} X1.5 {}", }, }, v_cry_double_slit = { name = "成对裂隙", text = { - "{C:attention}融合{} 可以", + "{C:attention}融合{}可以", "出现在商店和", "秘术包中", }, @@ -3621,20 +4689,24 @@ return { v_cry_double_vision = { name = "重影", text = { - "{C:dark_edition}双面{} 牌出现", - "{C:attention}4X{} 更频繁", + "{C:dark_edition}双面{}牌出现", + "{C:attention}4X{}更频繁", }, }, v_cry_fabric = { name = "宇宙结构", text = { - "{C:dark_edition}+#1#{} 小丑槽", + "{C:dark_edition}+#1#{}小丑槽", + }, + unlock = { + "累计兑换{C:dark_edition}反物质{}优惠券", + "{C:attention}10次{}", }, }, v_cry_grapplinghook = { name = "抓钩", text = { - "{C:attention}+#1#{} 牌", + "{C:attention}+#1#{}牌", "选择限制", "{C:inactive,s:0.7}你可以用它做很多事情,比你想象的要多得多。{}", }, @@ -3642,7 +4714,7 @@ return { v_cry_hyperspacetether = { name = "超时空钩锁", text = { - "{C:attention}+#1#{} 牌", + "{C:attention}+#1#{}牌", "选择限制", "{C:inactive,s:0.7}注意:未来会有额外的{}", "{C:inactive,s:0.7}功能{}", @@ -3654,30 +4726,48 @@ return { "商店中的所有牌和包", "费用为 {C:attention}$1{}", }, + unlock = { + "在一局中", + "兑换{C:attention}25个{}", + "{C:attention}优惠券", + }, }, v_cry_moneybean = { name = "金钱魔豆", text = { "提高每轮获得的", - "利息上限至 {C:money}$#1#{}", + "利息上限至{C:money}$#1#{}", + }, + unlock = { + "在{C:attention}一整局中{}", + "达到{C:attention}利息收益{}上限", }, }, v_cry_overstock_multi = { name = "多重库存", text = { - "{C:attention}+#1#{} 卡槽和", - "{C:attention}+#1#{} 补充包槽", + "{C:attention}+#1#{}卡槽和", + "{C:attention}+#1#{}补充包槽", "在商店中可用", }, + unlock = { + "在一局中", + "在商店花费{C:attention}1000$", + }, }, v_cry_pacclimator = { name = "星球适应器", text = { - "{C:planet}星球{} 牌出现的概率", - "{C:attention}X#1#{} ", + "{C:planet}星球{}牌出现的概率", + "{C:attention}X#1#{}", "购买此优惠券后本赛局所有", "{C:planet}星球{}牌都{C:green}免费{}", }, + unlock = { + "在商店中", + "累计购买{C:attention}100张{}", + "{C:planet}星球{}牌", + }, }, v_cry_pairamount_plus = { name = "至高山巅", @@ -3689,35 +4779,40 @@ return { v_cry_pairing = { name = "配对", text = { - "{C:attention}重新触发{} 所有 M 小丑", - "如果出牌是 {C:attention}一对", + "{C:attention}重新触发{}所有 M 小丑", + "如果出牌是{C:attention}对子", }, }, v_cry_quantum_computing = { name = "量子计算", text = { - "{C:cry_code}代码{} 牌生成时概率", - "带有 {C:dark_edition}负片{} 版本", + "{C:cry_code}代码{}牌生成时概率", + "带有{C:dark_edition}负片{}版本", }, }, v_cry_repair_man = { name = "修理工", text = { - "{C:attention}重新触发{} 所有 M 小丑", - "如果出牌包含 {C:attention}一对", + "{C:attention}重新触发{}所有 M 小丑", + "如果出牌包含{C:attention}对子", }, }, v_cry_rerollexchange = { name = "重掷交换", text = { "所有重掷", - "费用 {C:attention}$2{}", + "费用{C:attention}$2{}", + }, + unlock = { + "在一局中", + "{C:attention}重掷{}商店", + "共计{C:attention}250次{}", }, }, v_cry_satellite_uplink = { name = "卫星串联", text = { - "{C:cry_code}代码{} 牌可能", + "{C:cry_code}代码{}牌可能", "出现在任何", "{C:attention}天体包{}中", }, @@ -3725,8 +4820,8 @@ return { v_cry_scope = { name = "银河望远镜", text = { - "为出牌创造 {C:planet}星球", - "{C:attention}牌型{}", + "为出牌{C:attention}牌型{}", + "创造对应{C:planet}星球牌{}", "{C:inactive}(必须有空间){}", }, }, @@ -3734,31 +4829,41 @@ return { name = "粘粘手", text = { "选择限制", - "{C:attention}+#1#{} 牌", + "{C:attention}+#1#{}牌", }, }, v_cry_tacclimator = { name = "塔罗适应器", text = { - "{C:tarot}塔罗{} 牌出现的概率", - "{C:attention}X#1#{} ", + "{C:tarot}塔罗{}牌出现的概率", + "{C:attention}X#1#{}", "购买此优惠券后本赛局所有", "{C:tarot}塔罗{}牌都{C:green}免费{}", }, + unlock = { + "在商店中", + "累计购买{C:attention}100张{}", + "{C:tarot}塔罗{}牌", + }, }, v_cry_tag_printer = { name = "标签打印机", text = { "双倍标签变成", "{C:attention}四方标签{},并且", - " {C:attention}3X{} 常见", + " {C:attention}3X{}常见", }, }, v_cry_threers = { name = "读,写,算", text = { "永久", - "每回合获得 {C:red}+#1#{} 弃牌", + "每回合获得{C:red}+#1#{}弃牌", + }, + unlock = { + "累计弃掉", + "{C:attention}5000张{}", + "{C:attention}扑克牌{}", }, }, }, @@ -3767,7 +4872,7 @@ return { achievement_descriptions = { ach_cry_ace_in_crash = "check_for_unlock({type = ace_in_crash})", ach_cry_blurred_blurred_joker = "获得模糊的模糊小丑", - ach_cry_break_infinity = "在次出牌中获得1.79e308筹码", + ach_cry_break_infinity = "在单次出牌中获得1.79e308筹码", ach_cry_bullet_hell = "拥有15个AP小丑", ach_cry_cryptid_the_cryptid = "用神秘生物复制神秘生物", ach_cry_exodia = "拥有5个域外小丑", @@ -3778,7 +4883,7 @@ return { ach_cry_jokes_on_you = "在底注 1上触发笑料boss的效果并赢得比赛", ach_cry_niw_uoy = "达到底注 -8", ach_cry_now_the_fun_begins = "获得画布", - ach_cry_patience_virtue = "在打出第一手牌之前等待薰衣草环 2分钟并击败盲注", + ach_cry_patience_virtue = "在打出第一手牌之前等待薰衣草环2分钟并击败盲注", ach_cry_perfectly_balanced = "使用超平衡牌组击败飞升注", ach_cry_pull_request = "让 ://提交 生成它摧毁的相同小丑", ach_cry_traffic_jam = "击败所有高峰时段挑战", @@ -3826,9 +4931,13 @@ return { b_flip = "翻转", b_merge = "融合", b_pull = "拉取", + b_reset_gameset_modest = "重设游戏集设置(Modest)", + b_reset_gameset_mainline = "重设游戏集设置(Mainline)", + b_reset_gameset_madness = "重设游戏集设置(Madness)", b_unique_cards = "独特牌", cry_active = "激活", cry_again_q = "再来?", + cry_circus_generic = "{V:#1#}#2#{}每个小丑给予{X:mult,C:white} X#3# {}倍率", cry_code_apply = "应用", cry_code_apply_previous = "应用之前的", cry_code_cancel = "取消", @@ -3836,7 +4945,10 @@ return { cry_code_create_previous = "创建之前的", cry_code_enh = "输入增强", cry_code_enter_card = "输入一张牌", + cry_code_enter_hand = "输入扑克牌型", + cry_code_empty = "[声明手牌]", cry_code_execute = "执行", + cry_code_exit = "离开", cry_code_exploit = "利用", cry_code_exploit_previous = "利用之前的", cry_code_hand = "输入扑克手牌", @@ -3876,6 +4988,14 @@ return { cry_feat_tags = "标签", ["cry_feat_timer mechanics"] = "计时器机制", cry_feat_vouchers = "优惠券", + cry_gameset_explanation = { + "选择游戏集配置选项以应用于此卡。", + }, + cry_gameset_disabled = "已禁用", + cry_gameset_exp = "实验性内容", + cry_gameset_exp_modest = "实验性内容(Modest)", + cry_gameset_exp_mainline = "实验性内容(Mainline)", + cry_gameset_exp_madness = "实验性内容(Madness)", cry_gaming = "游戏中", cry_gaming_ex = "开赌!", cry_good_luck_ex = "祝你好运!", @@ -3911,7 +5031,14 @@ return { cry_sobbing = "救救我...", cry_sus_ex = "骗子!", cry_unredeemed = "Unredeemed...", + cry_view_set_contents = "查看集合中的项目", + cry_code_antevoucher = "接下来的Boss盲注和优惠券", + cry_code_nextjokers = "下一个商店的小丑", + cry_code_nextcards = "接下来抽到的牌", + cry_code_with_suits = "包括花色", + cry_code_without_suits = "忽略花色", k_code = "代码", + k_chips = "筹码", k_cry_candy = "糖果", k_cry_cursed = "诅咒", k_cry_epic = "史诗", @@ -3954,24 +5081,94 @@ return { k_cry_exotic = "域外", unique = "独特", }, + tutorial = { + cry_intro_1 = { + "你好,我是{C:attention}约瑟夫·J·小丑{}!", + "欢迎来到{C:cry_exotic,E:1}Cryptid{}!", + }, + cry_intro_2 = { + "看起来你从未在这个存档中", + "玩过{C:cry_exotic,E:1}Cryptid{}。", + "让我来告诉你怎么玩!", + }, + cry_intro_3 = { + "*长出双手*", + }, + cry_intro_4 = { + "用几句话总结这个模组很难,", + "但我能说的是,你即将经历一段{C:cry_exotic,E:1}疯狂{}的旅程!", + "这可不是你熟悉的{C:attention}小丑扑克{}...", + }, + cry_intro_5 = { + "你可能从这些{C:cry_ascendant}游戏集{}中看出来了,我喜欢字母{C:attention}M{}。", + "选择一个游戏集,我来为你解释...", + "{s:0.8}注意:游戏集平衡仍在大力开发中。", + "{s:0.8}预计会频繁更新!", + }, + cry_modest_1 = { + "想体验接近原版的玩法?", + "那么{C:cry_ascendant}Modest{}游戏集适合你!", + }, + cry_modest_2 = { + "不过,还是要小心隐藏在", + "Cryptid中的各种机制!你永远不知道", + "下一轮会遇到什么...", + }, + cry_mainline_1 = { + "想{E:1,C:attention}打破{}游戏?好消息,", + "不用太离谱就能做到!", + }, + cry_mainline_2 = { + "这里的内容仍然很疯狂,但你能有机会", + "体验{C:cry_ascendant}成长{}系统。", + "只是别太放松...", + }, + cry_mainline_3 = { + "因为你会变得更强,但我也设计了一些", + "{E:1,C:dark_edition}Boss{},可能会让你后悔选择这个{C:cry_ascendant}游戏集{}...", + }, + cry_madness_1 = { + "想彻底{C:red,E:1}毁灭{}你的硬盘?", + "太有趣了!{C:cry_ascendant}Madness{}游戏集的口号是:", + "'平衡?{E:1,C:red}那是什么鬼东西!{}'", + }, + cry_madness_2 = { + "我花了数周无眠的、喝着{C:green}Mountain Dew{}的夜晚,", + "确保这个游戏集{C:cry_ascendant}绝对平衡{},只为你!", + }, + cry_madness_3 = { + "你会解锁所有内容,这样就能释放", + "Cryptid的{C:red,E:1}全部力量{}!", + "只是小心别让游戏{C:attention,E:1}崩溃{},", + "因为这可能在你失败前就发生...", + }, + }, poker_hand_descriptions = { - cry_Bulwark = { + ["cry_Bulwark"] = { "5 张无等级,无花色的牌", }, - cry_Clusterfuck = { + ["cry_Clusterfuck"] = { "至少 8 张不包含", "对子、同花或顺子的牌", }, - cry_UltPair = { + ["cry_UltPair"] = { "两个两对,共两种花色", "每对两对是一种花色", "他们之间共有两种花色", }, - cry_WholeDeck = { + ["cry_WholeDeck"] = { "在一次出牌中,包含", "52张牌的牌组中的每一张牌", "你疯了?", }, + ["cry_None"] = { "出牌为 0 张牌" }, + + ["cry_Declare0"] = { "始终算作顺子" }, + ["cry_Declare1"] = { "始终算作同花" }, + ["cry_Declare2"] = { "始终算作葫芦" }, + ["cry_Declare0_suitless"] = { "始终算作顺子", "手牌不需要特定花色" }, + ["cry_Declare1_suitless"] = { "始终算作同花", "手牌不需要特定花色" }, + ["cry_Declare2_suitless"] = { "始终算作葫芦", "手牌不需要特定花色" }, }, poker_hands = { cry_Bulwark = "碉堡", @@ -3982,113 +5179,113 @@ return { rnj_loc_txts = { actions = { add_dollars = { - "获得 {C:money}$#2#{}", + "获得{C:money}$#2#{}", }, make_joker = { - "创造 {C:attention}#2# 小丑{}牌", + "创造{C:attention}#2#小丑{}牌", }, make_planet = { - "创造 {C:attention}#2#{C:planet} 星球{} 牌", + "创造{C:attention}#2#{C:planet}星球{}牌", }, make_spectral = { - "创造 {C:attention}#2#{C:spectral} 幻灵{} 牌", + "创造{C:attention}#2#{C:spectral}幻灵{}牌", }, make_tarot = { - "创造 {C:attention}#2#{C:tarot} 塔罗{} 牌", + "创造{C:attention}#2#{C:tarot}塔罗{}牌", }, }, conds = { big = { - "如果 {C:attention}盲注{} 是 {C:attention}大 {C:attention}盲注{}", + "如果{C:attention}盲注{}是{C:attention}大{C:attention}盲注{}", }, boss = { - "如果 {C:attention}盲注{} 是 {C:attention}Boss {C:attention}盲注{}", + "如果{C:attention}盲注{}是{C:attention}Boss{C:attention}盲注{}", }, buy_common = { - "如果是 {C:blue}普通{} {C:attention}小丑{}", + "如果是{C:blue}普通{}{C:attention}小丑{}", }, buy_uncommon = { - "如果是 {C:green}罕见{} {C:attention}小丑{}", + "如果是{C:green}罕见{}{C:attention}小丑{}", }, common = { - "如果是 {C:blue}普通{} {C:attention}小丑{}", + "如果是{C:blue}普通{}{C:attention}小丑{}", }, discards_left = { - "如果回合结束时剩余 {C:red}#3#{} 次丢弃", + "如果回合结束时剩余{C:red}#3#{}次弃牌", }, face = { - "如果卡牌是 {C:attention}面{} 卡", + "如果卡牌是{C:attention}人头牌{}", }, first = { - "如果是 {C:attention}第一次出牌{}", + "如果是{C:attention}第一次出牌{}", }, first_discard = { - "如果是 {C:attention}第一次 {C:attention}丢弃{}", + "如果是{C:attention}第一次{C:attention}弃牌{}", }, hands_left = { - "如果回合结束时剩余 {C:blue}#3#{} 手牌", + "如果回合结束时剩余{C:blue}#3#{}手牌", }, joker = { - "如果卡牌是 {C:attention}小丑{}", + "如果卡牌是{C:attention}小丑{}", }, last = { - "如果是 {C:attention}最后一次{} 出牌", + "如果是{C:attention}最后一次{}出牌", }, last_discard = { - "如果是 {C:attention}最后一次 {C:attention}丢弃{}", + "如果是{C:attention}最后一次{C:attention}弃牌{}", }, non_boss = { - "如果 {C:attention}盲注{} 是 {C:attention}非Boss {C:attention}盲注{}", + "如果{C:attention}盲注{}是{C:attention}非Boss{C:attention}盲注{}", }, odds = { - "以 {C:green}#4# {C:green}中 {C:green}#3#{} 的几率", + "以{C:green}#4# / #3#{}的概率", }, or_less = { - "如果手牌包含 {C:attention}#3#{} 或更少卡牌", + "如果手牌包含{C:attention}#3#{}张或更少卡牌", }, or_more = { - "如果手牌包含 {C:attention}#3#{} 或更多卡牌", + "如果手牌包含{C:attention}#3#{}张或更多卡牌", }, planet = { - "如果卡牌是 {C:planet}星球{} 卡", + "如果卡牌是{C:planet}星球牌{}", }, poker_hand = { - "如果手牌是 {C:attention}#3#{}", + "如果手牌是{C:attention}#3#{}", }, rank = { - "如果卡牌的等级是 {C:attention}#3#{}", + "如果卡牌的等级是{C:attention}#3#{}", }, rare = { - "如果是 {C:red}稀有{} {C:attention}小丑{}", + "如果是{C:red}稀有{}{C:attention}小丑{}", }, small = { - "如果 {C:attention}盲注{} 是 {C:attention}小 {C:attention}盲注{}", + "如果{C:attention}盲注{}是{C:attention}小{C:attention}盲注{}", }, spectral = { - "如果卡牌是 {C:spectral}幻灵{} 卡", + "如果卡牌是{C:spectral}幻灵牌{}", }, suit = { - "如果卡牌是 {V:1}#3#{}", + "如果卡牌是{V:1}#3#{}", }, tarot = { - "如果卡牌是 {C:tarot}塔罗{} 卡", + "如果卡牌是{C:tarot}塔罗牌{}", }, uncommon = { - "如果是 {C:green}罕见{} {C:attention}小丑{}", + "如果是{C:green}罕见{}{C:attention}小丑{}", }, }, contexts = { after = { - "每个 {C:attention}手牌{} 后", + "每次{C:attention}出牌{}后", }, before = { - "每个 {C:attention}手牌{} 前", + "每次{C:attention}出牌{}前", }, buying_card = { "购买卡牌时", }, debuffed_hand = { - "如果已打出 {C:attention}手牌{} 被削弱", + "如果已打出{C:attention}手牌{}被削弱", }, discard = { "为每张丢弃的卡牌", @@ -4097,7 +5294,7 @@ return { "回合结束时", }, ending_shop = { - "在 {C:attention}商店{} 结束时", + "在{C:attention}商店{}结束时", }, first_hand_drawn = { "回合开始时", @@ -4113,13 +5310,13 @@ return { }, joker_main = {}, open_booster = { - "当 {C:attention}补充包{} 被打开时", + "当{C:attention}补充包{}被打开时", }, other_joker = { - "每个 {C:attention}小丑{}", + "每个{C:attention}小丑{}", }, playing_card_added = { - "每次将 {C:attention}手牌{} 添加到牌组时", + "每次将{C:attention}手牌{}添加到牌组时", }, pre_discard = { "每次丢弃前", @@ -4134,7 +5331,7 @@ return { "重新触发已打出的卡牌", }, reroll_shop = { - "重roll商店", + "重掷商店", }, selling_card = { "出售卡牌时", @@ -4143,30 +5340,30 @@ return { "出售此卡时", }, setting_blind = { - "选择 {C:attention}盲注{} 时", + "选择{C:attention}盲注{}时", }, skip_blind = { - "跳过 {C:attention}盲注{} 时", + "跳过{C:attention}盲注{}时", }, skipping_booster = { - "跳过任何 {C:attention}补充包{} 时", + "跳过任何{C:attention}补充包{}时", }, using_consumeable = { - "使用 {C:attention}消耗牌{} 卡牌时", + "使用{C:attention}消耗牌{}卡牌时", }, }, stats = { h_size = { - "{C:attention}+#2#{} 手牌数目", + "{C:attention}+#2#{}手牌数目", }, money = { - "{C:money}+$#2#{} 金钱", + "{C:money}+$#2#{}金钱", }, plus_chips = { - "{C:blue}+#2#{} 筹码", + "{C:blue}+#2#{}筹码", }, plus_mult = { - "{C:red}+#2#{} 增加倍数", + "{C:red}+#2#{}增加倍数", }, x_chips = { "{X:blue,C:white} X#2#{} 筹码", @@ -4248,9 +5445,9 @@ return { "想法: #1#", }, cry_sticker_desc = { - "使用这张小丑在", - "#2#Stake#3# 难度", - "赢得 #2##1#", + "使用这张小丑", + "在#2##1##2#注#3#", + "难度下获胜", }, cry_sticker_name = { "#1# 贴纸", @@ -4258,19 +5455,19 @@ return { }, v_text = { ch_c_all_rnj = { - "所有小丑都是 {C:attention}RNJoker{}", + "所有小丑都是{C:attention}随机小丑{}", }, ch_c_cry_all_banana = { - "所有小丑都是 {C:eternal}香蕉{}", + "所有小丑都是{C:eternal}香蕉{}", }, ch_c_cry_all_perishable = { - "所有小丑都是 {C:eternal}易腐{}", + "所有小丑都是{C:eternal}易腐{}", }, ch_c_cry_all_pinned = { - "所有小丑都是 {C:eternal}固定{}", + "所有小丑都是{C:eternal}固定{}", }, ch_c_cry_all_rental = { - "所有小丑都是 {C:eternal}租赁{}", + "所有小丑都是{C:eternal}租赁{}", }, ch_c_cry_no_boosters = { "{C:attention}补充包{}不再出现在商店中", @@ -4279,22 +5476,22 @@ return { "不再出现{C:attention}消耗牌{} ", }, ch_c_cry_no_rerolls = { - "禁止 {C:attention}重掷{}", + "禁止{C:attention}重掷{}", }, ch_c_cry_no_tags = { - "跳过功能已 {C:attention}禁用{}", + "跳过功能已{C:attention}禁用{}", }, ch_c_cry_no_vouchers = { - "{C:attention}优惠券{} 不再出现在商店中", + "{C:attention}优惠券{}不再出现在商店中", }, ch_c_cry_rush_hour = { - "所有 Boss 盲注都是 {C:attention}时钟{} 或 {C:attention}薰衣草循环", + "所有Boss 盲注都是{C:attention}时钟{}或{C:attention}薰衣草循环", }, ch_c_cry_rush_hour_ii = { - "所有盲注都是 {C:attention}Boss 盲注{}", + "所有盲注都是{C:attention}Boss 盲注{}", }, ch_c_cry_rush_hour_iii = { - "{C:attention}时钟{} 和 {C:attention}薰衣草循环{} 的规模是 {C:attention}两倍{} 快", + "{C:attention}时钟{}和{C:attention}薰衣草循环{}的规模是{C:attention}两倍{}快", }, ch_c_cry_sticker_sheet_plus = { "所有可购买的物品都有所有贴纸", @@ -4377,7 +5574,7 @@ return { "会得到免费优惠券!", }, { - "对不起,", + "对不起", "由于预算削减", "没有优惠券", }, diff --git a/Cryptid/localization/zh_TW.lua b/Cryptid/localization/zh_TW.lua index 579a341..005d1f8 100644 --- a/Cryptid/localization/zh_TW.lua +++ b/Cryptid/localization/zh_TW.lua @@ -1222,7 +1222,7 @@ return { "{C:attention}first discard{} of each round", }, }, - j_cry_Megg = { + j_cry_megg = { name = "Megg", text = { "Sell this card to create", @@ -1236,7 +1236,7 @@ return { "{X:mult,C:white}X#1#{} Mult for each member", "in the {C:attention}Cryptid Discord{}", "{C:inactive}(Currently {X:mult,C:white}X#2#{C:inactive} Mult)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_membershipcardtwo = { @@ -1245,7 +1245,7 @@ return { "{C:chips}+#1#{} Chips for each member", "in the {C:attention}Cryptid Discord{}", "{C:inactive}(Currently {C:chips}+#2#{C:inactive} Chips)", - "{C:blue,s:0.7}https://discord.gg/cryptid{}", + "{C:blue,s:0.7}https://discord.gg/eUf9Ur6RyB{}", }, }, j_cry_meteor = { @@ -2045,6 +2045,14 @@ return { "card in your hand", }, }, + c_cry_meld = { + name = "Meld", + text = { + "Select a {C:attention}Joker{} or", + "{C:attention}playing card{} to", + "become {C:dark_edition}Double-Sided", + }, + }, c_cry_vacuum = { name = "Vacuum", text = { @@ -2477,14 +2485,6 @@ return { "into an {C:attention}Echo Card", }, }, - c_cry_meld = { - name = "Meld", - text = { - "Select a {C:attention}Joker{} or", - "{C:attention}playing card{} to", - "become {C:dark_edition}Double-Sided", - }, - }, c_cry_theblessing = { name = "The Blessing", text = { @@ -2716,6 +2716,15 @@ return { }, }, Other = { + alt_wheel_of_fortune = { + name = "幸運之輪", + text = { + "{C:green}#1#/#2#{}的機率會增加", + "{C:dark_edition}銀箔{}、{C:dark_edition}全像攝影{}和", + "{C:dark_edition}彩色{}版本", + "至隨機一張{C:attention}小丑牌", + }, + }, banana = { name = "Banana", text = { @@ -3041,6 +3050,7 @@ return { cry_debuff_obsidian_orb = "Applies abilities of all defeated bosses", k_code = "Code", + k_chips = "銀箔", b_code_cards = "Code Cards", b_pull = "PULL", cry_hooked_ex = "Hooked!", diff --git a/Cryptid/lovely/Probability.toml b/Cryptid/lovely/Probability.toml index fc8c5c9..23c0d85 100644 --- a/Cryptid/lovely/Probability.toml +++ b/Cryptid/lovely/Probability.toml @@ -25,55 +25,14 @@ payload = ''' function cry_prob(owned, den, rigged) prob = G.GAME and G.GAME.probabilities.normal or 1 if rigged then - return den + return to_number(math.min(den, 1e300)) else - if owned then return prob*owned else return prob end + if owned then return to_number(math.min(prob*owned, 1e300)) else return to_number(math.min(prob, 1e300)) end end end ''' match_indent = true -# lucky -[[patches]] -[patches.pattern] -target = "functions/common_events.lua" -pattern = '''elseif _c.effect == 'Lucky Card' then loc_vars = {G.GAME.probabilities.normal, cfg.mult, 5, cfg.p_dollars, 15}''' -position = "at" -payload = ''' -elseif _c.effect == 'Lucky Card' then loc_vars = {cfg.cry_prob and cry_prob(cfg.cry_prob, 15, cfg.cry_rigged) or G.GAME.probabilities.normal, cfg.mult, 5, cfg.p_dollars, 15} -''' -match_indent = true - -[[patches]] -[patches.pattern] -target = "card.lua" -pattern = '''if pseudorandom('lucky_money') < G.GAME.probabilities.normal/15 then''' -position = "at" -payload = ''' -if pseudorandom('lucky_money') < cry_prob(self.ability.cry_prob, 15, self.ability.cry_rigged)/15 then -''' -match_indent = true - -[[patches]] -[patches.pattern] -target = "card.lua" -pattern = '''if pseudorandom('lucky_mult') < G.GAME.probabilities.normal/5 then''' -position = "at" -payload = ''' -if pseudorandom('lucky_mult') < cry_prob(self.ability.cry_prob, 5, self.ability.cry_rigged)/5 then -''' -match_indent = true - -# glass -[[patches]] -[patches.pattern] -target = "functions/common_events.lua" -pattern = '''elseif _c.effect == 'Glass Card' then loc_vars = {cfg.Xmult, G.GAME.probabilities.normal, cfg.extra}''' -position = "at" -payload = ''' -elseif _c.effect == 'Glass Card' then loc_vars = {cfg.Xmult, cfg.cry_prob and cry_prob(cfg.cry_prob, cfg.extra, cfg.cry_rigged) or G.GAME.probabilities.normal, cfg.extra} -''' -match_indent = true # wow this is a fat line # Yellow Stake - Glass can't destroy Eternals @@ -81,220 +40,13 @@ match_indent = true [[patches]] [patches.pattern] target = "functions/state_events.lua" -pattern = '''if SMODS.has_enhancement(scoring_hand[i], 'm_glass') and not scoring_hand[i].debuff and pseudorandom('glass') < G.GAME.probabilities.normal/(scoring_hand[i].ability.name == 'Glass Card' and scoring_hand[i].ability.extra or G.P_CENTERS.m_glass.config.extra) then''' +pattern = '''if SMODS.has_enhancement(scoring_hand[i], 'm_glass') and scoring_hand[i]:can_calculate() and pseudorandom('glass') < G.GAME.probabilities.normal/(scoring_hand[i].ability.name == 'Glass Card' and scoring_hand[i].ability.extra or G.P_CENTERS.m_glass.config.extra) then''' position = "at" payload = ''' if (SMODS.has_enhancement(scoring_hand[i], 'm_glass') and not scoring_hand[i].debuff - and pseudorandom('glass') < cry_prob( - scoring_hand[i].ability.cry_prob, - scoring_hand[i].ability.extra or G.P_CENTERS.m_glass.config.extra, - scoring_hand[i].ability.cry_rigged - ) / (scoring_hand[i].ability.name == 'Glass Card' - and scoring_hand[i].ability.extra - or G.P_CENTERS.m_glass.config.extra) + and SMODS.pseudorandom_probability(scoring_hand[i], 'glass', 1, scoring_hand[i].ability.extra or G.P_CENTERS.m_glass.config.extra) or (G.GAME.modifiers.cry_shatter_rate and pseudorandom('cry_shatter') < 1 / G.GAME.modifiers.cry_shatter_rate)) - and not scoring_hand[i].ability.eternal then''' -match_indent = true - -# wheeeeeeeeeeel -[[patches]] -[patches.pattern] -target = "functions/common_events.lua" -pattern = '''elseif _c.name == "The Wheel of Fortune" then loc_vars = {G.GAME.probabilities.normal, cfg.extra}; info_queue[#info_queue+1] = G.P_CENTERS.e_foil; info_queue[#info_queue+1] = G.P_CENTERS.e_holo; info_queue[#info_queue+1] = G.P_CENTERS.e_polychrome;''' -position = "at" -payload = ''' -elseif _c.name == "The Wheel of Fortune" then loc_vars = {cfg.cry_prob and cry_prob(cfg.cry_prob, cfg.extra, cfg.cry_rigged) or G.GAME.probabilities.normal, cfg.extra}; info_queue[#info_queue+1] = G.P_CENTERS.e_foil; info_queue[#info_queue+1] = G.P_CENTERS.e_holo; info_queue[#info_queue+1] = G.P_CENTERS.e_polychrome; -''' -match_indent = true - -[[patches]] -[patches.pattern] -target = "card.lua" -pattern = '''if self.ability.name == 'Ectoplasm' or self.ability.name == 'Hex' or pseudorandom('wheel_of_fortune') < G.GAME.probabilities.normal/self.ability.extra then''' -position = "at" -payload = ''' -if self.ability.name == 'Ectoplasm' or self.ability.name == 'Hex' or pseudorandom('wheel_of_fortune') < cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged)/self.ability.extra then -''' -match_indent = true - -# ok now onto jonklers - -# space -[[patches]] -[patches.pattern] -target = "card.lua" -pattern = '''elseif self.ability.name == 'Space Joker' then loc_vars = {''..(G.GAME and G.GAME.probabilities.normal or 1), self.ability.extra}''' -position = "at" -payload = ''' -elseif self.ability.name == 'Space Joker' then loc_vars = {cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged), self.ability.extra} -''' -match_indent = true - -[[patches]] -[patches.pattern] -target = "card.lua" -pattern = '''if self.ability.name == 'Space Joker' and pseudorandom('space') < G.GAME.probabilities.normal/self.ability.extra then''' -position = "at" -payload = ''' -if self.ability.name == 'Space Joker' and pseudorandom('space') < cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged)/self.ability.extra then -''' -match_indent = true - -# 8ball -[[patches]] -[patches.pattern] -target = "card.lua" -pattern = '''elseif self.ability.name == '8 Ball' then loc_vars = {''..(G.GAME and G.GAME.probabilities.normal or 1),self.ability.extra}''' -position = "at" -payload = ''' -elseif self.ability.name == '8 Ball' then loc_vars = {cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged),self.ability.extra} -''' -match_indent = true - -[[patches]] -[patches.pattern] -target = "card.lua" -pattern = '''if (context.other_card:get_id() == 8) and (pseudorandom('8ball') < G.GAME.probabilities.normal/self.ability.extra) then''' -position = "at" -payload = ''' -if (context.other_card:get_id() == 8) and (pseudorandom('8ball') < cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged)/self.ability.extra) then -''' -match_indent = true - -# business -[[patches]] -[patches.pattern] -target = "card.lua" -pattern = '''elseif self.ability.name == 'Business Card' then loc_vars = {''..(G.GAME and G.GAME.probabilities.normal or 1), self.ability.extra}''' -position = "at" -payload = ''' -elseif self.ability.name == 'Business Card' then loc_vars = {cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged),self.ability.extra} -''' -match_indent = true - -[[patches]] -[patches.pattern] -target = "card.lua" -pattern = '''pseudorandom('business') < G.GAME.probabilities.normal/self.ability.extra then''' -position = "at" -payload = ''' -pseudorandom('business') < cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged)/self.ability.extra then -''' -match_indent = true - -# gros michel + cavendish -[[patches]] -[patches.pattern] -target = "card.lua" -pattern = '''elseif self.ability.name == 'Gros Michel' then loc_vars = {self.ability.extra.mult, ''..(G.GAME and G.GAME.probabilities.normal or 1), self.ability.extra.odds}''' -position = "at" -payload = ''' -elseif self.ability.name == 'Gros Michel' then loc_vars = {self.ability.extra.mult, cry_prob(self.ability.cry_prob, self.ability.extra.odds, self.ability.cry_rigged), self.ability.extra.odds} -''' -match_indent = true - -[[patches]] -[patches.pattern] -target = "card.lua" -pattern = '''elseif self.ability.name == 'Cavendish' then loc_vars = {self.ability.extra.Xmult, ''..(G.GAME and G.GAME.probabilities.normal or 1), self.ability.extra.odds}''' -position = "at" -payload = ''' -elseif self.ability.name == 'Cavendish' then loc_vars = {self.ability.extra.Xmult, cry_prob(self.ability.cry_prob, self.ability.extra.odds, self.ability.cry_rigged), self.ability.extra.odds} -''' -match_indent = true - -[[patches]] -[patches.pattern] -target = "card.lua" -pattern = '''if pseudorandom(self.ability.name == 'Cavendish' and 'cavendish' or 'gros_michel') < G.GAME.probabilities.normal/self.ability.extra.odds then''' -position = "at" -payload = ''' -if pseudorandom(self.ability.name == 'Cavendish' and 'cavendish' or 'gros_michel') < cry_prob(self.ability.cry_prob, self.ability.extra.odds, self.ability.cry_rigged)/self.ability.extra.odds then -''' -match_indent = true - -# business -[[patches]] -[patches.pattern] -target = "card.lua" -pattern = '''elseif self.ability.name == 'Business Card' then loc_vars = {''..(G.GAME and G.GAME.probabilities.normal or 1), self.ability.extra}''' -position = "at" -payload = ''' -elseif self.ability.name == 'Business Card' then loc_vars = {cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged),self.ability.extra} -''' -match_indent = true - -[[patches]] -[patches.pattern] -target = "card.lua" -pattern = '''pseudorandom('business') < G.GAME.probabilities.normal/self.ability.extra then''' -position = "at" -payload = ''' -pseudorandom('business') < cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged)/self.ability.extra then -''' -match_indent = true - -# bloodstone -[[patches]] -[patches.pattern] -target = "card.lua" -pattern = '''elseif self.ability.name == 'Bloodstone' then loc_vars = {''..(G.GAME and G.GAME.probabilities.normal or 1), self.ability.extra.odds, self.ability.extra.Xmult}''' -position = "at" -payload = ''' -elseif self.ability.name == 'Bloodstone' then loc_vars = {cry_prob(self.ability.cry_prob, self.ability.extra.odds, self.ability.cry_rigged), self.ability.extra.odds, self.ability.extra.Xmult} -''' -match_indent = true - -[[patches]] -[patches.pattern] -target = "card.lua" -pattern = '''pseudorandom('bloodstone') < G.GAME.probabilities.normal/self.ability.extra.odds then''' -position = "at" -payload = ''' -pseudorandom('bloodstone') < cry_prob(self.ability.cry_prob, self.ability.extra.odds, self.ability.cry_rigged)/self.ability.extra.odds then -''' -match_indent = true - -# reserved parking -[[patches]] -[patches.pattern] -target = "card.lua" -pattern = '''elseif self.ability.name == 'Reserved Parking' then loc_vars = {self.ability.extra.dollars, ''..(G.GAME and G.GAME.probabilities.normal or 1), self.ability.extra.odds}''' -position = "at" -payload = ''' -elseif self.ability.name == 'Reserved Parking' then loc_vars = {self.ability.extra.dollars, cry_prob(self.ability.cry_prob, self.ability.extra.odds, self.ability.cry_rigged), self.ability.extra.odds} -''' -match_indent = true - -[[patches]] -[patches.pattern] -target = "card.lua" -pattern = '''pseudorandom('parking') < G.GAME.probabilities.normal/self.ability.extra.odds then''' -position = "at" -payload = ''' -pseudorandom('parking') < cry_prob(self.ability.cry_prob, self.ability.extra.odds, self.ability.cry_rigged)/self.ability.extra.odds then -''' -match_indent = true - -# hallucination -[[patches]] -[patches.pattern] -target = "card.lua" -pattern = '''elseif self.ability.name == 'Hallucination' then loc_vars = {G.GAME.probabilities.normal, self.ability.extra}''' -position = "at" -payload = ''' -elseif self.ability.name == 'Hallucination' then loc_vars = {cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged), self.ability.extra} -''' -match_indent = true - -[[patches]] -[patches.pattern] -target = "card.lua" -pattern = '''if pseudorandom('halu'..G.GAME.round_resets.ante) < G.GAME.probabilities.normal/self.ability.extra then''' -position = "at" -payload = ''' -if pseudorandom('halu'..G.GAME.round_resets.ante) < cry_prob(self.ability.cry_prob, self.ability.extra, self.ability.cry_rigged)/self.ability.extra then -''' -match_indent = true + and not SMODS.is_eternal(scoring_hand[i]) then''' +match_indent = true \ No newline at end of file diff --git a/Cryptid/lovely/Voucher.toml b/Cryptid/lovely/Voucher.toml index 4e731f8..992c373 100644 --- a/Cryptid/lovely/Voucher.toml +++ b/Cryptid/lovely/Voucher.toml @@ -34,10 +34,9 @@ match_indent = true [[patches]] [patches.pattern] target = "card.lua" -pattern = '''G.GAME.current_round.voucher = nil''' -position = "at" +pattern = '''--G.GAME.current_round.voucher = nil''' +position = "after" payload = ''' --- G.GAME.current_round.voucher = nil if self.shop_cry_bonusvoucher then G.GAME.cry_bonusvouchersused[self.shop_cry_bonusvoucher] = true end ''' match_indent = true @@ -57,23 +56,23 @@ match_indent = true # initialise the other helpful variables # tarot/planet percrates appear here too because why not -[[patches]] -[patches.pattern] -target = "game.lua" -pattern = '''ecto_minus = 1,''' -position = "after" -payload = ''' -cry_bonusvouchercount = 0, -cry_bonusvouchersused = {}, -cry_percrate = {tarot = 100, planet = 100}, -''' -match_indent = true +# [[patches]] +# [patches.pattern] +# target = "game.lua" +# pattern = '''ecto_minus = 1,''' +# position = "after" +# payload = ''' +# cry_bonusvouchercount = 0, +# cry_bonusvouchersused = {}, +# cry_percrate = {tarot = 100, planet = 100}, +# ''' +# match_indent = true # populate the table with keys [[patches]] [patches.pattern] target = "functions/state_events.lua" -pattern = '''G.GAME.current_round.voucher = get_next_voucher_key()''' +pattern = '''G.GAME.current_round.voucher = SMODS.get_next_vouchers()''' position = "after" payload = ''' G.GAME.current_round.cry_voucher_stickers = Cryptid.next_voucher_stickers() @@ -81,7 +80,7 @@ G.GAME.current_round.cry_voucher_edition = cry_get_next_voucher_edition() or {} G.GAME.current_round.cry_bonusvouchers = {} G.GAME.cry_bonusvouchersused = {} -- i'm not sure why i'm putting these in two separate tables but it doesn't matter much for i = 1, G.GAME.cry_bonusvouchercount do - G.GAME.current_round.cry_bonusvouchers[i] = get_next_voucher_key() + G.GAME.current_round.cry_bonusvouchers[i] = SMODS.get_next_vouchers() end ''' match_indent = true @@ -90,7 +89,7 @@ match_indent = true [[patches]] [patches.pattern] target = "game.lua" -pattern = '''self.GAME.current_round.voucher = G.SETTINGS.tutorial_progress and G.SETTINGS.tutorial_progress.forced_voucher or get_next_voucher_key()''' +pattern = '''self.GAME.current_round.voucher = forced_voucher and {forced_voucher, spawn = {[forced_voucher] = true }} or SMODS.get_next_vouchers()''' position = "after" payload = ''' G.GAME.current_round.cry_voucher_stickers = Cryptid.next_voucher_stickers() @@ -125,7 +124,7 @@ for i = 1, #G.GAME.current_round.cry_bonusvouchers do local card = Card(G.shop_vouchers.T.x + G.shop_vouchers.T.w/2, G.shop_vouchers.T.y, G.CARD_W, G.CARD_H, G.P_CARDS.empty, G.P_CENTERS[G.GAME.current_round.cry_bonusvouchers[i]],{bypass_discovery_center = true, bypass_discovery_ui = true}) card.shop_cry_bonusvoucher = i - Cryptid.misprintize(card) + Cryptid.manipulate(card) if G.GAME.events.ev_cry_choco2 then card.misprint_cost_fac = (card.misprint_cost_fac or 1) * 2 card:set_cost() @@ -144,7 +143,7 @@ for i = 1, #G.GAME.current_round.cry_bonusvouchers do end ''' -# control the planet/tarot rates +# control the planet/tarot rates (This needs to be left in to maintain vanilla RNG [[patches]] [patches.pattern] target = "functions/UI_definitions.lua" @@ -159,7 +158,38 @@ payload = ''' ''' match_indent = true -# fix total rate +# Adds adjustability to every other consumable type +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = ''' + table.insert(rates, { type = v, val = G.GAME[v:lower()..'_rate'] }) +''' +position = "at" +payload = ''' +local num = G.GAME.cry_percrate and G.GAME.cry_percrate[v:lower()] or 100 +table.insert(rates, { type = v, val = G.GAME[v:lower()..'_rate'] * ((num or 100) / 100) }) +''' +match_indent = true + +# fix total rate (Current Cryptid implementation) +# [[patches]] +# [patches.pattern] +# target = "functions/UI_definitions.lua" +# pattern = ''' +# total_rate = total_rate + G.GAME[v:lower()..'_rate'] +# ''' +# position = "at" +# payload = ''' +# if not (v:lower() == 'tarot' or v:lower() == 'planet') then +# total_rate = total_rate + G.GAME[v:lower()..'_rate'] +# else +# total_rate = total_rate + ( G.GAME[v:lower()..'_rate'] * (G.GAME.cry_percrate[v:lower()]/100) ) +# end +# ''' +# match_indent = true + +# fix total rate (IcyEthics Refactor) [[patches]] [patches.pattern] target = "functions/UI_definitions.lua" @@ -168,11 +198,7 @@ total_rate = total_rate + G.GAME[v:lower()..'_rate'] ''' position = "at" payload = ''' -if not (v:lower() == 'tarot' or v:lower() == 'planet') then - total_rate = total_rate + G.GAME[v:lower()..'_rate'] -else - total_rate = total_rate + ( G.GAME[v:lower()..'_rate'] * (G.GAME.cry_percrate[v:lower()]/100) ) -end +total_rate = total_rate + ( G.GAME[v:lower()..'_rate'] * (G.GAME.cry_percrate[v:lower()]/100) ) ''' match_indent = true diff --git a/Cryptid/lovely/abstracted.toml b/Cryptid/lovely/abstracted.toml new file mode 100644 index 0000000..aef0e9e --- /dev/null +++ b/Cryptid/lovely/abstracted.toml @@ -0,0 +1,185 @@ +[manifest] +version = "0.0.1" +dump_lua = true +priority = 2 + +# Destroy abstract cards at the end of round +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = "G.FUNCS.draw_from_hand_to_discard()" +position = "before" +payload = ''' +i = 1 +while i <= #G.hand.cards do + local gone = G.hand.cards[i]:calculate_abstract_break() + if not gone then i = i + 1 end +end +-- i = 1 +-- while i <= #G.deck.cards do +-- local gone = G.deck.cards[i]:calculate_abstract_break() +-- if not gone then i = i + 1 end +-- end +-- i = 1 +-- while i <= #G.discard.cards do +-- local gone = G.discard.cards[i]:calculate_abstract_break() +-- if not gone then i = i + 1 end +-- end +''' +match_indent = true + +## Specific suit from enhancement check +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "if flush_calc then" +position = "before" +payload = ''' +--Force suit to be suit X if specified in enhancement, only if not vampired +if Cryptid.cry_enhancement_has_specific_suit(self) and not self.vampired then + return suit == Cryptid.cry_enhancement_get_specific_suit(self) +end +''' +match_indent = true + +## For better mod compat, the if statement will be wrapped around + +## Idol: Ignore abstracted cards +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "valid_idol_cards[#valid_idol_cards+1] = v" +position = "before" +payload = ''' + if not SMODS.has_enhancement(v, "m_cry_abstract") then +''' +match_indent = true +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "valid_idol_cards[#valid_idol_cards+1] = v" +position = "after" +payload = ''' + end +''' +match_indent = true + +## Mail in rebate: ignore abstracted cards +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "valid_mail_cards[#valid_mail_cards+1] = v" +position = "before" +payload = ''' + if not SMODS.has_enhancement(v, "m_cry_abstract") then +''' +match_indent = true +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "valid_mail_cards[#valid_mail_cards+1] = v" +position = "after" +payload = ''' + end +''' +match_indent = true + +## castle: ignore abstracted cards +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "valid_castle_cards[#valid_castle_cards+1] = v" +position = "before" +payload = ''' + if not SMODS.has_enhancement(v, "m_cry_abstract") then +''' +match_indent = true +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "valid_castle_cards[#valid_castle_cards+1] = v" +position = "after" +payload = ''' + end +''' +match_indent = true + +## really hacky UnStable crossmod workaround; +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = "if hand[i]:is_suit(suit, nil, true) then flush_count = flush_count + 1; t[#t+1] = hand[i] end" +position = "before" +payload = ''' + if Cryptid.cry_enhancement_has_specific_suit(hand[i]) then + if hand[i]:is_suit_force_enhancement(suit, nil, true) then flush_count = flush_count + 1; t[#t+1] = hand[i] end + else +''' +match_indent = true +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = "if hand[i]:is_suit(suit, nil, true) then flush_count = flush_count + 1; t[#t+1] = hand[i] end" +position = "after" +payload = ''' + end +''' +match_indent = true + +## Artificially add abstracted 'suits' to flush calculations without declaring them (sigil, familiar) +## Also make sure to create a hard copy of suits and iterate, otherwise adding the artificial suit will add it to suit.obj_buffer for real! +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = "local suits = SMODS.Suit.obj_buffer" +position = "at" +payload = ''' + local suits = {} + suits[#suits + 1] = 'cry_abstract' + + for i,v in pairs(SMODS.Suit.obj_buffer) do + suits[#suits + 1] = v + end +''' +match_indent = true + +## Artificially add abstracted 'rank' to X of a kind calculations +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = '''for i = 1, SMODS.Rank.max_id.value do + vals[i] = {} + end''' +position = "after" +payload = ''' + vals[#vals + 1] = {} +''' +match_indent = true + +## Force abstract cards to be only slightly above stone cards + +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''elseif self.config.center.no_rank then''' +position = "before" +payload = ''' +if Cryptid.cry_enhancement_get_specific_rank(self) == 'cry_abstract' then + mult = -9000 +end +''' +match_indent = true + +## Force abstracted to not be face cards + +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''if not id then return end''' +position = "before" +payload = ''' +if SMODS.has_enhancement(self, "m_cry_abstract") then + return +end +''' +match_indent = true diff --git a/Cryptid/lovely/blind.toml b/Cryptid/lovely/blind.toml index 4b24515..710804b 100644 --- a/Cryptid/lovely/blind.toml +++ b/Cryptid/lovely/blind.toml @@ -3,32 +3,6 @@ version = "1.0.0" dump_lua = true priority = -1 -# The Tax effect -[[patches]] -[patches.pattern] -target = "functions/state_events.lua" -pattern = "func = (function() update_hand_text({delay = 0, immediate = true}, {mult = 0, chips = 0, chip_total = math.floor(hand_chips*mult), level = '', handname = ''});play_sound('button', 0.9, 0.6);return true end)" -position = "at" -payload = "func = (function() update_hand_text({delay = 0, immediate = true}, {mult = 0, chips = 0, chip_total = G.GAME.blind.cry_cap_score and G.GAME.blind:cry_cap_score(math.floor(hand_chips*mult)) or math.floor(hand_chips*mult), level = '', handname = ''});play_sound('button', 0.9, 0.6);return true end)" -match_indent = true - -[[patches]] -[patches.pattern] -target = "functions/state_events.lua" -pattern = "ease_to = G.GAME.chips + math.floor(hand_chips*mult)," -position = "at" -payload = "ease_to = G.GAME.chips + (G.GAME.blind.cry_cap_score and G.GAME.blind:cry_cap_score(math.floor(hand_chips*mult)) or math.floor(hand_chips*mult))," -match_indent = true - -# Bunco (Magenta Dagger) and Cryptid (The Tax) compat -[[patches]] -[patches.pattern] -target = 'functions/state_events.lua' -pattern = "ease_to = G.GAME.chips + math.floor(hand_chips * mult) * (e and e.antiscore and -1 or 1)," -position = 'at' -match_indent = true -payload = '''ease_to = G.GAME.chips + (G.GAME.blind.cry_cap_score and G.GAME.blind:cry_cap_score(math.floor(hand_chips*mult)) or math.floor(hand_chips*mult)) * (e and e.antiscore and -1 or 1),''' - # Fix a crash related to undebuffing Jokers at end of round [[patches]] [patches.pattern] @@ -77,4 +51,204 @@ check_for_unlock({ type = "lose_to_specific_blind", blind = cry_defeated_by, amo ''' match_indent = true +# ReAdd pre-cash context for "the decision", to force open a booster when round ends + +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = '''G.STATE = G.STATES.ROUND_EVAL + G.STATE_COMPLETE = false''' +position = "before" +payload = ''' +if G.GAME.blind.config.blind.cry_before_cash and not G.GAME.blind.disabled then + G.GAME.blind:cry_before_cash() +else +G.GAME.cry_make_a_decision = nil + +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = '''G.STATE = G.STATES.ROUND_EVAL + G.STATE_COMPLETE = false''' +position = "after" +payload = ''' +end +''' +match_indent = true + +## Always be able to add cursed Jokers +[[patches]] +[patches.pattern] +target = '''functions/button_callbacks.lua''' +pattern = '''if card.ability.set ~= 'Joker' or #G.jokers.cards < G.jokers.config.card_limit + card_limit then + e.config.colour = G.C.GREEN + e.config.button = 'use_card'''' +position = "after" +payload = ''' +elseif card.ability.set == 'Joker' and card.config.center.rarity == "cry_cursed" then + e.config.colour = G.C.GREEN + e.config.button = 'use_card' +''' +match_indent = true + +## Get back into blind and complete it after using a pack +[[patches]] +[patches.pattern] +target = '''functions/button_callbacks.lua''' +pattern = '''G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.2*delayfac, + func = function() + save_run() + return true + end}))''' +position = "at" +payload = ''' +G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.2*delayfac, + func = function() + if G.GAME.cry_make_a_decision then + G.GAME.cry_make_a_decision = nil + G.STATE = G.STATES.ROUND_EVAL + G.STATE_COMPLETE = false + else + save_run() + end + + return true +end})) + +''' +match_indent = true + +## Do not trigger booster pack tags after ending the baneful pack, otherwise it will be awkward +[[patches]] +[patches.pattern] +target = '''functions/button_callbacks.lua''' +pattern = '''for i = 1, #G.GAME.tags do + if G.GAME.tags[i]:apply_to_run({type = 'new_blind_choice'}) then break end + end''' +position = "at" +payload = ''' +for i = 1, #G.GAME.tags do + if not G.GAME.cry_make_a_decision then + if G.GAME.tags[i]:apply_to_run({type = 'new_blind_choice'}) then break end + end +end +''' +match_indent = true + +##Part 1 of below: +[[patches]] +[patches.pattern] +target = '''functions/misc_functions.lua''' +pattern = '''--Control the music here''' +position = "before" +payload = ''' +local disable_booster_music = false +local obj = SMODS.OPENED_BOOSTER +if obj and obj.config and obj.config.center and obj.config.center.no_music then + disable_booster_music = true +end +''' +match_indent = true + +## Force music to be Boss Blind music while in baneful pack +[[patches]] +[patches.pattern] +target = '''functions/misc_functions.lua''' +pattern = '''(G.booster_pack and not G.booster_pack.REMOVED and 'music2') or''' +position = "at" +payload = '''(G.booster_pack and not G.booster_pack.REMOVED and not disable_booster_music and 'music2') or''' +match_indent = true + +## If selling luchador inside the baneful buffoon pack and the blind is active, automatically skip it without penalty +[[patches]] +[patches.pattern] +target = '''blind.lua''' +pattern = '''G.STATE = G.STATES.NEW_ROUND + G.STATE_COMPLETE = false''' +position = "before" +payload = ''' + +if G.GAME.cry_make_a_decision and G.STATE == G.STATES.SMODS_BOOSTER_OPENED then + SMODS.calculate_context({skipping_booster = true, booster = booster_obj}) + booster_obj = nil + G.FUNCS.end_consumeable() +else +''' +match_indent = true +##Wrapper of above +[[patches]] +[patches.pattern] +target = '''blind.lua''' +pattern = '''G.STATE = G.STATES.NEW_ROUND + G.STATE_COMPLETE = false''' +position = "after" +payload = ''' +end +''' +match_indent = true + +## If rarity is cursed and no more jokers remain, always spawn Monopoly Money +[[patches]] +[patches.pattern] +target = '''functions/common_events.lua''' +pattern = '''elseif _type == 'Planet' then _pool[#_pool + 1] = "c_pluto"''' +position = "before" +payload = ''' +elseif _type == 'Joker' and _rarity == 'cry_cursed' then _pool[#_pool + 1] = "j_cry_monopoly_money" +''' +match_indent = true + +## In the rare event you have mr bones at hand, also force close +[[patches]] +[patches.pattern] +target = '''blind.lua''' +pattern = '''self:set_text() + self:wiggle()''' +position = "before" +payload = ''' +--Function to check if less than size and if they are SAVED. +G.E_MANAGER:add_event(Event({ + trigger = 'immediate', + func = function() + if self.boss and to_big(G.GAME.chips) - G.GAME.blind.chips < to_big(0) and SMODS.saved then + if G.GAME.cry_make_a_decision and G.STATE == G.STATES.SMODS_BOOSTER_OPENED then + SMODS.calculate_context({skipping_booster = true, booster = booster_obj}) + booster_obj = nil + G.FUNCS.end_consumeable() + end + end + return true +end +})) +''' +match_indent = true + +## Baneful warning +[[patches]] +[patches.pattern] +target = '''=[SMODS _ "src/game_object.lua"]''' +pattern = '''G.CONTROLLER.interrupt.focus = true''' +position = "after" +payload = ''' +if SMODS.OPENED_BOOSTER.config.center.cry_baneful_punishment then +G.E_MANAGER:add_event(Event({ + trigger = 'before', + func = function() + attention_text({ + scale = 0.8, + text = localize("cry_baneful_warning"), + hold = 12, + align = "cm", + offset = { x = 0, y = -2.7 }, + major = G.play, + }) + return true + end, +})) +end +''' +match_indent = true diff --git a/Cryptid/lovely/cat.toml b/Cryptid/lovely/cat.toml index c09e6a4..3dd2ce7 100644 --- a/Cryptid/lovely/cat.toml +++ b/Cryptid/lovely/cat.toml @@ -22,6 +22,17 @@ pattern = '''tag_sprite.stop_hover = function(_self) _self.hovering = false; Nod position = "after" payload = ''' tag_sprite.click = function(_self) + if G.GAME.USING_POINTER then + local t = G.P_TAGS[self.key] + if not t.no_doe and not t.hidden and not t.no_pointer then + add_tag(self) + G.FUNCS.exit_overlay_menu_code() + if G.GAME.CODE_DESTROY_CARD then + G.GAME.CODE_DESTROY_CARD:start_dissolve() + G.GAME.CODE_DESTROY_CARD = nil + end + end + end if self.key == 'tag_cry_cat' and self.HUD_tag then for i = 1, #G.GAME.tags do local other_cat = G.GAME.tags[i] @@ -192,9 +203,11 @@ target = "tag.lua" pattern = '''local tag_sprite = Sprite(0,0,_size*1,_size*1,G.ASSET_ATLAS[(not self.hide_ability) and G.P_TAGS[self.key].atlas or "tags"], (self.hide_ability) and G.tag_undiscovered.pos or self.pos)''' position = "at" payload = ''' -local tagatlas = G.ASSET_ATLAS[(not self.hide_ability) and G.P_TAGS[self.key].atlas or "tags"] +local tagatlas = G.ASSET_ATLAS[self and (not self.hide_ability) and G.P_TAGS[self.key] and G.P_TAGS[self.key].atlas or "tags"] if self.ability.shiny and not self.hide_ability then - if not G.P_TAGS[self.key].atlas then + if G.P_TAGS[self.key].shiny_atlas then + tagatlas = G.ASSET_ATLAS[G.P_TAGS[self.key].shiny_atlas] + elseif not G.P_TAGS[self.key].atlas then tagatlas = G.ASSET_ATLAS['cry_shinyv'] elseif G.P_TAGS[self.key].atlas == 'cry_tag_cry' then tagatlas = G.ASSET_ATLAS['cry_shinyc'] @@ -211,14 +224,14 @@ match_indent = true [patches.pattern] target = '''=[SMODS _ "src/overrides.lua"]''' pattern = ''' - opt_callback = 'your_collection_tags_page', - focus_args = { snap_to = true, nav = 'wide' }, - current_option = page, - colour = G.C.RED, - no_pips = true - }) - } - }''' + opt_callback = 'your_collection_tags_page', + focus_args = { snap_to = true, nav = 'wide' }, + current_option = page, + colour = G.ACTIVE_MOD_UI and (G.ACTIVE_MOD_UI.ui_config or {}).collection_option_cycle_colour or G.C.RED, + no_pips = true + }) + } +}''' position = "after" payload = ''' , diff --git a/Cryptid/lovely/ccd.toml b/Cryptid/lovely/ccd.toml index 0e487a1..98c0f2e 100644 --- a/Cryptid/lovely/ccd.toml +++ b/Cryptid/lovely/ccd.toml @@ -12,7 +12,7 @@ position = "before" payload = ''' if G.GAME.modifiers.cry_ccd then for k, v in pairs(G.playing_cards) do - v:set_ability(Cryptid.random_consumable('cry_ccd',{"no_doe", "no_grc"}, nil, nil, true), true, nil) + v:set_ability(Cryptid.random_consumable('cry_ccd', nil, nil, nil, true), true, nil) end end ''' @@ -56,6 +56,54 @@ position = "before" payload = "if self.ability.set == 'Enhanced' then self.ability.consumeable = nil end" match_indent = true +# Remove CCD from enhanced cards +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''if center.consumeable then + self.ability.consumeable = center.config''' +position = "after" +payload = ''' +else + self.ability.consumeable = nil + ''' +match_indent = true + +#Fixes for negative CCD cards +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = """ +if self.edition.type == 'negative' and self.ability.consumeable then + badges[#badges + 1] = 'negative_consumable' +elseif self.edition.type == 'negative' and (self.ability.set == 'Enhanced' or self.ability.set == 'Default') then + badges[#badges + 1] = 'negative_playing_card' +""" +position = "at" +payload = """ +if self.edition.type == 'negative' and self.playing_card then + badges[#badges + 1] = 'negative_playing_card' +elseif self.edition.type == 'negative' and self.ability.consumeable then + badges[#badges + 1] = 'negative_consumable' +""" +match_indent = true + +[[patches]] +[patches.pattern] +target = """=[SMODS _ "src/overrides.lua"]""" +pattern = """if self.ability.consumeable then""" +position = "at" +payload = """if self.ability.consumeable and not self.playing_card then""" +match_indent = true + +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = """if self.ability.consumeable then""" +position = "at" +payload = """if self.ability.consumeable and not self.playing_card then""" +match_indent = true + # ui, ui, ui [[patches]] [patches.pattern] @@ -106,4 +154,4 @@ if specific_vars and specific_vars.ccd then end end ''' -match_indent = true \ No newline at end of file +match_indent = true diff --git a/Cryptid/lovely/code.toml b/Cryptid/lovely/code.toml index 2d5ff08..eac6113 100644 --- a/Cryptid/lovely/code.toml +++ b/Cryptid/lovely/code.toml @@ -80,16 +80,6 @@ if G.GAME.current_round.semicolon then end ''' -# Semicolon - end screen text -[[patches]] -[patches.regex] -target = "functions/common_events.lua" -pattern = '''localize\('ph_mr_bones'\)..' '\}, colours = \{G.C.FILTER''' -position = 'at' -# match_indent = true -line_prepend = '' -payload = '''(G.GAME.current_round.semicolon and ";" or localize('ph_mr_bones'))..' '}, colours = {(G.GAME.current_round.semicolon and G.C.SET.Code or G.C.FILTER)''' - # Semicolon - polished UI [[patches]] [patches.pattern] @@ -103,9 +93,9 @@ match_indent = true [[patches]] [patches.pattern] target = "functions/common_events.lua" -pattern = '''{n=G.UIT.T, config={text = localize('$')..config.dollars, scale = 1.2*scale, colour = G.C.WHITE, shadow = true, juice = true}}''' +pattern = '''{n=G.UIT.T, config={text = localize('$')..format_ui_value(config.dollars), scale = 1.2*scale, colour = G.C.WHITE, shadow = true, juice = true}}''' position = "at" -payload = '''{n=G.UIT.T, config={text = not G.GAME.current_round.semicolon and localize('$')..config.dollars or ';', scale = 1.2*scale, colour = G.C.WHITE, shadow = true, juice = true}}''' +payload = '''{n=G.UIT.T, config={text = not G.GAME.current_round.semicolon and localize('$')..format_ui_value(config.dollars) or ';', scale = 1.2*scale, colour = G.C.WHITE, shadow = true, juice = true}}''' match_indent = true # Semicolon - polished UI @@ -117,17 +107,6 @@ position = "at" payload = '''{n=G.UIT.R, config={id = 'cash_out_button', align = "cm", padding = 0.1, minw = 7, r = 0.15, colour = G.GAME.current_round.semicolon and G.C.SET.Code or G.C.ORANGE, shadow = true, hover = true, one_press = true, button = 'cash_out', focus_args = {snap_to = true}}, nodes={''' match_indent = true -# Semicolon - reset value at start of round -[[patches]] -[patches.pattern] -target = "functions/state_events.lua" -pattern = "G.GAME.blind:set_blind(G.GAME.round_resets.blind)" -position = "after" -payload = ''' -G.GAME.current_round.semicolon = false -''' -match_indent = true - # Delete - placeholder booster, in the case that all are deleted [[patches]] [patches.regex] @@ -160,7 +139,7 @@ end ''' match_indent = true -# Delete - multiuse 2 +# Multiuse + Function:// code [[patches]] [patches.pattern] target = "functions/button_callbacks.lua" @@ -182,26 +161,149 @@ if cry_muse then scale = 1.1, hold = 0.6, major = card, - backdrop_colour = G.C.SECONDARY_SET[card.config.center.set], + backdrop_colour = G.C.SET[card.config.center.set], align = 'bm', offset = {x = 0, y = 0.2} }) delay(0.8) - local _area = area ~= G.pack_cards and area or G.consumeables - draw_card(G.play, _area, 1, 'up', true, card, nil, true) + if card.playing_card then + draw_card(G.play, G.hand, 1, 'up', true, card, nil, true) + elseif not G.GAME.modifiers.cry_beta then + if to_big(#G.consumeables.cards) < to_big(G.consumeables.config.card_limit) then + draw_card(G.play, G.consumeables, 1, 'up', true, card, nil, true) + else card:start_dissolve() + end + else + if to_big(#G.jokers.cards) < to_big(G.jokers.config.card_limit) then + draw_card(G.play, G.jokers, 1, 'up', true, card, nil, true) + else card:start_dissolve() + end + end +end +if not G.GAME.modifiers.cry_beta then -- function code + fallback + if card.ability.cry_function_counter == 1 then + G.E_MANAGER:add_event(Event({ + func = function() + local new_card = create_card( + "Consumeables", + G.consumeables, + nil, + nil, + nil, + nil, + G.GAME.cry_function_cards[2], + "cry_cryfunction" + ) + new_card:add_to_deck() + new_card.ability.cry_function_sticker = true + new_card.ability.cry_function_counter = 2 + G.consumeables:emplace(new_card) + G.GAME.consumeable_buffer = 0 + return true + end, + })) + elseif card.ability.cry_function_counter == 2 then + G.E_MANAGER:add_event(Event({ + func = function() + local new_card = create_card( + "Consumeables", + G.consumeables, + nil, + nil, + nil, + nil, + G.GAME.cry_function_cards[3], + "cry_cryfunction" + ) + new_card:add_to_deck() + G.consumeables:emplace(new_card) + G.GAME.consumeable_buffer = 0 + return true + end, + })) + elseif card.ability.cry_function_sticker and not card.ability.cry_function_counter == 3 then + G.E_MANAGER:add_event(Event({ + func = function() + local new_card = create_card( + "Consumeables", + G.consumeables, + nil, + nil, + nil, + nil, + nil, + "cry_cryfunction" + ) + new_card:add_to_deck() + G.consumeables:emplace(new_card) + G.GAME.consumeable_buffer = 0 + return true + end, + })) + end + else + if card.ability.cry_function_counter == 1 then + G.E_MANAGER:add_event(Event({ + func = function() + local new_card = create_card( + "Consumeables", + G.jokers, + nil, + nil, + nil, + nil, + G.GAME.cry_function_cards[2], + "cry_cryfunction" + ) + new_card:add_to_deck() + new_card.ability.cry_function_sticker = true + new_card.ability.cry_function_counter = 2 + G.jokers:emplace(new_card) + G.GAME.consumeable_buffer = 0 + return true + end, + })) + elseif card.ability.cry_function_counter == 2 then + G.E_MANAGER:add_event(Event({ + func = function() + local new_card = create_card( + "Consumeables", + G.jokers, + nil, + nil, + nil, + nil, + G.GAME.cry_function_cards[3], + "cry_cryfunction" + ) + new_card:add_to_deck() + G.jokers:emplace(new_card) + G.GAME.consumeable_buffer = 0 + return true + end, + })) + elseif card.ability.cry_function_sticker and not card.ability.cry_function_counter == 3 then + G.E_MANAGER:add_event(Event({ + func = function() + local new_card = create_card( + "Consumeables", + G.jokers, + nil, + nil, + nil, + nil, + nil, + "cry_cryfunction" + ) + new_card:add_to_deck() + G.jokers:emplace(new_card) + G.GAME.consumeable_buffer = 0 + return true + end, + })) + end end -''' -match_indent = true - -# Delete - init table to avoid headaches -[[patches]] -[patches.pattern] -target = "game.lua" -pattern = '''ecto_minus = 1,''' -position = "after" -payload = ''' -cry_banished_keys = {}, ''' match_indent = true @@ -311,18 +413,18 @@ match_indent = true [[patches]] [patches.pattern] target = "game.lua" -pattern = "{card_limit = self.GAME.starting_params.consumable_slots, type = 'joker', highlight_limit = 1})" +pattern = "{card_limit = self.GAME.starting_params.consumable_slots, type = 'joker', highlight_limit = 1, negative_info = 'consumable'})" position = "at" -payload = "{card_limit = self.GAME.starting_params.consumable_slots, type = 'joker', highlight_limit = 1e100})" +payload = "{card_limit = self.GAME.starting_params.consumable_slots, type = 'joker', highlight_limit = 1e100, negative_info = 'consumable'})" match_indent = true # Increase highlight limit for jokers [[patches]] [patches.pattern] target = "game.lua" -pattern = "{card_limit = self.GAME.starting_params.joker_slots, type = 'joker', highlight_limit = 1})" +pattern = "{card_limit = self.GAME.starting_params.joker_slots, type = 'joker', highlight_limit = 1, negative_info = 'joker'})" position = "at" -payload = "{card_limit = self.GAME.starting_params.joker_slots, type = 'joker', highlight_limit = 1e100})" +payload = "{card_limit = self.GAME.starting_params.joker_slots, type = 'joker', highlight_limit = 1e100, negative_info = 'joker'})" match_indent = true # Satellite Uplink @@ -367,6 +469,21 @@ text = G.GAME.cry_exploit_override or text ''' match_indent = true +# Multiuse localization +[[patches]] +[patches.pattern] +target = '''functions/common_events.lua''' +pattern = '''if main_end then''' +position = "before" +payload = ''' +if cfg and cfg.cry_multiuse then + local loc = {} + localize{type = 'other', key = 'cry_multiuse', nodes = loc, vars = {cfg.cry_multiuse}} + desc_nodes[#desc_nodes+1] = loc[1] +end +''' +match_indent = true + # Double Tag makes exact copy of rework tag [[patches]] [patches.pattern] @@ -382,3 +499,284 @@ payload = ''' add_tag(tag) ''' match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = "G.GAME.last_hand_played = text" +position = "after" +payload = ''' +G.GAME.last_hand_played_cards = {} +for i = 1, #G.play.cards do + G.GAME.last_hand_played_cards[i] = G.play.cards[i].sort_id +end +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "cardarea.lua" +pattern = "local text,disp_text,poker_hands = G.FUNCS.get_poker_hand_info(self.highlighted)" +position = "after" +payload = ''' +local text,disp_text,poker_hands +if self == G.hand then + local tbl = {} + for i, v in pairs(G.jokers.cards) do + if v.base.nominal and v.base.suit then + tbl[#tbl+1] = v + end + end + text,disp_text,poker_hands = G.FUNCS.get_poker_hand_info(Cryptid.table_merge(self.highlighted, tbl)) +else + text,disp_text,poker_hands = G.FUNCS.get_poker_hand_info(self.highlighted) +end +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = "local text,disp_text,poker_hands,scoring_hand,non_loc_disp_text = G.FUNCS.get_poker_hand_info(G.play.cards)" +position = "after" +payload = ''' +local tbl = {} +for i, v in pairs(G.jokers.cards) do + if v.base.nominal and v.base.suit then + tbl[#tbl+1] = v + end +end +local text,disp_text,poker_hands,scoring_hand,non_loc_disp_text = G.FUNCS.get_poker_hand_info(Cryptid.table_merge(G.play.cards, tbl)) +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = "local text = {ref_table = args.ref_table, ref_value = args.ref_value, letters = {}, current_position = string.len(args.ref_table[args.ref_value])}" +position = "at" +payload = ''' +local text = {ref_table = args.ref_table, ref_value = args.ref_value, letters = {}, current_position = string.len(args.ref_table[args.ref_value] or "")} +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = ''' + UIBox_button({button = 'your_collection_enhancements', label = {localize('b_enhanced_cards')}, minw = 5}), + UIBox_button({button = 'your_collection_seals', label = {localize('b_seals')}, minw = 5, id = 'your_collection_seals'}), + UIBox_button({button = 'your_collection_editions', label = {localize('b_editions')}, count = G.DISCOVER_TALLIES.editions, minw = 5, id = 'your_collection_editions'}), +''' +position = "at" +payload = ''' + enhanced, + seals, + editions, +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = ''' + local t = create_UIBox_generic_options({ back_func = G.STAGE == G.STAGES.RUN and 'options' or 'exit_overlay_menu', contents = { +''' +position = "before" +payload = ''' + local use_pointer = G.GAME.USING_POINTER or G.GAME.POINTER_COLLECTION + local enhanced = (not use_pointer and UIBox_button({button = 'your_collection_enhancements', label = {localize('b_enhanced_cards')}, minw = 5})) + or UIBox_button({button = 'your_collection_create_card_rank', label = {localize('b_playing_cards')}, minw = 5, minh = 3.4, id = 'your_collection_create_card'}) + local seals = (not use_pointer and UIBox_button({button = 'your_collection_seals', label = {localize('b_seals')}, minw = 5, id = 'your_collection_seals'})) or nil + local editions = not use_pointer and UIBox_button({button = 'your_collection_editions', label = {localize('b_editions')}, count = G.DISCOVER_TALLIES.editions, minw = 5, id = 'your_collection_editions'}) or nil + + local blinds = UIBox_button({button = 'your_collection_blinds', label = {localize('b_blinds')}, count = G.DISCOVER_TALLIES.blinds, minw = 5, minh = (use_pointer and 2.8 or 2.0), id = 'your_collection_blinds', focus_args = {snap_to = true}}) + local other = not use_pointer and UIBox_button({button = 'your_collection_other_gameobjects', label = {localize('k_other')}, minw = 5, id = 'your_collection_other_gameobjects', focus_args = {snap_to = true}}) or nil + + local decks = not use_pointer and UIBox_button({button = 'your_collection_decks', label = {localize('b_decks')}, count = G.DISCOVER_TALLIES.backs, minw = 5}) or nil + local vouchers = UIBox_button({button = 'your_collection_vouchers', label = {localize('b_vouchers')}, count = G.DISCOVER_TALLIES.vouchers, minw = 5, id = 'your_collection_vouchers', minh = use_pointer and 2.0}) +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = ''' +UIBox_button({button = 'your_collection_blinds', label = {localize('b_blinds')}, count = G.DISCOVER_TALLIES.blinds, minw = 5, minh = 2.0, id = 'your_collection_blinds', focus_args = {snap_to = true}}),UIBox_button({button = 'your_collection_other_gameobjects', label = {localize('k_other')}, minw = 5, id = 'your_collection_other_gameobjects', focus_args = {snap_to = true}}), +''' +position = "at" +payload = ''' + blinds, + other +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = ''' + UIBox_button({button = 'your_collection_decks', label = {localize('b_decks')}, count = G.DISCOVER_TALLIES.backs, minw = 5}), + UIBox_button({button = 'your_collection_vouchers', label = {localize('b_vouchers')}, count = G.DISCOVER_TALLIES.vouchers, minw = 5, id = 'your_collection_vouchers'}), +''' +position = "at" +payload = ''' + decks, + vouchers, +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = '''=[SMODS _ "src/overrides.lua"]''' +pattern = ''' + if v.discovered and not v.alerted then + blinds_to_be_alerted[#blinds_to_be_alerted + 1] = card + end +''' +position = "at" +payload = ''' + if v.discovered and not v.alerted then + blinds_to_be_alerted[#blinds_to_be_alerted + 1] = card + end + card.click = function() + if G.GAME.USING_POINTER then + local self = v + local b = self + if not b.no_doe and not b.hidden and not b.no_pointer then + local bl = "Boss" + G.GAME.round_resets.blind_choices[bl] = b.key + if G.blind_select or G.GAME.blind_on_deck ~= "Boss" then + if G.blind_select then + G.blind_select:remove() + G.blind_prompt_box:remove() + G.STATE_COMPLETE = false + end + else + G.GAME.blind:disable() + G.GAME.blind:set_blind(G.P_BLINDS[b.key]) + end + G.FUNCS.exit_overlay_menu_code() + if G.GAME.CODE_DESTROY_CARD then + G.GAME.CODE_DESTROY_CARD:start_dissolve() + G.GAME.CODE_DESTROY_CARD = nil + end + end + end + end +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = '''=[SMODS _ "src/overrides.lua"]''' +pattern = ''' + for k, _hand in pairs(SMODS.PokerHands) do + results[k] = _hand.evaluate(parts, hand) or {} + end +''' +position = "after" +payload = ''' + local hands = { + G.GAME.hands.cry_Declare0, + G.GAME.hands.cry_Declare1, + G.GAME.hands.cry_Declare2, + } + for i, v in pairs(hands) do + if v.index then + local is_this_hand = true + local cards = {} + if v.declare_cards then + local satisfied = true + for i, v in pairs(v.declare_cards) do + local rank + local suit + for i2, v2 in pairs(hand) do + if not v2.canfit then + if SMODS.has_no_rank(v2) and v.rank == "rankless" or v2:get_id() == v.rank then + if v2:is_suit(v.suit) or (v.suit == "suitless" and SMODS.has_no_suit(v2)) or not v.suit then + v2.canfit = true + end + end + end + if not v2.marked and not (suit and rank) then + if SMODS.has_no_rank(v2) and v.rank == "rankless" or v2:get_id() == v.rank then rank = true end + if v2:is_suit(v.suit) or (v.suit == "suitless" and SMODS.has_no_suit(v2)) or not v.suit then suit = true end + if not (suit and rank) then + suit = false + rank = false + end + if suit and rank then + cards[#cards+1] = v2 + v2.marked = true + end + end + end + if not rank or not suit then satisfied = false end + end + for i2, v2 in pairs(hand) do + v2.marked = false + if v2.canfit then + cards[#cards+1] = v2 + v2.canfit = nil + end + end + if not satisfied then is_this_hand = false end + end + if is_this_hand then + key = "cry_Declare"..tostring(v.index) + local tbl = {cards} + local skey = ({ + [0] = "Flush", + [1] = "Straight", + [2] = "Full House" + })[v.index] + results[key] = tbl + results[skey] = tbl + if skey == "Full House" then + results["Three of a Kind"] = tbl + results["Two Pair"] = tbl + results["Pair"] = tbl + end + results.top = tbl + else + key = "cry_Declare"..tostring(v.index) + results[key] = {} + end + end + end + if not results["cry_Declare0"] then results["cry_Declare0"] = {} end + if not results["cry_Declare1"] then results["cry_Declare1"] = {} end + if not results["cry_Declare2"] then results["cry_Declare2"] = {} end +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = '''=[SMODS _ "src/overrides.lua"]''' +pattern = ''' +for k, v in pairs(SMODS.PokerHands[key]) do +''' +position = "at" +payload = ''' +for k, v in pairs(SMODS.PokerHands[key] or {}) do +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = '''card.lua''' +pattern = ''' + for k, v in pairs(G.P_CENTER_POOLS.Planet) do + if v.config.hand_type == G.GAME.last_hand_played then + _planet = v.key + end + end +''' +position = "after" +payload = ''' +if (G.GAME.last_hand_played == "cry_Declare0" or G.GAME.last_hand_played == "cry_Declare1" or G.GAME.last_hand_played == "cry_Declare2") and Cryptid.enabled("c_cry_voxel") == true then + _planet = "c_cry_voxel" +end +''' +match_indent = true + diff --git a/Cryptid/lovely/conveyor.toml b/Cryptid/lovely/conveyor.toml index 0dde77d..1812afa 100644 --- a/Cryptid/lovely/conveyor.toml +++ b/Cryptid/lovely/conveyor.toml @@ -3,13 +3,13 @@ version = "1.0.0" dump_lua = true priority = -1 -# Conveyor Deck - Don't sort cards +# Conveyor Deck and the decision - Don't sort cards [[patches]] [patches.pattern] target = "cardarea.lua" pattern = "table.sort(self.cards, function (a, b) return a.T.x + a.T.w/2 - 100*((a.pinned and not a.ignore_pinned) and a.sort_id or 0) < b.T.x + b.T.w/2 - 100*((b.pinned and not b.ignore_pinned) and b.sort_id or 0) end)" position = "at" -payload = "if not G.GAME.modifiers.cry_conveyor then table.sort(self.cards, function (a, b) return a.T.x + a.T.w/2 - 100*((a.pinned and not a.ignore_pinned) and a.sort_id or 0) < b.T.x + b.T.w/2 - 100*((b.pinned and not b.ignore_pinned) and b.sort_id or 0) end) end" +payload = "if not G.GAME.modifiers.cry_conveyor and not G.GAME.cry_fastened then table.sort(self.cards, function (a, b) return a.T.x + a.T.w/2 - 100*((a.pinned and not a.ignore_pinned) and a.sort_id or 0) < b.T.x + b.T.w/2 - 100*((b.pinned and not b.ignore_pinned) and b.sort_id or 0) end) end" match_indent = true # Start of round effects diff --git a/Cryptid/lovely/cube.toml b/Cryptid/lovely/cube.toml deleted file mode 100644 index a3246ba..0000000 --- a/Cryptid/lovely/cube.toml +++ /dev/null @@ -1,27 +0,0 @@ -[manifest] -version = "1.0.0" -dump_lua = true -priority = -1 - -# Joker Lock -[[patches]] -[patches.pattern] -target = "functions/common_events.lua" -pattern = "elseif v.enhancement_gate then" -position = "before" -payload = ''' -elseif v.source_gate then - if v.source_gate ~= _append then - add = nil - else - add = true - end -elseif v.joker_gate then - add = nil - for kk, vv in pairs(G.jokers.cards) do - if vv.ability.name == v.joker_gate then - add = true - end - end -''' -match_indent = true \ No newline at end of file diff --git a/Cryptid/lovely/equilibrium.toml b/Cryptid/lovely/equilibrium.toml index 65cef87..5c60d43 100644 --- a/Cryptid/lovely/equilibrium.toml +++ b/Cryptid/lovely/equilibrium.toml @@ -10,21 +10,4 @@ target = "game.lua" pattern = "G.shop_booster.T.y, G.CARD_W*1.27, G.CARD_H*1.27, G.P_CARDS.empty, G.P_CENTERS[G.GAME.current_round.used_packs[i]], {bypass_discovery_center = true, bypass_discovery_ui = true})" position = "at" payload = "G.shop_booster.T.y, G.CARD_W*(G.P_CENTERS[G.GAME.current_round.used_packs[i]].set == 'Booster' and 1.27 or 1), G.CARD_H*(G.P_CENTERS[G.GAME.current_round.used_packs[i]].set == 'Booster' and 1.27 or 1), G.P_CARDS.empty, G.P_CENTERS[G.GAME.current_round.used_packs[i]], {bypass_discovery_center = true, bypass_discovery_ui = true})" -match_indent = true - -# scaling issues when reclaiming Overstock -[[patches]] -[patches.pattern] -target = "functions/UI_definitions.lua" -pattern = "G.GAME.shop.joker_max*1.02*G.CARD_W," -position = "at" -payload = "math.min(G.GAME.shop.joker_max,4)*1.02*G.CARD_W," -match_indent = true - -[[patches]] -[patches.pattern] -target = "functions/common_events.lua" -pattern = "G.shop_jokers.T.w = G.GAME.shop.joker_max*1.01*G.CARD_W" -position = "at" -payload = "G.shop_jokers.T.w = math.min(G.GAME.shop.joker_max,4)*1.02*G.CARD_W" match_indent = true \ No newline at end of file diff --git a/Cryptid/lovely/lib_gameset.toml b/Cryptid/lovely/lib_gameset.toml index 962689d..4586a7b 100644 --- a/Cryptid/lovely/lib_gameset.toml +++ b/Cryptid/lovely/lib_gameset.toml @@ -7,9 +7,9 @@ priority = -1 [[patches]] [patches.pattern] target = "card_character.lua" -pattern = 'self.children.card.states.visible = false' -position = "before" -payload = "self.children.card:set_ability(G.P_CENTERS.j_jolly)" +pattern = 'self.children.card = Card(self.T.x, self.T.y, G.CARD_W, G.CARD_H, G.P_CARDS.empty, args.center or G.P_CENTERS.j_joker, {bypass_discovery_center = true})' +position = "at" +payload = 'self.children.card = Card(self.T.x, self.T.y, G.CARD_W, G.CARD_H, G.P_CARDS.empty, args.center or G.P_CENTERS.j_jolly, {bypass_discovery_center = true})' match_indent = true [[patches]] @@ -26,7 +26,7 @@ match_indent = true target = "game.lua" pattern = 'self:load_profile(G.SETTINGS.profile or 1)' position = "before" -payload = '''Cryptid.profile_prefix = Jen and "J" or "M" +payload = '''Cryptid.profile_prefix = "M" if type(G.SETTINGS.profile) ~= "string" or G.SETTINGS.profile:sub(1, #Cryptid.profile_prefix) ~= Cryptid.profile_prefix then G.SETTINGS.profile = Cryptid.profile_prefix .. "1" end @@ -196,4 +196,4 @@ target = "functions/common_events.lua" pattern = "elseif _c.set == 'Tag' then" position = "before" payload = "elseif _c.set == 'Back' or _c.set == 'Blind' then localize{type = 'descriptions', key = _c.key, set = _c.set, nodes = desc_nodes, vars = specific_vars or {}}" -match_indent = true \ No newline at end of file +match_indent = true diff --git a/Cryptid/lovely/lib_https.toml b/Cryptid/lovely/lib_https.toml index 67b8a4d..01844fe 100644 --- a/Cryptid/lovely/lib_https.toml +++ b/Cryptid/lovely/lib_https.toml @@ -3,23 +3,6 @@ version = "1.0.0" dump_lua = true priority = -1 -# hi it's me toneblock and i'm being stupid again! (Game:update inject) -[[patches]] -[patches.pattern] -target = "game.lua" -pattern = '''if G.FILE_HANDLER and G.FILE_HANDLER and G.FILE_HANDLER.update_queued and (''' -position = "before" -payload = ''' -if not Cryptid.member_count_delay then Cryptid.member_count_delay = 0 end -if (Cryptid.member_count_delay > 5) or not Cryptid.member_count then -- it doesn't need to update this frequently? but it also doesn't need to be higher tbh... - if Cryptid.update_member_count then Cryptid.update_member_count() end -- i honestly hate nil checks like this, wish there was a shorthand - Cryptid.member_count_delay = 0 -else - Cryptid.member_count_delay = Cryptid.member_count_delay + dt -end -''' -match_indent = true - # call Cryptid.update_member_count() whenever the collection is opened to ensure it updates properly on title collection if it can (better than running it on loc_vars) # it's not computationally intense at all, so whatever [[patches]] @@ -32,43 +15,13 @@ if Cryptid.update_member_count then Cryptid.update_member_count() end ''' match_indent = true -# notice if https is disabled (by default) -# also does some other things since this is patching in the same spot (SDM0 easter egg) +# test [[patches]] [patches.pattern] target = "functions/common_events.lua" -pattern = "if _c.set == 'Other' then" +pattern = "if _c.specific_vars then specific_vars = _c.specific_vars end" position = "before" payload = ''' -if _c.name == 'cry-membershipcard' or _c.name == 'cry-membershipcardtwo' then - if not Cryptid_config["HTTPS Module"] then - if G.localization.descriptions.Other.cry_https_disabled then - main_end = {} - localize{type = 'other', key = 'cry_https_disabled', nodes = main_end, vars = {}} - main_end = main_end[1] - end - end -end -if _c.name == 'cry-translucent Joker' then - if G.jokers and G.jokers.cards then - for k, v in ipairs(G.jokers.cards) do - if (v.edition and v.edition.negative) and (G.localization.descriptions.Other.remove_negative)then - main_end = {} - localize{type = 'other', key = 'remove_negative', nodes = main_end, vars = {}} - main_end = main_end[1] - break - end - end - end -end -if _c.name == 'cry-blurred Joker' then - if (SMODS.Mods["sdm0sstuff"] or {}).can_load then - if G.localization.descriptions.Other.blurred_sdm0 then - main_end = {} - localize{type = 'other', key = 'blurred_sdm0', nodes = main_end, vars = {}} - main_end = main_end[1] - end - end -end +if _c.plua_extra then main_start = _c.plua_extra end ''' -match_indent = true \ No newline at end of file +match_indent = true diff --git a/Cryptid/lovely/lib_misc.toml b/Cryptid/lovely/lib_misc.toml index e0264de..dfe4b1e 100644 --- a/Cryptid/lovely/lib_misc.toml +++ b/Cryptid/lovely/lib_misc.toml @@ -42,15 +42,6 @@ end ''' match_indent = true -# Patch related crash -[[patches]] -[patches.pattern] -target = "card.lua" -pattern = "if not initial then G.GAME.blind:debuff_card(self) end" -position = "at" -payload = "if not initial and G.GAME and G.GAME.blind then G.GAME.blind:debuff_card(self) end" -match_indent = true - # Draw midground layer [[patches]] [patches.pattern] @@ -67,16 +58,6 @@ end ''' match_indent = true - -# Custom variables in info queue -[[patches]] -[patches.pattern] -target = "functions/common_events.lua" -pattern = "function generate_card_ui(_c, full_UI_table, specific_vars, card_type, badges, hide_desc, main_start, main_end)" -position = "after" -payload = "if _c.specific_vars then specific_vars = _c.specific_vars end" -match_indent = true - # Fix not all cards returning to hand on big hands [[patches]] [patches.pattern] @@ -108,26 +89,6 @@ position = "at" payload = "if not G.SAVED_GAME or not G.SAVED_GAME.VERSION or G.SAVED_GAME.VERSION < '0.9.2' then" match_indent = true -# Register banned bosses for rush hour -# Also initializes disabled/enabled cards -[[patches]] -[patches.pattern] -target = "game.lua" -pattern = "set_profile_progress()" -position = "before" -payload = ''' -for i = 1, #G.CHALLENGES do - if (G.CHALLENGES[i].id == 'c_cry_rush_hour' or G.CHALLENGES[i].id == 'c_cry_rush_hour_ii' or G.CHALLENGES[i].id == 'c_cry_rush_hour_iii') and #G.CHALLENGES[i].restrictions.banned_other == 0 then - for k, v in pairs(G.P_BLINDS) do - if k ~= "bl_cry_clock" and k ~= "bl_cry_lavender_loop" and v.boss then - G.CHALLENGES[i].restrictions.banned_other[#G.CHALLENGES[i].restrictions.banned_other+1] = {id = k, type = 'blind'} - end - end - end -end -''' -match_indent = true - # Prevent Jokers from spitting empty messages [[patches]] [patches.pattern] @@ -170,6 +131,16 @@ position = "before" payload = ''' Cryptid = {} Cryptid.aliases = {} +Cryptid.pointerblist = {} +Cryptid.pointerblistrarity = {} +Cryptid.mod_gameset_whitelist = {} +Cryptid.ascension_numbers = {} + +Cryptid.pin_debuff = {} +Cryptid.circus_rarities = { + --format {base_mult = ..., loc_key = ..., rarity=..., order=...} +} + function cry_format(...) return ... end @@ -192,7 +163,9 @@ end ''' position = "after" payload = ''' -SMODS.calculate_context{cry_creating_card = true, card = card} +if G.deck then + SMODS.calculate_context{cry_creating_card = true, card = card} +end ''' match_indent = true diff --git a/Cryptid/lovely/misc.toml b/Cryptid/lovely/misc.toml index 4202722..7798c06 100644 --- a/Cryptid/lovely/misc.toml +++ b/Cryptid/lovely/misc.toml @@ -15,6 +15,7 @@ new_card.from_copy = true match_indent = true # Update value of Monsters created via copy_card +# Also make copied cards lose their hooks [[patches]] [patches.pattern] target = 'functions/common_events.lua' @@ -22,6 +23,7 @@ pattern = "if not strip_edition then" position = 'before' payload = ''' if new_card.ability.name == "cry-longboi" then new_card:set_ability(new_card.config.center) end +if new_card.ability.cry_hooked then new_card.ability.cry_hooked = nil end ''' match_indent = true @@ -29,7 +31,7 @@ match_indent = true [[patches]] [patches.pattern] target = "card.lua" -pattern = "if self.ability.name == 'Campfire' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and self.ability.x_mult > 1 then" +pattern = "if self.ability.name == 'Campfire' and G.GAME.blind.boss and self.ability.x_mult > 1 then" position = "at" payload = ''' if self.ability.name == 'Campfire' and G.GAME.blind.boss and not (G.GAME.blind.config and G.GAME.blind.config.bonus) and to_big(self.ability.x_mult) > to_big(1) then @@ -56,13 +58,23 @@ if to_big(self.ability.x_mult) > to_big(1) then ''' match_indent = true +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "if self.ability.x_mult - self.ability.extra <= 1 then" +position = "at" +payload = ''' +if to_big(self.ability.x_mult) - to_big(self.ability.extra) <= to_big(1) then +''' +match_indent = true + [[patches]] [patches.pattern] target = "card.lua" pattern = "if self.ability.name ~= 'Seeing Double' and self.ability.x_mult > 1 and (self.ability.type == '' or next(context.poker_hands[self.ability.type])) then" position = "at" payload = ''' -if self.ability.name ~= 'Seeing Double' and to_big(self.ability.x_mult) > to_big(1) and (self.ability.type == '' or next(context.poker_hands[self.ability.type])) then +if self.ability.name ~= 'Seeing Double' and to_big(self.ability.x_mult) > to_big(1) and (self.ability.type == '' or (context.poker_hands[self.ability.type] and next(context.poker_hands[self.ability.type]))) then ''' match_indent = true @@ -82,7 +94,7 @@ target = "card.lua" pattern = "if self.ability.t_mult > 0 and next(context.poker_hands[self.ability.type]) then" position = "at" payload = ''' -if to_big(self.ability.t_mult) > to_big(0) and next(context.poker_hands[self.ability.type]) then +if to_big(self.ability.t_mult) > to_big(0) and (context.poker_hands[self.ability.type] and next(context.poker_hands[self.ability.type])) then ''' match_indent = true @@ -92,7 +104,7 @@ target = "card.lua" pattern = "if self.ability.t_chips > 0 and next(context.poker_hands[self.ability.type]) then" position = "at" payload = ''' -if to_big(self.ability.t_chips) > to_big(0) and next(context.poker_hands[self.ability.type]) then +if to_big(self.ability.t_chips) > to_big(0) and (context.poker_hands[self.ability.type] and next(context.poker_hands[self.ability.type])) then ''' match_indent = true @@ -192,7 +204,7 @@ target = "functions/misc_functions.lua" pattern = "function localize(args, misc_cat)" position = "after" payload = ''' -if args and args.vars then +if args and args.vars and type(args.vars) == "table" then local reset = {} for i, j in pairs(args.vars) do if type(j) == 'table' then @@ -208,21 +220,6 @@ end ''' match_indent = true -# Compat UI for Old Blueprint and Gemini - -# I deleted the patches --Jevonn (test) - -# calculate wheel fail (for Wheel of Hope) -[[patches]] -[patches.pattern] -target = "card.lua" -pattern = "if self.ability.name == 'Ectoplasm' or self.ability.name == 'Hex' or pseudorandom('wheel_of_fortune') < G.GAME.probabilities.normal/self.ability.extra then" -position = "after" -payload = ''' -if self.ability.name == 'The Wheel of Fortune' then self.cry_wheel_success = true end -''' -match_indent = false - # no "Again!" text if a card will shatter [[patches]] [patches.pattern] @@ -249,19 +246,11 @@ target = "functions/button_callbacks.lua" pattern = '''add_tag(_tag.config.ref_table)''' position = "at" payload = ''' -add_tag( next(SMODS.find_card('j_cry_kittyprinter')) and Tag('tag_cry_cat') or _tag.config.ref_table, true) +local tag_key = Cryptid.get_next_tag() +add_tag(tag_key and Tag(tag_key) or _tag.config.ref_table, true) ''' match_indent = true -# Energia - don't add tags from save load -[[patches]] -[patches.pattern] -target = "game.lua" -pattern = '''add_tag(_tag)''' -position = "at" -payload = '''add_tag(_tag, nil, true)''' -match_indent = true - # Beta Deck - merge slots [[patches]] [patches.pattern] @@ -321,22 +310,20 @@ match_indent = true # More Beta Deck fixes [[patches]] [patches.pattern] -target = "functions/state_events.lua" -pattern = '''for i=1, #G.jokers.cards + #G.consumeables.cards do''' -position = "at" +target = '''=[SMODS _ "src/utils.lua"]''' +pattern = '''-- TARGET: add your own CardAreas for joker evaluation''' +position = "after" payload = ''' -local numcards = #G.jokers.cards + #G.consumeables.cards -if G.GAME.modifiers.cry_beta then numcards = #G.jokers.cards end -for i=1, numcards do''' +if G.GAME.modifiers.cry_beta then t = {G.jokers, G.vouchers} end''' match_indent = true -# Poker Hand display can have enhancements +# Fix Boredom crash (somehow) [[patches]] [patches.pattern] -target = "functions/UI_definitions.lua" -pattern = '''local card = Card(0,0, 0.5*G.CARD_W, 0.5*G.CARD_H, G.P_CARDS[v[1]], G.P_CENTERS.c_base)''' +target = '''=[SMODS _ "src/utils.lua"]''' +pattern = '''if eff.retrigger_flag then SMODS.calculate_effect(eff, eff.card); j = j+1; _, eff = next(reps[j]) end''' position = "at" -payload = '''local card = Card(0,0, 0.5*G.CARD_W, 0.5*G.CARD_H, G.P_CARDS[v[1]], G.P_CENTERS[v[3] or 'c_base'])''' +payload = '''if eff.retrigger_flag and reps[j+1] ~= nil then SMODS.calculate_effect(eff, eff.card); j = j+1; _, eff = next(reps[j]) end''' match_indent = true # Adds G.GAME.modifiers.cry_forced_draw_amount @@ -381,7 +368,7 @@ if G.GAME.oldbpfactor then G.GAME.oldbpfactor = math.max(G.GAME.oldbpfactor - G. match_indent = true # Make Loopy reset here so it retriggers everything before resetting regardless of position -# Makes Old Blueprint self-destruct after triggering other end of round effects +# Calculate Destroyed cards from sus, It's done here and not in the sus joker code so that it doesn't trigger these multiple times [[patches]] [patches.pattern] target = "functions/state_events.lua" @@ -394,7 +381,13 @@ for _, v in pairs(find_joker("cry-loopy")) do card_eval_status_text(v, 'extra', nil, nil, nil, {message = localize("k_reset"), colour = G.C.GREEN}) end end -SMODS.calculate_context{end_of_round2 = true} +for _, v in pairs(G.deck.cards) do + v.sus = nil +end +if G.GAME.sus_cards then + SMODS.calculate_context({ remove_playing_cards = true, removed = G.GAME.sus_cards }) + G.GAME.sus_cards = nil +end ''' match_indent = true @@ -424,25 +417,9 @@ target = "functions/UI_definitions.lua" pattern = "local _tag = Tag(G.GAME.round_resets.blind_tags[blind_choice], nil, blind_choice)" position = "after" payload = ''' -if next(SMODS.find_card('j_cry_kittyprinter')) then - _tag = Tag('tag_cry_cat', nil, blind_choice) -end -''' -match_indent = true - -# avoids a game-locking crash related to opened booster being nil -# remove this as soon as a fix is done -[[patches]] -[patches.pattern] -target = "game.lua" -pattern = "SMODS.OPENED_BOOSTER.config.center:update_pack(dt)" -position = "at" -payload = ''' -if not SMODS.OPENED_BOOSTER then - G.STATE = G.STATES.SHOP - print('Error: SMODS.OPENED_BOOSTER is nil. Game recovered by setting game state to shop.') -else - SMODS.OPENED_BOOSTER.config.center:update_pack(dt) +local tag = Cryptid.get_next_tag() +if tag then + _tag = Tag(tag, nil, blind_choice) end ''' match_indent = true @@ -492,3 +469,183 @@ payload = ''' if Cryptid.forced_edition() then self:nope() end ''' match_indent = true + +#Fix bignum select limit +[[patches]] +[patches.pattern] +target = "cardarea.lua" +pattern = "if #self.highlighted >= self.config.highlighted_limit then" +position = "at" +payload = "if to_big(#self.highlighted) >= to_big(self.config.highlighted_limit) then" +match_indent = true + +#Fix bignum values sometimes crashing the game for some reason idfk +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = """ +text = (amt <-0.01 and '-' or '')..localize("$")..tostring(math.abs(amt)) +colour = amt <-0.01 and G.C.RED or G.C.MONEY +""" +position = "at" +payload = """ +text = (to_big(amt) < to_big(-0.01) and '-' or '')..localize("$")..tostring(math.abs(amt)) +colour = to_big(amt) < to_big(-0.01) and G.C.RED or G.C.MONEY +""" +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = """ +if amt > 0 or amt < 0 then +""" +position = "at" +payload = """ +if to_big(amt) ~= to_big(0) then +""" +match_indent = true + +[[patches]] +[patches.pattern] +target = '''=[SMODS _ "src/utils.lua"]''' +pattern = """ +return val and (val > 0 and '+'..val or ''..val) or '0' +""" +position = "at" +payload = """ +return val and (to_big(val) > to_big(0) and '+'..number_format(val) or ''..number_format(val)) or '0' +""" +match_indent = true + +[[patches]] +[patches.pattern] +target = '''=[SMODS _ "src/utils.lua"]''' +pattern = """ +return val and (val > 0 and '$'..val or '-$'..-val) or '0' +""" +position = "at" +payload = """ +return val and (to_big(val) > to_big(0) and '$'..number_format(val) or '-$'..number_format(-val)) or '0' +""" +match_indent = true + +[[patches]] +[patches.pattern] +target = '''=[SMODS _ "src/utils.lua"]''' +pattern = """ +if (key == 'chips' or key == 'h_chips' or key == 'chip_mod') and amount then +""" +position = "at" +payload = """ +if (key == 'chips' or key == 'h_chips' or key == 'chip_mod') and amount and hand_chips then +""" +match_indent = true + +[[patches]] +[patches.pattern] +target = '''=[SMODS _ "src/utils.lua"]''' +pattern = """ +if (key == 'mult' or key == 'h_mult' or key == 'mult_mod') and amount then +""" +position = "at" +payload = """ +if (key == 'mult' or key == 'h_mult' or key == 'mult_mod') and amount and mult then +""" +match_indent = true + +[[patches]] +[patches.pattern] +target = '''=[SMODS _ "src/utils.lua"]''' +pattern = """ +if (key == 'x_chips' or key == 'xchips' or key == 'Xchip_mod') and amount ~= 1 then +""" +position = "at" +payload = """ +if (key == 'x_chips' or key == 'xchips' or key == 'Xchip_mod') and amount ~= 1 and hand_chips then +""" +match_indent = true + +[[patches]] +[patches.pattern] +target = '''=[SMODS _ "src/utils.lua"]''' +pattern = """ +if (key == 'x_mult' or key == 'xmult' or key == 'Xmult' or key == 'x_mult_mod' or key == 'Xmult_mod') and amount ~= 1 then +""" +position = "at" +payload = """ +if (key == 'x_mult' or key == 'xmult' or key == 'Xmult' or key == 'x_mult_mod' or key == 'Xmult_mod') and amount ~= 1 and mult then +""" +match_indent = true + +[[patches]] +[patches.pattern] +target = '''=[SMODS _ "src/utils.lua"]''' +pattern = """ +if key == 'balance' then +""" +position = "at" +payload = """ +if key == 'balance' and hand_chips and mult then +""" +match_indent = true + + +#Make joker-editioning consumables not crash when they have no valid target +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = """ +local edition = nil +""" +position = "before" +payload = """ +if not eligible_card then return true end +""" +match_indent = true + +# Make Cube only show up in shop +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "elseif v.enhancement_gate then" +position = "before" +payload = ''' +elseif v.source_gate then + if v.source_gate ~= _append then + add = nil + else + add = true + end +''' +match_indent = true + +#Make negative playing cards not take up space even when debuffed +[[patches]] +[patches.pattern] +target = "cardarea.lua" +pattern = """if not card.debuff and card.edition and card.edition.card_limit and (self == G.hand) then""" +position = "at" +payload = """if card.edition and card.edition.card_limit and (self == G.hand) then""" +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = """limit = limit - 1 + (not card.debuff and card.edition and card.edition.card_limit or 0)""" +position = "at" +payload = """limit = limit - 1 + (card.edition and card.edition.card_limit or 0)""" +match_indent = true + + +#This fixes a double-sided green seal cards crashing the game while trying to open "View deck" while flipped inside the random deck selection in a booster pack +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "for k, v in pairs(other.ability.seal or {}) do" +position = "at" +payload = ''' +local safe_seal = type(other.ability.seal) == "table" and other.ability.seal or {} +for k, v in pairs(safe_seal) do +''' +match_indent = true diff --git a/Cryptid/lovely/misc_joker.toml b/Cryptid/lovely/misc_joker.toml index f159ee6..01cd675 100644 --- a/Cryptid/lovely/misc_joker.toml +++ b/Cryptid/lovely/misc_joker.toml @@ -18,5 +18,4 @@ target = "functions/common_events.lua" pattern = "ret.playing_card = {}" position = "at" payload = "ret.playing_card = ret.playing_card or {}" -match_indent = true - +match_indent = true \ No newline at end of file diff --git a/Cryptid/lovely/misprint.toml b/Cryptid/lovely/misprint.toml index 2edca00..6766215 100644 --- a/Cryptid/lovely/misprint.toml +++ b/Cryptid/lovely/misprint.toml @@ -30,7 +30,7 @@ target = "game.lua" pattern = "create_shop_card_ui(card, 'Booster', G.shop_booster)" position = "before" payload = ''' -Cryptid.misprintize(card) +Cryptid.manipulate(card) ''' match_indent = true @@ -40,7 +40,7 @@ match_indent = true [[patches]] [patches.pattern] target = "card.lua" -pattern = "G.GAME.pack_choices = self.ability.choose or self.config.center.config.choose or 1" +pattern = "G.GAME.pack_choices = math.min((self.ability.choose or self.config.center.config.choose or 1) + (G.GAME.modifiers.booster_choice_mod or 0), self.ability.extra and math.max(1, self.ability.extra + (G.GAME.modifiers.booster_size_mod or 0)) or self.config.center.extra and math.max(1, self.config.center.extra + (G.GAME.modifiers.booster_size_mod or 0)) or 1)" position = "after" payload = ''' G.GAME.pack_choices = ((self.ability.choose and self.ability.extra) and math.min(math.floor(self.ability.extra), self.ability.choose)) or 1 @@ -49,31 +49,51 @@ if G.GAME.modifiers.cry_misprint_min then if G.GAME.pack_size < 1 then G.GAME.pack_size = 1 end self.ability.extra = G.GAME.pack_size G.GAME.pack_choices = math.min(math.floor(G.GAME.pack_size), self.ability.choose) - --G.GAME.pack_choices = math.min(math.floor(G.GAME.pack_size),cry_format(G.GAME.pack_choices * Cryptid.log_random(pseudoseed('cry_misprint_p'..G.GAME.round_resets.ante),G.GAME.modifiers.cry_misprint_min,G.GAME.modifiers.cry_misprint_max),"%.2f")) end -if G.GAME.cry_oboe then +if G.GAME.cry_oboe > 0 then self.ability.extra = self.ability.extra + G.GAME.cry_oboe G.GAME.pack_choices = G.GAME.pack_choices + G.GAME.cry_oboe - G.GAME.cry_oboe = nil + G.GAME.cry_oboe = 0 end if G.GAME.boostertag and G.GAME.boostertag > 0 then self.ability.extra = self.ability.extra * 2 G.GAME.pack_choices = G.GAME.pack_choices * 2 G.GAME.boostertag = math.max(0, G.GAME.boostertag - 1) + if G.GAME.boostertag > 0 then + G.E_MANAGER:add_event(Event({ + func = function() + attention_text({ + scale = 1, + text = localize({ type = "name_text", set = "Tag", key = "tag_cry_booster" }) .. ": " .. localize{type = 'variable', key = ('loyalty_inactive'), vars = {G.GAME.boostertag}}, + hold = 2, + align = "cm", + offset = { x = 0, y = -2.7 }, + major = G.play, + }) + return true + end, + })) + end end -self.ability.extra = math.min(self.ability.extra, 1000) -G.GAME.pack_choices = math.min(G.GAME.pack_choices, 1000) +self.ability.extra = math.min(self.ability.extra, 500) +G.GAME.pack_choices = math.min(G.GAME.pack_choices, 500) G.GAME.pack_size = self.ability.extra ''' match_indent = true +#idk wtf is going on my head hurts +#but this should fix it [[patches]] [patches.pattern] target = "card.lua" -pattern = "if self.ability.name:find('Arcana') then" +pattern = ''' +booster_obj = self.config.center +if booster_obj and SMODS.Centers[booster_obj.key] then +''' position = "before" payload = ''' -if self.ability.extra < 1 then self.ability.extra = 1 end +self.ability.extra = to_number(self.ability.extra) +if to_big(self.ability.extra) < to_big(1) then self.ability.extra = 1 end ''' match_indent = true @@ -84,7 +104,7 @@ target = '''=[SMODS _ "src/utils.lua"]''' pattern = "create_shop_card_ui(card, 'Voucher', G.shop_vouchers)" position = "before" payload = ''' -Cryptid.misprintize(card) +Cryptid.manipulate(card) if G.GAME.events.ev_cry_choco2 then card.misprint_cost_fac = (card.misprint_cost_fac or 1) * 2 card:set_cost() @@ -98,7 +118,7 @@ target = "tag.lua" pattern = "create_shop_card_ui(card, 'Voucher', G.shop_vouchers)" position = "before" payload = ''' -Cryptid.misprintize(card) +Cryptid.manipulate(card) if G.GAME.events.ev_cry_choco2 then card.misprint_cost_fac = (card.misprint_cost_fac or 1) * 2 card:set_cost() @@ -115,6 +135,14 @@ position = "after" payload = "G.GAME.round_resets.ante = Big and (to_number(math.floor(to_big(G.GAME.round_resets.ante)))) or math.floor(G.GAME.round_resets.ante)" match_indent = true +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = "G.GAME.round_resets.blind_ante = G.GAME.round_resets.blind_ante or G.GAME.round_resets.ante" +position = "after" +payload = "G.GAME.round_resets.blind_ante = Big and (to_number(math.floor(to_big(G.GAME.round_resets.blind_ante)))) or math.floor(G.GAME.round_resets.blind_ante)" +match_indent = true + # UI Bugs [[patches]] [patches.pattern] @@ -166,23 +194,6 @@ position = "at" payload = "self.ability.consumeable.mod_num = self.ability.consumeable.max_highlighted" match_indent = true -# Infinite Deck -[[patches]] -[patches.pattern] -target = "cardarea.lua" -pattern = "self.config.highlighted_limit = config.highlight_limit or 5" -position = "at" -payload = "self.config.highlighted_limit = config.highlight_limit or G.GAME.modifiers.cry_highlight_limit or 5" -match_indent = true - -[[patches]] -[patches.pattern] -target = "functions/button_callbacks.lua" -pattern = "if #G.hand.highlighted <= 0 or G.GAME.blind.block_play or #G.hand.highlighted > 5 then" -position = "at" -payload = "if #G.hand.highlighted <= (G.GAME.stamp_mod and 1 or 0) or G.GAME.blind.block_play then" -match_indent = true - # Hieroglyph [[patches]] [patches.pattern] @@ -292,9 +303,9 @@ position = "after" payload = ''' if (self and self.ability and self.ability.extra_disp) then -- redeeming through centers isn't misprinted local self_disp = self.ability.extra_disp - local orig_disp = self.config.center.config.extra_disp + local orig_disp = self.config.center.config.extra_disp or 1 local self_extra = self.ability.extra - local orig_extra = self.config.center.config.extra + local orig_extra = self.config.center.config.extra or 1 local new_fac = self_disp / orig_disp self.ability.extra = new_fac*orig_extra @@ -502,3 +513,24 @@ payload = ''' v_planet_tycoon= {order = 20, discovered = false, unlocked = false, available = true,cost = 10, name = "Planet Tycoon", pos = {x=2,y=1}, set = "Voucher", config = {extra = 32/9.6, extra_disp = 4}, requires = {'v_planet_merchant'},unlock_condition = {type = 'c_planets_bought', extra = 50}}, ''' match_indent = true + +#Fix copying jokers with bignum values +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = "if not strip_edition then " +position = "before" +payload = ''' +--misprintize table has to stay around +--cause i literally cant fix this without it +Cryptid.misprintize_tbl( + new_card.config.center_key, + new_card, + "ability", + nil, + {min = 1, max = 1}, + true, + Cryptid.is_card_big(new_card) + ) +''' +match_indent = true diff --git a/Cryptid/lovely/none.toml b/Cryptid/lovely/none.toml new file mode 100644 index 0000000..430083e --- /dev/null +++ b/Cryptid/lovely/none.toml @@ -0,0 +1,305 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = 0 + +[[patches]] +[patches.pattern] +target = "functions/ui_definitions.lua" +pattern = ''' +local discard_button = {n=G.UIT.C, config={id = 'discard_button',align = "tm", padding = 0.3, r = 0.1, minw = 2.5, minh = button_height, hover = true, colour = G.C.RED, button = "discard_cards_from_highlighted", one_press = true, shadow = true, func = 'can_discard'}, nodes={ + {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ + {n=G.UIT.T, config={text = localize('b_discard'), scale = text_scale, colour = G.C.UI.TEXT_LIGHT, focus_args = {button = 'y', orientation = 'bm'}, func = 'set_button_pip'}} + }} +}} +''' +position = "at" +payload = ''' +local discard_button = {n=G.UIT.C, config={id = 'discard_button',align = "tm", padding = 0.3, r = 0.1, minw = 2.5, minh = button_height, hover = true, colour = G.C.RED, button = "discard_cards_from_highlighted", shadow = true, func = 'can_discard'}, nodes={ + {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ + {n=G.UIT.T, config={text = localize('b_discard'), scale = text_scale, colour = G.C.UI.TEXT_LIGHT, focus_args = {button = 'y', orientation = 'bm'}, func = 'set_button_pip'}} + }} +}} +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = ''' +func = (function() update_hand_text({delay = 0, immediate = true}, {mult = 0, chips = 0, chip_total = G.GAME.blind.cry_cap_score and G.GAME.blind:cry_cap_score(math.floor(hand_chips*mult)) or math.floor(hand_chips*mult), level = '', handname = ''});play_sound('button', 0.9, 0.6);return true end) +''' +position = "at" +payload = ''' +func = (function() + +if G.GAME.hands["cry_None"].visible then +update_hand_text({delay = 0, immediate = true}, {mult = 0, chips = 0, chip_total = G.GAME.blind.cry_cap_score and G.GAME.blind:cry_cap_score(math.floor(hand_chips*mult)) or math.floor(hand_chips*mult), level = '', handname = ''}); + G.reset_to_none = true + +else + update_hand_text({delay = 0, immediate = true}, {mult = 0, chips = 0, chip_total = G.GAME.blind.cry_cap_score and G.GAME.blind:cry_cap_score(math.floor(hand_chips*mult)) or math.floor(hand_chips*mult), level = '', handname = ''}); +end +play_sound('button', 0.9, 0.6);return true end) +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +level_up_hand(context.blueprint_card or self, text, nil, 1) +update_hand_text({sound = 'button', volume = 0.7, pitch = 1.1, delay = 0}, {mult = 0, chips = 0, handname = '', level = ''}) +return nil, true +''' +position = "at" +payload = ''' + level_up_hand(context.blueprint_card or self, text, nil, 1) + if G.GAME.hands["cry_None"].visible then + Cryptid.reset_to_none() + + else + update_hand_text({delay = 0}, {mult = 0, chips = 0, handname = '', level = ''}) + end + return nil, true +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +level_up_hand(used_tarot, self.ability.consumeable.hand_type) +update_hand_text({sound = 'button', volume = 0.7, pitch = 1.1, delay = 0}, {mult = 0, chips = 0, handname = '', level = ''}) +''' +position = "at" +payload = ''' +level_up_hand(used_tarot, self.ability.consumeable.hand_type) +update_hand_text({sound = 'button', volume = 0.7, pitch = 1.1, delay = 0}, {mult = 0, chips = 0, handname = '', level = ''}) +if G.GAME.current_round.current_hand.handname ~= "" then + G.E_MANAGER:add_event(Event({ + trigger = 'after', + func = function() + G.hand:parse_highlighted() + return true + end + })) +end +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +for k, v in pairs(G.GAME.hands) do + level_up_hand(self, k, true) +end +update_hand_text({sound = 'button', volume = 0.7, pitch = 1.1, delay = 0}, {mult = 0, chips = 0, handname = '', level = ''}) +''' +position = "at" +payload = ''' + for k, v in pairs(G.GAME.hands) do + level_up_hand(self, k, true) + end + if G.GAME.hands["cry_None"].visible then + Cryptid.reset_to_none() + + else + update_hand_text({delay = 0}, {mult = 0, chips = 0, handname = '', level = ''}) + end +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +if self.ability.consumeable.max_highlighted then + update_hand_text({immediate = true, nopulse = true, delay = 0}, {mult = 0, chips = 0, level = '', handname = ''}) +end +''' +position = "at" +payload = ''' +if self.ability.consumeable.max_highlighted then + if G.GAME.hands["cry_None"].visible then + Cryptid.reset_to_none() + + else + update_hand_text({delay = 0}, {mult = 0, chips = 0, handname = '', level = ''}) + end +end +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = ''' +G.E_MANAGER:add_event(Event({ + trigger = 'immediate', + func = (function() G.GAME.current_round.current_hand.handname = '';return true end) + })) +''' +position = "at" +payload = ''' +G.E_MANAGER:add_event(Event({ + trigger = 'immediate', + func = (function() + if G.GAME.current_round.current_hand.handname ~= localize('cry_None', "poker_hands") or not G.GAME.hands["cry_None"].visible then + G.GAME.current_round.current_hand.handname = '' + end + return true end) + })) +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = ''' + G.E_MANAGER:add_event(Event({ + trigger = 'immediate', + func = (function() + if G.GAME.current_round.current_hand.handname ~= localize('cry_None', "poker_hands") or not G.GAME.hands["cry_None"].visible then + G.GAME.current_round.current_hand.handname = '' + end + return true end) + })) + delay(0.3) +''' +position = "at" +payload = ''' + G.E_MANAGER:add_event(Event({ + trigger = 'immediate', + func = (function() + if text ~= "cry_None" or not G.GAME.hands["cry_None"].visible then + G.GAME.current_round.current_hand.handname = '' + end + return true end) + })) + delay(0.3) +delay(0.3) +if not (SMODS.Mods["Talisman"] or {}).can_load then + evaluate_play_after(text, disp_text, poker_hands, scoring_hand, non_loc_disp_text, percent, percent_delta) +end +return text, disp_text, poker_hands, scoring_hand, non_loc_disp_text, percent, percent_delta +end +function evaluate_play_after(text, disp_text, poker_hands, scoring_hand, non_loc_disp_text, percent, percent_delta) +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = ''' +G.GAME.hands[text].played = G.GAME.hands[text].played + 1 +''' +position = "at" +payload = ''' +local hand = (G.GAME.hands[text]) +if not hand then text = "cry_None"; disp_text = localize("cry_None", "poker_hands") end +hand = G.GAME.hands[text] +if text == "cry_None" then G.GAME.hands["cry_None"].visible = true end +hand.played = hand.played + 1 +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = ''' +G.GAME.hands[hand].level = math.max(0, G.GAME.hands[hand].level + amount) +G.GAME.hands[hand].mult = math.max(G.GAME.hands[hand].mult + G.GAME.hands[hand].l_mult*amount, 1) +G.GAME.hands[hand].chips = math.max(G.GAME.hands[hand].chips + G.GAME.hands[hand].l_chips*amount, 1) +''' +position = "at" +payload = ''' +G.GAME.hands[hand].level = math.max(0, G.GAME.hands[hand].level + amount) +G.GAME.hands[hand].mult = G.GAME.hands[hand].mult + G.GAME.hands[hand].l_mult*amount +G.GAME.hands[hand].chips = G.GAME.hands[hand].chips + G.GAME.hands[hand].l_chips*amount +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "game.lua" +pattern = ''' +if #G.hand.cards < 1 and #G.deck.cards < 1 and #G.play.cards < 1 then + end_round() +end +''' +position = "at" +payload = ''' +if #G.hand.cards < 1 and #G.deck.cards < 1 and #G.play.cards < 1 and not G.PROFILES[G.SETTINGS.profile].cry_none then + end_round() +end +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "game.lua" +pattern = ''' +if #G.hand.cards < 1 and #G.deck.cards < 1 then + end_round() +else + save_run() + G.CONTROLLER:recall_cardarea_focus('hand') +end +''' +position = "at" +payload = ''' +if #G.hand.cards < 1 and #G.deck.cards < 1 and not G.PROFILES[G.SETTINGS.profile].cry_none then + end_round() +else + save_run() + G.CONTROLLER:recall_cardarea_focus('hand') +end +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = ''' +G.hand.config.card_limit <= 0 and #G.hand.cards == 0 then +''' +position = "at" +payload = ''' +G.hand.config.card_limit <= 0 and #G.hand.cards == 0 and not G.PROFILES[G.SETTINGS.profile].cry_none then +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +local text,disp_text = G.FUNCS.get_poker_hand_info(G.hand.highlighted) +''' +position = "after" +payload = ''' +if not text or text == "NULL" then + G.GAME.hands["cry_None"].visible = true + text = "cry_None" +end +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "game.lua" +pattern = ''' + if (not G.hand.cards[1]) and G.deck.cards[1] then + G.STATE = G.STATES.DRAW_TO_HAND + G.STATE_COMPLETE = false + else +''' +position = "at" +payload = ''' + if (not G.hand.cards[1]) and G.deck.cards[1] and G.hand.config.card_limit > 0 then + G.STATE = G.STATES.DRAW_TO_HAND + G.STATE_COMPLETE = false + else +''' +match_indent = true diff --git a/Cryptid/lovely/planet.toml b/Cryptid/lovely/planet.toml index 8b26260..0a790d0 100644 --- a/Cryptid/lovely/planet.toml +++ b/Cryptid/lovely/planet.toml @@ -17,7 +17,7 @@ elseif v.config.hand_type then softlocked = G.GAME.hands[v.config.hand_type].played == 0 elseif v.config.hand_types then for _, h in pairs(v.config.hand_types) do - if G.GAME.hands[h].played > 0 then + if (G.GAME.hands[h].played or 0) > 0 then softlocked = false end end diff --git a/Cryptid/lovely/seal.toml b/Cryptid/lovely/seal.toml index eed6ca9..9fad4fd 100644 --- a/Cryptid/lovely/seal.toml +++ b/Cryptid/lovely/seal.toml @@ -12,7 +12,7 @@ pattern = '(?[\t ]*)if destroyed then \n' position = 'before' line_prepend = '$indent' payload = ''' -if scoring_hand[i]:calculate_seal({destroying_card = scoring_hand[i], full_hand = G.play.cards}) and not scoring_hand[i].ability.eternal then +if scoring_hand[i]:calculate_seal({destroying_card = scoring_hand[i], full_hand = G.play.cards}) and not SMODS.is_eternal(scoring_hand[i]) then destroyed = true end diff --git a/Cryptid/lovely/spooky.toml b/Cryptid/lovely/spooky.toml index c01bbc0..b301dec 100644 --- a/Cryptid/lovely/spooky.toml +++ b/Cryptid/lovely/spooky.toml @@ -35,7 +35,7 @@ if G.GAME.events.ev_cry_choco10 then end if add then local card = create_card('Joker', G.jokers, true, nil, nil, nil, nil, 'cry_antique') - Cryptid.misprintize(card) + Cryptid.manipulate(card) card.misprint_cost_fac = 50/card.cost card:set_cost() create_shop_card_ui(card, 'Voucher', G.shop_vouchers) diff --git a/Cryptid/lovely/stake.toml b/Cryptid/lovely/stake.toml index c80ca04..52a4d36 100644 --- a/Cryptid/lovely/stake.toml +++ b/Cryptid/lovely/stake.toml @@ -19,20 +19,6 @@ end ''' match_indent = true -# Yellow Stake - perishable and rental effects on cards held in hand -[[patches]] -[patches.pattern] -target = "functions/state_events.lua" -pattern = "local effects = {[1] = {playing_card = G.hand.cards[i]:get_end_of_round_effect()}}" -position = "after" -payload = ''' --- these are already calculated --- does mean this patch is pointless now, but i want to leave it here just so it's clear, maybe remove later --- G.hand.cards[i]:calculate_rental() --- G.hand.cards[i]:calculate_perishable() -''' -match_indent = true - # Yellow Stake - perishable and rental effects on cards in deck and discard pile # Double Down [[patches]] @@ -57,11 +43,25 @@ while i <= #G.deck.cards do end if G.GAME.used_vouchers.v_cry_double_down then local function update_dbl(area) + local area = G.jokers for i = 1, #area.cards do - if area.cards[i].dbl_side then + if area.cards[i].ability.immutable and type(area.cards[i].ability.immutable.other_side) == "table" then --tweak to do deck effects with on the flip side - Cryptid.misprintize(area.cards[i].dbl_side, {min = 1.5, max = 1.5}, nil, true) - card_eval_status_text(area.cards[i], "extra", nil, nil, nil, { message = localize("k_upgrade_ex") }) + if not G.P_CENTERS[area.cards[i].ability.immutable.other_side.key].immutable then + if area.cards[i].ability.immutable.other_side and area.cards[i].edition.cry_double_sided then + Cryptid.manipulate_table( + area.cards[i], + area.cards[i].ability.immutable, + "other_side", + { + value = 1.5, + type = "X", + big = Cryptid.is_card_big({config = {center = G.P_CENTERS[area.cards[i].ability.immutable.other_side.key]}}) + } + ) + card_eval_status_text(area.cards[i], "extra", nil, nil, nil, { message = localize("k_upgrade_ex") }) + end + end end end end @@ -78,18 +78,18 @@ match_indent = true [[patches]] [patches.pattern] target = "card.lua" -pattern = "if self.ability.name == 'The Hermit' or self.ability.consumeable.hand_type or self.ability.name == 'Temperance' or self.ability.name == 'Black Hole' then" +pattern = "if self.ability.name == 'The Wheel of Fortune' then" position = "before" payload = ''' if self.ability.name == "The Hanged Man" then for i = 1, #G.hand.highlighted do - if G.hand.highlighted[i].ability.eternal then return false end + if SMODS.is_eternal(G.hand.highlighted[i]) then return false end end end if self.ability.name == "Death" then local rightmost = G.hand.highlighted[1] for i=1, #G.hand.highlighted-1 do if G.hand.highlighted[i].T.x > rightmost.T.x then rightmost = G.hand.highlighted[i] end end - for i=1, #G.hand.highlighted do if G.hand.highlighted[i].ability.eternal and rightmost ~= G.hand.highlighted[i] then return false end end + for i=1, #G.hand.highlighted do if SMODS.is_eternal(G.hand.highlighted[i]) and rightmost ~= G.hand.highlighted[i] then return false end end end ''' match_indent = true @@ -103,7 +103,7 @@ pattern = "for k, v in ipairs(G.hand.cards) do temp_hand[#temp_hand+1] = v end" position = "at" payload = ''' for k, v in ipairs(G.hand.cards) do - if not v.ability.eternal then + if not SMODS.is_eternal(v) then temp_hand[#temp_hand+1] = v end end @@ -117,7 +117,7 @@ match_indent = true target = "card.lua" pattern = "if G.hand.highlighted[i] ~= rightmost then" position = "at" -payload = "if G.hand.highlighted[i] ~= rightmost and not G.hand.highlighted[i].ability.eternal then" +payload = "if G.hand.highlighted[i] ~= rightmost and not SMODS.is_eternal(G.hand.highlighted[i]) then" match_indent = true @@ -127,7 +127,7 @@ match_indent = true target = "card.lua" pattern = "G.GAME.current_round.discards_used <= 0 and #context.full_hand == 1 then" position = "at" -payload = "G.GAME.current_round.discards_used <= 0 and #context.full_hand == 1 and not context.other_card.ability.eternal then" +payload = "G.GAME.current_round.discards_used <= 0 and #context.full_hand == 1 and not SMODS.is_eternal(context.other_card) then" match_indent = true @@ -137,7 +137,7 @@ match_indent = true target = "card.lua" pattern = "if self.ability.name == 'Sixth Sense' and #context.full_hand == 1 and context.full_hand[1]:get_id() == 6 and G.GAME.current_round.hands_played == 0 then" position = "at" -payload = "if self.ability.name == 'Sixth Sense' and #context.full_hand == 1 and context.full_hand[1]:get_id() == 6 and not context.full_hand[1].ability.eternal and G.GAME.current_round.hands_played == 0 then" +payload = "if self.ability.name == 'Sixth Sense' and #context.full_hand == 1 and context.full_hand[1]:get_id() == 6 and not SMODS.is_eternal(context.full_hand[1]) and G.GAME.current_round.hands_played == 0 then" match_indent = true @@ -155,14 +155,31 @@ rental = self.ability and self.ability.rental, ''' match_indent = true - -# Amber Stake - edit number of booster packs +# Crimson Stake - Disable restocks on even antes [[patches]] [patches.pattern] target = "game.lua" -pattern = "for i = 1, 2 do" +pattern = '''for _,_ in pairs(G.GAME.current_round.voucher.spawn) do vouchers_to_spawn = vouchers_to_spawn + 1 end +if vouchers_to_spawn < G.GAME.starting_params.vouchers_in_shop + (G.GAME.modifiers.extra_vouchers or 0) then + SMODS.get_next_vouchers(G.GAME.current_round.voucher) +end +for _, key in ipairs(G.GAME.current_round.voucher or {}) do + if G.P_CENTERS[key] and G.GAME.current_round.voucher.spawn[key] then + SMODS.add_voucher_to_shop(key) + end +end''' position = "at" -payload = "for i = 1, G.GAME.modifiers.cry_no_boosters and 0 or G.GAME.modifiers.cry_booster_packs or 2 do" +payload = '''if (G.GAME.modifiers.cry_voucher_restock_antes == nil or G.GAME.round_resets.ante % G.GAME.modifiers.cry_voucher_restock_antes == 0) then + for _,_ in pairs(G.GAME.current_round.voucher.spawn) do vouchers_to_spawn = vouchers_to_spawn + 1 end + if vouchers_to_spawn < G.GAME.starting_params.vouchers_in_shop + (G.GAME.modifiers.extra_vouchers or 0) then + SMODS.get_next_vouchers(G.GAME.current_round.voucher) + end + for _, key in ipairs(G.GAME.current_round.voucher or {}) do + if G.P_CENTERS[key] and G.GAME.current_round.voucher.spawn[key] then + SMODS.add_voucher_to_shop(key) + end + end +end''' match_indent = true # Quartz Stake - pinned effect applies in every type of slot @@ -270,13 +287,14 @@ match_indent = true # Sapphire Stake - ante tax # The Joke boss effect # Save game state for Revert -[[patches]] -[patches.pattern] -target = "functions/state_events.lua" -pattern = "delay(0.4); ease_ante(1); delay(0.4); check_for_unlock({type = 'ante_up', ante = G.GAME.round_resets.ante + 1})" -position = "at" -payload = "delay(0.4); ease_ante(G.GAME.blind and G.GAME.blind:cry_calc_ante_gain() or 1); Cryptid.apply_ante_tax(); delay(0.4); check_for_unlock({type = 'ante_up', ante = G.GAME.round_resets.ante + 1})" -match_indent = true +# this needs to be redone at a later point +# [[patches]] +#[patches.pattern] +#target = "functions/state_events.lua" +#pattern = "delay(0.4); ease_ante(1); delay(0.4); check_for_unlock({type = 'ante_up', ante = G.GAME.round_resets.ante + 1})" +#position = "at" +#payload = "delay(0.4); ease_ante(G.GAME.blind and G.GAME.blind:cry_calc_ante_gain() or 1); Cryptid.apply_ante_tax(); delay(0.4); check_for_unlock({type = 'ante_up', ante = G.GAME.round_resets.ante + 1})" +#match_indent = true # Emerald Stake - Permanently flipped cards @@ -306,7 +324,7 @@ match_indent = true # Emerald Stake - flipped vouchers [[patches]] [patches.pattern] -target = "game.lua" +target = """=[SMODS _ "src/utils.lua"]""" pattern = "create_shop_card_ui(card, 'Voucher', G.shop_vouchers)" position = "before" payload = ''' @@ -345,16 +363,6 @@ position = "at" payload = "G.GAME.round_resets.blind_states.Small = G.GAME.modifiers.cry_no_small_blind and 'Hide' or 'Upcoming'" match_indent = true -# Ember Stake - grant no money on sell -# this is NOT ember stake grant no money on sell wtf -[[patches]] -[patches.pattern] -target = "functions/common_events.lua" -pattern = '''elseif v.boss.showdown and (G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2 then''' -position = "at" -payload = '''elseif v.boss.showdown and (((G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2) or G.GAME.modifiers.cry_big_showdown ) then''' -match_indent = true - # Ember Stake - give no money for selling [[patches]] [patches.pattern] diff --git a/Cryptid/lovely/sticker.toml b/Cryptid/lovely/sticker.toml index 06582ae..216f023 100644 --- a/Cryptid/lovely/sticker.toml +++ b/Cryptid/lovely/sticker.toml @@ -24,11 +24,11 @@ match_indent = true [[patches]] [patches.pattern] target = "functions/state_events.lua" -pattern = "G.GAME.current_round.voucher = get_next_voucher_key()" +pattern = "G.GAME.current_round.voucher = SMODS.get_next_vouchers()" position = "at" payload = ''' if G.GAME.current_round.cry_voucher_stickers.pinned == false then - G.GAME.current_round.voucher = get_next_voucher_key() + G.GAME.current_round.voucher = SMODS.get_next_vouchers() end ''' match_indent = true @@ -65,7 +65,7 @@ end local gone = false if self.ability.banana then if not self.ability.extinct then - if (pseudorandom('oops_it_banana') < G.GAME.probabilities.normal/G.GAME.cry_consumeable_banana_odds) then + if SMODS.pseudorandom_probability(self, "oops_it_banana", 1, G.GAME.cry_consumeable_banana_odds, "Banana Sticker") then local gone = true self.ability.extinct = true G.E_MANAGER:add_event(Event({ @@ -121,7 +121,7 @@ match_indent = true [[patches]] [patches.pattern] target = "card.lua" -pattern = "if self.ability.queue_negative_removal then" +pattern = "if self.joker_added_to_deck_but_debuffed then" position = "before" payload = ''' if self.ability.consumeable and self.pinned and (G.GAME.cry_pinned_consumeables > 0) then diff --git a/Cryptid/lovely/universum.toml b/Cryptid/lovely/universum.toml index 45c7f6c..50ad95a 100644 --- a/Cryptid/lovely/universum.toml +++ b/Cryptid/lovely/universum.toml @@ -3,32 +3,16 @@ version = "1.0.0" dump_lua = true priority = -1 -# Level up modifier [[patches]] [patches.pattern] -target = "functions/common_events.lua" -pattern = "amount = amount or 1" -position = "after" -payload = "if not next(find_joker('cry-Universum')) then" -match_indent = true - - -[[patches]] -[patches.pattern] -target = "functions/common_events.lua" -pattern = "G.GAME.hands[hand].mult = math.max(G.GAME.hands[hand].s_mult + G.GAME.hands[hand].l_mult*(G.GAME.hands[hand].level - 1), 1)" -position = "at" -payload = "G.GAME.hands[hand].mult = math.max(G.GAME.hands[hand].mult + G.GAME.hands[hand].l_mult*amount, 1)" -match_indent = true - - -[[patches]] -[patches.pattern] -target = "functions/common_events.lua" -pattern = "G.GAME.hands[hand].chips = math.max(G.GAME.hands[hand].s_chips + G.GAME.hands[hand].l_chips*(G.GAME.hands[hand].level - 1), 0)" +target = '''=[SMODS _ "src/game_object.lua"]''' +pattern = ''' +hand[self.key] = math.max(hand['s_'..self.key] + hand['l_'..self.key]*(hand.level - 1), 0) +''' position = "at" payload = ''' -G.GAME.hands[hand].chips = math.max(G.GAME.hands[hand].chips + G.GAME.hands[hand].l_chips*amount, 1) +if not next(find_joker('cry-Universum')) then + hand[self.key] = math.max(hand['s_'..self.key] + hand['l_'..self.key]*(hand.level - 1), 0) else universum_mod = 1 local effects = {} @@ -36,9 +20,7 @@ else for i = 1, #effects do universum_mod = universum_mod * (effects[i] and effects[i].jokers and effects[i].jokers.mod or 1) end - G.GAME.hands[hand].level = math.max(0, G.GAME.hands[hand].level + amount) - G.GAME.hands[hand].mult = math.max(G.GAME.hands[hand].mult * (universum_mod)^amount, 1) - G.GAME.hands[hand].chips = math.max(G.GAME.hands[hand].chips * (universum_mod)^amount, 1) + hand[self.key] = math.max(hand[self.key]* (universum_mod)^amount, hand['s_'..self.key]) end ''' -match_indent = true \ No newline at end of file +match_indent = true diff --git a/Cryptid/lovely/very_fair.toml b/Cryptid/lovely/very_fair.toml index 79343b2..03a347b 100644 --- a/Cryptid/lovely/very_fair.toml +++ b/Cryptid/lovely/very_fair.toml @@ -7,7 +7,7 @@ priority = -1 [[patches]] [patches.pattern] target = "game.lua" -pattern = "self.GAME.current_round.voucher = G.SETTINGS.tutorial_progress and G.SETTINGS.tutorial_progress.forced_voucher or SMODS.get_next_vouchers()" +pattern = "self.GAME.current_round.voucher = forced_voucher and {forced_voucher, spawn = {[forced_voucher] = true }} or SMODS.get_next_vouchers()" position = "after" payload = ''' if self.GAME.modifiers.cry_no_vouchers then diff --git a/Steamodded/.github/CODEOWNERS b/Steamodded/.github/CODEOWNERS index 972521c..bf4de4c 100644 --- a/Steamodded/.github/CODEOWNERS +++ b/Steamodded/.github/CODEOWNERS @@ -1,7 +1,7 @@ -* @Aurelius7309 +* @Aurelius7309 @Eremel src/crash_handler.lua @WilsontheWolf libs/https/ @WilsontheWolf lovely/crash_handler.toml @WilsontheWolf lovely/libs.toml @WilsontheWolf -lsp_def/ @GauntletGames-2086 \ No newline at end of file +lsp_def/ @GauntletGames-2086 diff --git a/Steamodded/README.md b/Steamodded/README.md index 31f18e4..c5c6283 100644 --- a/Steamodded/README.md +++ b/Steamodded/README.md @@ -16,6 +16,10 @@ Click [here](https://github.com/Steamopollys/Steamodded/wiki). - Put the mod into that directory. (The mod can be a single file if there is only one file provided, or it can be a whole folder.) - Launch the game and enjoy! +## Creating a Mod + +Useful resources for creating your first mod can be found [here](https://github.com/Steamodded/smods/wiki/Your-First-Mod). + ## Features Documentation for this project is currently incomplete. A collection of documentation pages and guides that are currently available can be found [here](https://github.com/Steamopollys/Steamodded/wiki). diff --git a/Steamodded/libs/https/smods-https.lua b/Steamodded/libs/https/smods-https.lua index 6bbd333..b7f24fb 100644 --- a/Steamodded/libs/https/smods-https.lua +++ b/Steamodded/libs/https/smods-https.lua @@ -73,10 +73,10 @@ end local methods = {GET=true, HEAD=true, POST=true, PUT=true, DELETE=true, PATCH=true} local function checkAndHandleInput(url, options, skipUserAgent) - assert(type(url) == "string", "url must be a string") + assert(type(url) == "string", "\"url\" must be a string") options = options or {} - assert(type(options) == "table", "options must be a table") - assert(type(options.headers or {}) == "table", "options.headers must be a table") + assert(type(options) == "table", "\"options\" must be a table") + assert(type(options.headers or {}) == "table", "\"options.headers\" must be a table") local contentTypeHeader = false if not skipUserAgent then local headers = {} @@ -96,10 +96,10 @@ local function checkAndHandleInput(url, options, skipUserAgent) options.headers = headers end if options.method then - assert(type(options.method) == "string", "options.method must be a string") - assert(methods[options.method], "options.method must be one of \"GET\", \"HEAD\", \"POST\", \"PUT\", \"DELETE\", or \"PATCH\"") + assert(type(options.method) == "string", "\"options.method\" must be a string") + assert(methods[options.method], "\"options.method\" must be one of \"GET\", \"HEAD\", \"POST\", \"PUT\", \"DELETE\", or \"PATCH\"") end - assert(type(options.data or "") == "string", "options.data must be a string") + assert(type(options.data or "") == "string", "\"options.data\" must be a string") if options.data == "" then options.data = nil end return options end @@ -226,7 +226,7 @@ if not isThread then -- In main thread assert(type(msgType) == "string", "Thread message type is not a string") if msgType == "log" then assert(type(msg.msg) == "string", "Logging msg not a string") - assert(type(msg.level) == "string", "logging level not a string") + assert(type(msg.level) == "string", "Logging level not a string") assert(type(msg.logger) == "string", "Logging logger not a string") sendMessageToConsole(msg.level, msg.logger .. "(" .. tostring(msg.id) .. ")", msg.msg) elseif msgType == "cb" then -- NOTE: cb removes the thread so it must be the last message diff --git a/Steamodded/localization/en-us.lua b/Steamodded/localization/en-us.lua index e79f666..27d314c 100644 --- a/Steamodded/localization/en-us.lua +++ b/Steamodded/localization/en-us.lua @@ -136,6 +136,41 @@ return { "{C:money}#1#{} if held at end of round", }, }, + card_extra_repetitions = { + text = { + "Retrigger this", + "card {C:attention}#1#{} #2#", + }, + }, + artist = { + text = { + "{C:inactive}Artist", + }, + }, + artist_credit = { + name = "Artist", + text = { + "{E:1}#1#{}" + }, + }, + generic_card_limit = { + name = "Card Limit", + text = { + '{C:dark_edition}#1#{} area slot' + } + }, + generic_card_limit_plural = { + name = "Card Limit", + text = { + '{C:dark_edition}#1#{} area slots' + } + }, + generic_extra_slots = { + name = "Slots Used", + text = { + 'Fills {C:dark_edition}#1#{} slots' + } + } }, Edition = { e_negative_playing_card = { @@ -144,6 +179,12 @@ return { "{C:dark_edition}+#1#{} hand size" }, }, + e_negative_generic = { + name = "Negative", + text = { + "{C:dark_edition}+#1#{} area slot" + }, + } }, Enhanced = { m_gold={ @@ -167,6 +208,15 @@ return { "{C:mult}#1#{} Mult", }, }, + m_lucky={ + name="Lucky Card", + text={ + "{C:green}#1# in #3#{} chance", + "for {C:mult}+#2#{} Mult", + "{C:green}#6# in #5#{} chance", + "to win {C:money}$#4#", + }, + }, } }, misc = { @@ -196,7 +246,7 @@ return { b_authors = 'Authors', b_unknown = 'Unknown', b_lovely_mod = '(Lovely Mod) ', - b_by = ' By: ', + b_by = 'By: ', b_priority = 'Priority: ', b_config = "Config", b_additions = 'Additions', @@ -215,9 +265,12 @@ return { 'Enabled', 'Bypass Restrictions' }, - b_deckskins_lc = 'Low Contrast Colors', - b_deckskins_hc = 'High Contrast Colors', - b_deckskins_def = 'Default Colors', + b_deckskins_lc = 'Low Contrast Colours', + b_deckskins_hc = 'High Contrast Colours', + b_deckskins_def = 'Default Colours', + b_limit = 'Up to ', + b_retrigger_single = 'time', + b_retrigger_plural = 'times' }, v_dictionary = { c_types = '#1# Types', diff --git a/Steamodded/localization/es_419.lua b/Steamodded/localization/es_419.lua index c29f162..0949103 100644 --- a/Steamodded/localization/es_419.lua +++ b/Steamodded/localization/es_419.lua @@ -62,6 +62,112 @@ return { '¡Este mod ha sido', '{C:attention}desactivado{}!' } + }, + -- card perma bonuses + card_extra_chips = { + text = { + "{C:chips}#1#{} fichas extra", + }, + }, + card_x_chips = { + text = { + "{X:chips,C:white}X#1#{} fichas" + } + }, + card_extra_x_chips = { + text = { + "{X:chips,C:white}X#1#{} fichas extra" + } + }, + card_extra_mult = { + text = { + "{C:mult}#1#{} multi extra" + } + }, + card_x_mult = { + text = { + "{X:mult,C:white}X#1#{} multi" + } + }, + card_extra_x_mult = { + text = { + "{X:mult,C:white}X#1#{} multi extra" + } + }, + card_extra_p_dollars = { + text = { + "{C:money}#1#{} cuando anota", + } + }, + card_extra_h_chips = { + text = { + "{C:chips}#1#{} fichas mientras esté en tu mano", + } + }, + card_h_x_chips = { + text = { + "{X:chips,C:white}X#1#{} fichas mientras esté en tu mano", + } + }, + card_extra_h_x_chips = { + text = { + "{X:chips,C:white}X#1#{} fichas extra mientras esté en tu mano", + } + }, + card_extra_h_mult = { + text = { + "{C:mult}#1#{} multi extra mientras esté en tu mano", + } + }, + card_h_x_mult = { + text = { + "{X:mult,C:white}X#1#{} multi mientras esté en tu mano", + } + }, + card_extra_h_x_mult = { + text = { + "{X:mult,C:white}X#1#{} multi extra mientras esté en tu mano", + } + }, + card_extra_h_dollars = { + text = { + "{C:money}#1#{} si está en tu mano al final de la ronda", + }, + }, + card_extra_repetitions = { + text = { + "Reactiva esta", + "carta {C:attention}#1#{} #2#", + }, + }, + artist = { + text = { + "{C:inactive}Artista", + }, + }, + artist_credit = { + name = "Artista", + text = { + "{E:1}#1#{}" + }, + }, + generic_card_limit = { + name = "Límite de Cartas", + text = { + '{C:dark_edition}#1#{} ranura del área' + } + }, + generic_card_limit_plural = { + name = "Límite de Cartas", + text = { + '{C:dark_edition}#1#{} ranuras del área' + } + }, + generic_extra_slots = { + name = "Ranuras Usadas", + text = { + 'Ocupa {C:dark_edition}#1#{} ranuras' + } } }, Edition = { @@ -71,6 +177,44 @@ return { "{C:dark_edition}+#1#{} de tamaño de mano" }, }, + e_negative_generic = { + name = "Negativa", + text = { + "{C:dark_edition}+#1#{} ranura del área" + }, + } + }, + Enhanced = { + m_gold = { + name = "Carta de oro", + text = { + "{C:money}#1#{} si esta", + "carta está en tu mano", + "al final de la ronda", + }, + }, + m_stone = { + name = "Carta de piedra", + text = { + "{C:chips}#1#{} fichas", + "sin categoría ni palo", + }, + }, + m_mult = { + name = "Carta multi", + text = { + "{C:mult}#1#{} multi", + }, + }, + m_lucky = { + name = "Carta de la suerte", + text = { + "{C:green}#1# en #3#{} probabilidades", + "de {C:mult}+#2#{} multi", + "{C:green}#6# en #5#{} probabilidades", + "de ganar {C:money}#4# $", + }, + }, } }, misc = { @@ -101,6 +245,7 @@ return { b_unknown = 'Desconocido', b_lovely_mod = '(Mod de Lovely) ', b_by = ' Por: ', + b_priority = 'Prioridad: ', b_config = "Configuración", b_additions = 'Adiciones', b_stickers = 'Stickers', @@ -108,10 +253,36 @@ return { b_applies_stakes_1 = 'Aplica ', b_applies_stakes_2 = '', b_graphics_mipmap_level = "Nivel de Mipmap", + b_browse = 'Navegar', + b_search_prompt = 'Buscar mods', + b_search_button = 'Buscar', + b_seeded_unlocks = 'Desbloqueos con código', + b_seeded_unlocks_info = 'Habilita desbloqueos y descubrimientos en partidas con código', + ml_achievement_settings = { + 'Deshabilitado', + 'Habilitado', + 'Ignorar Restricciones' + }, + b_deckskins_lc = 'Colores de bajo contraste', + b_deckskins_hc = 'Colores de alto contraste', + b_deckskins_def = 'Colores por defecto', + b_limit = 'Hasta ', + b_retrigger_single = 'vez', + b_retrigger_plural = 'veces' }, v_dictionary = { c_types = '#1# Tipos', cashout_hidden = '...y #1# más', + a_xchips = "X#1# fichas", + a_xchips_minus = "-X#1# fichas", + smods_version_mismatch = { + "¡Tu versión de Steamodded ha cambiado", + "desde que has comenzado esta partida!", + "Continuarla podría producir", + "comportamiento inesperado y que el juego se bloquee.", + "Versión de inicio: #1#", + "Versión actual: #2#", + } }, } } diff --git a/Steamodded/localization/es_ES.lua b/Steamodded/localization/es_ES.lua index c29f162..11185d7 100644 --- a/Steamodded/localization/es_ES.lua +++ b/Steamodded/localization/es_ES.lua @@ -62,6 +62,112 @@ return { '¡Este mod ha sido', '{C:attention}desactivado{}!' } + }, + -- card perma bonuses + card_extra_chips = { + text = { + "{C:chips}#1#{} fichas extra", + }, + }, + card_x_chips = { + text = { + "{X:chips,C:white}X#1#{} fichas" + } + }, + card_extra_x_chips = { + text = { + "{X:chips,C:white}X#1#{} fichas extra" + } + }, + card_extra_mult = { + text = { + "{C:mult}#1#{} multi extra" + } + }, + card_x_mult = { + text = { + "{X:mult,C:white}X#1#{} multi" + } + }, + card_extra_x_mult = { + text = { + "{X:mult,C:white}X#1#{} multi extra" + } + }, + card_extra_p_dollars = { + text = { + "{C:money}#1#{} cuando anota", + } + }, + card_extra_h_chips = { + text = { + "{C:chips}#1#{} fichas mientras esté en tu mano", + } + }, + card_h_x_chips = { + text = { + "{X:chips,C:white}X#1#{} fichas mientras esté en tu mano", + } + }, + card_extra_h_x_chips = { + text = { + "{X:chips,C:white}X#1#{} fichas extra mientras esté en tu mano", + } + }, + card_extra_h_mult = { + text = { + "{C:mult}#1#{} multi extra mientras esté en tu mano", + } + }, + card_h_x_mult = { + text = { + "{X:mult,C:white}X#1#{} multi mientras esté en tu mano", + } + }, + card_extra_h_x_mult = { + text = { + "{X:mult,C:white}X#1#{} multi extra mientras esté en tu mano", + } + }, + card_extra_h_dollars = { + text = { + "{C:money}#1#{} si está en tu mano al final de la ronda", + }, + }, + card_extra_repetitions = { + text = { + "Reactiva esta", + "carta {C:attention}#1#{} #2#", + }, + }, + artist = { + text = { + "{C:inactive}Artista", + }, + }, + artist_credit = { + name = "Artista", + text = { + "{E:1}#1#{}" + }, + }, + generic_card_limit = { + name = "Límite de Cartas", + text = { + '{C:dark_edition}#1#{} ranura del área' + } + }, + generic_card_limit_plural = { + name = "Límite de Cartas", + text = { + '{C:dark_edition}#1#{} ranuras del área' + } + }, + generic_extra_slots = { + name = "Ranuras Usadas", + text = { + 'Ocupa {C:dark_edition}#1#{} ranuras' + } } }, Edition = { @@ -71,6 +177,44 @@ return { "{C:dark_edition}+#1#{} de tamaño de mano" }, }, + e_negative_generic = { + name = "Negativa", + text = { + "{C:dark_edition}+#1#{} ranura del área" + }, + } + }, + Enhanced = { + m_gold = { + name = "Carta de oro", + text = { + "{C:money}#1#{} si esta", + "carta está en tu mano", + "al final de la ronda", + }, + }, + m_stone = { + name = "Carta de piedra", + text = { + "{C:chips}#1#{} fichas", + "sin categoría ni palo", + }, + }, + m_mult = { + name = "Carta multi", + text = { + "{C:mult}#1#{} multi", + }, + }, + m_lucky = { + name = "Carta de la suerte", + text = { + "{C:green}#1# en #3#{} probabilidades", + "de {C:mult}+#2#{} multi", + "{C:green}#6# en #5#{} probabilidades", + "de ganar {C:money}$#4#", + }, + }, } }, misc = { @@ -101,6 +245,7 @@ return { b_unknown = 'Desconocido', b_lovely_mod = '(Mod de Lovely) ', b_by = ' Por: ', + b_priority = 'Prioridad: ', b_config = "Configuración", b_additions = 'Adiciones', b_stickers = 'Stickers', @@ -108,10 +253,36 @@ return { b_applies_stakes_1 = 'Aplica ', b_applies_stakes_2 = '', b_graphics_mipmap_level = "Nivel de Mipmap", + b_browse = 'Navegar', + b_search_prompt = 'Buscar mods', + b_search_button = 'Buscar', + b_seeded_unlocks = 'Desbloqueos con código', + b_seeded_unlocks_info = 'Habilita desbloqueos y descubrimientos en partidas con código', + ml_achievement_settings = { + 'Deshabilitado', + 'Habilitado', + 'Ignorar Restricciones' + }, + b_deckskins_lc = 'Colores de bajo contraste', + b_deckskins_hc = 'Colores de alto contraste', + b_deckskins_def = 'Colores por defecto', + b_limit = 'Hasta ', + b_retrigger_single = 'vez', + b_retrigger_plural = 'veces' }, v_dictionary = { c_types = '#1# Tipos', cashout_hidden = '...y #1# más', + a_xchips = "X#1# fichas", + a_xchips_minus = "-X#1# fichas", + smods_version_mismatch = { + "¡Tu versión de Steamodded ha cambiado", + "desde que has comenzado esta partida!", + "Continuarla podría producir", + "comportamiento inesperado y que el juego se bloquee.", + "Versión de inicio: #1#", + "Versión actual: #2#", + } }, } } diff --git a/Steamodded/localization/it.lua b/Steamodded/localization/it.lua new file mode 100644 index 0000000..326c164 --- /dev/null +++ b/Steamodded/localization/it.lua @@ -0,0 +1,236 @@ +return { + descriptions = { + Other = { + load_success = { + text = { + 'Mod caricata', + '{C:green}con successo!' + } + }, + load_failure_d = { + text = { + '{C:attention}Dipendenze mancanti!', + '#1#', + } + }, + load_failure_c = { + text = { + '{C:attention}Conflitti rilevati!', + '#1#' + } + }, + load_failure_d_c = { + text = { + '{C:attention}Dipendenze mancanti!', + '#1#', + '{C:attention}Conflitti rilevati!', + '#2#' + } + }, + load_failure_o = { + text = { + '{C:attention}Obsoleta!{} le versioni', + 'di Steamodded {C:money}0.9.8{} ed inferiori', + 'non sono più supportate.' + } + }, + load_failure_i = { + text = { + '{C:attention}Incompatibile!{} Richiede la versione', + '#1# di Steamodded,', + 'ma la #2# è installata.' + } + }, + load_failure_p = { + text = { + '{C:attention}Conflitto fra i prefissi!{}', + 'Il prefisso di questa mod è', + 'lo stesso di quest\'altra mod', + '({C:attention}#1#{})' + } + }, + load_failure_m = { + text = { + '{C:attention}File principale non trovato!{}', + 'Il file principale di questa mod', + 'non è stato trovato.', + '({C:attention}#1#{})' + } + }, + load_disabled = { + text = { + 'Questa mod è stata', + '{C:attention}disattivata!{}' + } + }, + + + -- card perma bonuses + card_extra_chips={ + text={ + "{C:chips}#1#{} fiche extra", + }, + }, + card_x_chips = { + text = { + "{X:chips,C:white}X#1#{} fiche" + } + }, + card_extra_x_chips = { + text = { + "{X:chips,C:white}X#1#{} fiche extra" + } + }, + card_extra_mult = { + text = { + "{C:mult}#1#{} Molt extra" + } + }, + card_x_mult = { + text = { + "{X:mult,C:white}X#1#{} Molt" + } + }, + card_extra_x_mult = { + text = { + "{X:mult,C:white}X#1#{} Molt extra" + } + }, + card_extra_p_dollars = { + text = { + "{C:money}#1#{} quando assegna punti", + } + }, + card_extra_h_chips = { + text = { + "{C:chips}#1#{} fiche se tenuta in mano", + } + }, + card_h_x_chips = { + text = { + "{X:chips,C:white}X#1#{} fiche se tenuta in mano", + } + }, + card_extra_h_x_chips = { + text = { + "{X:chips,C:white}X#1#{} fiche extra se tenuta in mano", + } + }, + card_extra_h_mult = { + text = { + "{C:mult}#1#{} Molt extra se tenuta in mano", + } + }, + card_h_x_mult = { + text = { + "{X:mult,C:white}X#1#{} Molt se tenuta in mano", + } + }, + card_extra_h_x_mult = { + text = { + "{X:mult,C:white}X#1#{} Molt extra se tenuta in mano", + } + }, + card_extra_h_dollars = { + text = { + "{C:money}#1#{} se hai in mano questa carta alla fine del round", + }, + }, + }, + Edition = { + e_negative_playing_card = { + name = "Negativo", + text = { + "{C:dark_edition}+#1#{} carte della mano" + }, + }, + }, + Enhanced = { + m_gold={ + name="Carta dorata", + text={ + "{C:money}$#1#{} se hai", + "in mano questa carta", + "alla fine del round", + }, + }, + m_stone={ + name="Carta di pietra", + text={ + "{C:chips}+#1#{} fiche", + "nessun valore o seme", + }, + }, + m_mult={ + name="Carta Molt", + text={ + "{C:mult}+#1#{} Molt", + }, + }, + } + }, + misc = { + achievement_names = { + hidden_achievement = "???", + }, + achievement_descriptions = { + hidden_achievement = "Gioca per scoprirlo!", + }, + dictionary = { + b_mods = 'Mod', + b_mods_cap = 'MOD', + b_modded_version = 'Versione Modificata!', + b_steamodded = 'Steamodded', + b_credits = 'Crediti', + b_open_mods_dir = 'Apri cartella Mods', + b_no_mods = 'Nessuna mod rilevata...', + b_mod_list = 'Lista di mod attivate', + b_mod_loader = 'Mod Loader', + b_developed_by = 'sviluppato da ', + b_rewrite_by = 'Riscritto da by ', + b_github_project = 'Progetto Github', + b_github_bugs_1 = 'Puoi segnalare bug e', + b_github_bugs_2 = 'contribuire qui.', + b_disable_mod_badges = 'Disattiva etichette mod', + b_author = 'Autore', + b_authors = 'Autori', + b_unknown = 'Sconosciuto', + b_lovely_mod = '(Lovely Mod) ', + b_by = ' Di: ', + b_config = "Configurazione", + b_additions = 'Aggiunte', + b_stickers = 'Adesivi', + b_achievements = "Obiettivi", + b_applies_stakes_1 = 'Applica ', + b_applies_stakes_2 = '', + b_graphics_mipmap_level = "Livello mipmap", + b_browse = 'Sfoglia', + b_search_prompt = 'Cerca mod', + b_search_button = 'Cerca', + b_seeded_unlocks = 'Sblocchi con seed scelto', + b_seeded_unlocks_info = 'Attiva sblocchi e scoperte in sessioni con seed scelto', + ml_achievement_settings = { + 'Disattivato', + 'Attivato', + 'Aggira restrizioni' + }, + b_deckskins_lc = 'Colori a basso contrasto', + b_deckskins_hc = 'Colori ad alto contrasto', + b_deckskins_def = 'Colori predefiniti', + }, + v_dictionary = { + c_types = '#1# Tipi', + cashout_hidden = '...e #1# in più', + a_xchips = "X#1# fiche", + a_xchips_minus = "-X#1# fiche", + smods_version_mismatch = { + "La versione di Steamodded è cambiata", + "dall'inizio di questa sessione!", + "Continuare potrebbe causare", + "comportamenti anomali e crash.", + "Versione di partenza: #1#", + "Versione attuale: #2#", + } + }, + } +} diff --git a/Steamodded/localization/ru.lua b/Steamodded/localization/ru.lua new file mode 100644 index 0000000..d59ea89 --- /dev/null +++ b/Steamodded/localization/ru.lua @@ -0,0 +1,237 @@ +return { + descriptions = { + Other = { + load_success = { + text = { + 'Мод загружен', + '{C:green}успешно!' + } + }, + load_failure_d = { + text = { + 'Не хватает {C:attention}зависимостей!', + '#1#', + } + }, + load_failure_c = { + text = { + 'Неразрешенные {C:attention}конфликты!', + '#1#' + } + }, + load_failure_d_c = { + text = { + 'Не хватает {C:attention}зависимостей!', + '#1#', + 'Неразрешенные {C:attention}конфликты!', + '#1#' + } + }, + load_failure_o = { + text = { + '{C:attention}Устаревший!{} Steamodded', + 'версия {C:money}0.9.8{} и ниже', + 'более не поддерживается.' + } + }, + load_failure_i = { + text = { + '{C:attention}Несовместимо!{}', + 'Нужен Steammodded #1#,', + 'но #2# установлен.' + } + }, + load_failure_p = { + text = { + '{C:attention}Конфликт префиксов!{}', + 'Префикс этого мода', + 'такой же как у другого.', + '({C:attention}#1#{})' + } + }, + load_failure_m = { + text = { + '{C:attention}Основной файл не найден!{}', + 'Основной файл этого мода', + 'не найден.', + '({C:attention}#1#{})' + } + }, + load_disabled = { + text = { + 'Данный мод был', + '{C:attention}отключён!{}' + } + }, + + + -- card perma bonuses + card_extra_chips={ + text={ + "{C:chips}#1#{} доп. фишек", + }, + }, + card_x_chips = { + text = { + "{X:chips,C:white}X#1#{} фишек" + } + }, + card_extra_x_chips = { + text = { + "{X:chips,C:white}X#1#{} доп. фишек" + } + }, + card_extra_mult = { + text = { + "{C:mult}#1#{} доп. Множ." + } + }, + card_x_mult = { + text = { + "{X:mult,C:white}X#1#{} Множ." + } + }, + card_extra_x_mult = { + text = { + "{X:mult,C:white}X#1#{} доп. Множ." + } + }, + card_extra_p_dollars = { + text = { + "{C:money}#1#{} когда засчитано", + } + }, + card_extra_h_chips = { + text = { + "{C:chips}#1#{} фишек когда удерживается", + } + }, + card_h_x_chips = { + text = { + "{X:chips,C:white}X#1#{} фишек когда удерживается", + } + }, + card_extra_h_x_chips = { + text = { + "{X:chips,C:white}X#1#{} доп. фишек когда удерживается", + } + }, + card_extra_h_mult = { + text = { + "{C:mult}#1#{} доп. Множ. когда удерживается", + } + }, + card_h_x_mult = { + text = { + "{X:mult,C:white}X#1#{} Множ. когда удерживается", + } + }, + card_extra_h_x_mult = { + text = { + "{X:mult,C:white}X#1#{} доп. Множ. когда удерживается", + } + }, + card_extra_h_dollars = { + text = { + "{C:money}#1#{} если удерживается в конце раунда", + }, + }, + }, + Edition = { + e_negative_playing_card = { + name = "Негативная", + text = { + "{C:dark_edition}+#1#{} размер руки" + }, + }, + }, + Enhanced = { + m_gold = { + name = "Золотая карта", + text = { + "{C:money}$#1#{}, если эта", + "карта есть в руке", + "в конце раунда", + } + }, + m_stone = { + name = "Каменная карта", + text = { + "{C:chips}+#1#{} шт. фишек", + "без достоинства или масти" + } + }, + m_mult = { + name = "Карта с множителем", + text = { + "{C:mult}+#1#{} множ.", + } + }, + } + }, + misc = { + achievement_names = { + hidden_achievement = "???", + }, + achievement_descriptions = { + hidden_achievement = "Играйте больше, чтобы открыть!", + }, + dictionary = { + b_mods = 'Моды', + b_mods_cap = 'МОДЫ', + b_modded_version = 'Модифицированная версия!', + b_steamodded = 'Steamodded', + b_credits = 'Авторы', + b_open_mods_dir = 'Открыть папку с модами', + b_no_mods = 'Модов не найдено...', + b_mod_list = 'Список активированных модов', + b_mod_loader = 'Загрузчик модов', + b_developed_by = 'разработан ', + b_rewrite_by = 'Переписан ', + b_github_project = 'Github Проект', + b_github_bugs_1 = 'Вы можете сообщать нам о багах', + b_github_bugs_2 = 'и помочь в разработке.', + b_disable_mod_badges = 'Отключить значки модов', + b_author = 'Автор', + b_authors = 'Авторы', + b_unknown = 'Неизвестно', + b_lovely_mod = '(Мод на Lovely) ', + b_by = ' От: ', + b_priority = 'Приоритет: ', + b_config = "Настройки", + b_additions = 'Нововведения', + b_stickers = 'Наклейки', + b_achievements = "Достижения", + b_applies_stakes_1 = 'Применяет ', + b_applies_stakes_2 = '', + b_graphics_mipmap_level = "Уровни Mipmap", + b_browse = 'Найти', + b_search_prompt = 'Поиск модов', + b_search_button = 'Поиск', + b_seeded_unlocks = 'Разблокировка с сидами', + b_seeded_unlocks_info = 'Включает возможность открывать предметы коллекции в партиях с сидами', + ml_achievement_settings = { + 'Отключены', + 'Включены', + 'Обойти ограничения' + }, + b_deckskins_lc = 'Низкоконтрастные цвета', + b_deckskins_hc = 'Высококонтрастные цвета', + b_deckskins_def = 'Стандартные цвета', + }, + v_dictionary = { + c_types = '#1# Типов', + cashout_hidden = '...и #1# более', + a_xchips = "X#1# фишек", + a_xchips_minus = "-X#1# фишек", + smods_version_mismatch = { + "Версия Steamodded изменилась", + "с начала партии!", + "Продолжение может привести к", + "неожиданным последствиям и крашам.", + "Изначальная версия: #1#", + "Текущая версия: #2#", + } + }, + } +} diff --git a/Steamodded/localization/zh_CN.lua b/Steamodded/localization/zh_CN.lua index f9e259d..1423301 100644 --- a/Steamodded/localization/zh_CN.lua +++ b/Steamodded/localization/zh_CN.lua @@ -48,11 +48,11 @@ return { '({C:attention}#1#{})' } }, - load_failure_m = { -- To be translated + load_failure_m = { text = { - '{C:attention}Main File Not Found!{}', - 'This mod\'s main file', - 'could not be found.', + '{C:attention}主文件未找到!{}', + '此模组的主文件', + '有所缺失。', '({C:attention}#1#{})' } }, @@ -61,7 +61,81 @@ return { '该模组', '已被{C:attention}禁用{}!' } - } + }, + + + + -- card perma bonuses + card_extra_chips={ + text={ + "{C:chips}#1#{}额外筹码", + }, + }, + card_x_chips = { + text = { + "{X:chips,C:white}X#1#{}筹码" + } + }, + card_extra_x_chips = { + text = { + "{X:chips,C:white}X#1#{}额外筹码" + } + }, + card_extra_mult = { + text = { + "{C:mult}#1#{}额外倍率" + } + }, + card_x_mult = { + text = { + "{X:mult,C:white}X#1#{}倍率" + } + }, + card_extra_x_mult = { + text = { + "{X:mult,C:white}X#1#{}额外倍率" + } + }, + card_extra_p_dollars = { + text = { + "打出并计分时获得{C:money}$#1#{}", + } + }, + card_extra_h_chips = { + text = { + "留在手牌中时获得{C:chips}#1#{}筹码", + } + }, + card_h_x_chips = { + text = { + "留在手牌中时获得{X:chips,C:white}X#1#{}筹码", + } + }, + card_extra_h_x_chips = { + text = { + "留在手牌中时获得{X:chips,C:white}X#1#{}额外筹码", + } + }, + card_extra_h_mult = { + text = { + "留在手牌中时获得{C:mult}#1#{}额外倍率", + } + }, + card_h_x_mult = { + text = { + "留在手牌中时获得{X:mult,C:white}X#1#{}倍率", + } + }, + card_extra_h_x_mult = { + text = { + "留在手牌中时获得{X:mult,C:white}X#1#{}额外倍率", + } + }, + card_extra_h_dollars = { + text = { + "回合结束时还在手牌中则获得{C:money}#1#{}", + }, + }, }, Edition = { e_negative_playing_card = { @@ -70,14 +144,37 @@ return { "手牌上限{C:dark_edition}+#1#" }, }, - } + }, + Enhanced = { + m_gold={ + name="黄金牌", + text={ + "如果这张卡牌", + "在回合结束时还在手牌中", + "你获得{C:money}$#1#{}", + }, + }, + m_stone={ + name="石头牌", + text={ + "{C:chips}#1#{}筹码", + "无点数无花色", + }, + }, + m_mult={ + name="倍率牌", + text={ + "{C:mult}#1#{}倍率", + }, + }, + }, }, misc = { achievement_names = { hidden_achievement = "???", }, achievement_descriptions = { - hidden_achievement = "未发现", + hidden_achievement = "继续游玩以解锁!", }, dictionary = { b_mods = '模组', @@ -100,18 +197,41 @@ return { b_unknown = '未知', b_lovely_mod = '(依赖Lovely加载器的补丁模组)', b_by = ' 作者:', + b_priority = '优先级:', b_config = "配置", - b_additions = '新增项目', + b_additions = '新增内容', b_stickers = '贴纸', b_achievements = "成就", b_applies_stakes_1 = '', b_applies_stakes_2 = '的限制也都起效', b_graphics_mipmap_level = "多级渐远纹理层级", + b_browse = '浏览', + b_search_prompt = '搜索模组', + b_search_button = '搜索', + b_seeded_unlocks = '种子解锁', + b_seeded_unlocks_info = '在种子模式下启用解锁和发现', + ml_achievement_settings = { + '禁用', + '启用', + '绕过限制' + }, + b_deckskins_lc = '低对比度配色', + b_deckskins_hc = '高对比度配色', + b_deckskins_def = '默认配色', }, v_dictionary = { c_types = '共有#1#种', cashout_hidden = '……还有#1#', + a_xchips = "X#1# 筹码", + a_xchips_minus = "-X#1# 筹码", + smods_version_mismatch = { + "自本局游戏开始以来,", + "您的Steamodded版本已更改!", + "继续游戏可能导致", + "意外行为或游戏崩溃。", + "开始版本:#1#", + "当前版本:#2#", + }, }, }, - } diff --git a/Steamodded/lovely/atlas.toml b/Steamodded/lovely/atlas.toml index 8976a87..dd4c2ee 100644 --- a/Steamodded/lovely/atlas.toml +++ b/Steamodded/lovely/atlas.toml @@ -50,6 +50,20 @@ payload = '''self.original_T = copy_table(self.T)''' [[patches]] [patches.pattern] target = 'card.lua' +pattern = '''self.T.scale = 0.95''' +position = 'after' +match_indent = true +payload = '''self.original_T.scale = 0.95''' +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = '''self:set_ability(center, true)''' +position = 'before' +match_indent = true +payload = '''self.original_T = copy_table(self.T)''' +[[patches]] +[patches.pattern] +target = 'card.lua' match_indent = true position = 'before' pattern = ''' diff --git a/Steamodded/lovely/back.toml b/Steamodded/lovely/back.toml index 24efafc..b6af41f 100644 --- a/Steamodded/lovely/back.toml +++ b/Steamodded/lovely/back.toml @@ -191,3 +191,17 @@ if self.effect.config.jokers then })) end ''' + +# Load deck when continuing the run +# Game.start_run +[[patches]] +[patches.pattern] +target = 'game.lua' +pattern = "self.GAME.selected_back = Back(selected_back)" +position = 'after' +match_indent = true +payload = ''' +if saveTable then + self.GAME.selected_back:load(saveTable.BACK) +end +''' \ No newline at end of file diff --git a/Steamodded/lovely/better_calc.toml b/Steamodded/lovely/better_calc.toml index 89917c9..b3e095d 100644 --- a/Steamodded/lovely/better_calc.toml +++ b/Steamodded/lovely/better_calc.toml @@ -14,6 +14,7 @@ position = 'at' line_prepend = '$indent' payload = '''$handtext delay(0.3) +SMODS.calculate_context({initial_scoring_step = true, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands}) for _, v in ipairs(SMODS.get_card_areas('playing_cards')) do SMODS.calculate_main_scoring({cardarea = v, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands}, v == G.play and scoring_hand or nil) delay(0.3) @@ -34,7 +35,15 @@ match_indent = true payload = ''' function eval_card(card, context) context = context or {} - if not card:can_calculate(context.ignore_debuff) then return {}, {} end + if not card:can_calculate(context.ignore_debuff, context.remove_playing_cards) then + if card.ability.rental then + local ret = {} + ret[SMODS.Stickers.rental] = card:calculate_sticker(context, 'rental') + return ret, {} + end + return {}, {} + end + if context.other_card and context.other_card.can_calculate and not context.other_card:can_calculate(context.ignore_other_debuff or context.ignore_debuff) then return {}, {} end local ret = {} ''' @@ -106,16 +115,6 @@ if context.cardarea == G.play and context.main_scoring then end -- TARGET: main scoring on played cards - - local jokers = card:calculate_joker(context) - if jokers then - ret.jokers = jokers - end - - local edition = card:calculate_edition(context) - if edition then - ret.edition = edition - end end if context.end_of_round and context.cardarea == G.hand and context.playing_card_end_of_round then local end_of_round = card:get_end_of_round_effect(context) @@ -138,6 +137,11 @@ if context.cardarea == G.hand then if h_x_mult > 0 then ret.x_mult = h_x_mult end + + local jokers = card:calculate_joker(context) + if jokers then + ret.jokers = jokers + end ''' match_indent = true position = "at" @@ -185,6 +189,7 @@ if card.ability.set == 'Enhanced' then ret.enhancement = enhancement end end +if context.extra_enhancement then return ret end if card.edition then local edition = card:calculate_edition(context) if edition then @@ -197,7 +202,8 @@ if card.seal then ret.seals = seals end end -for k,v in pairs(SMODS.Stickers) do +for _,k in ipairs(SMODS.Sticker.obj_buffer) do + local v = SMODS.Stickers[k] local sticker = card:calculate_sticker(context, k) if sticker then ret[v] = sticker @@ -205,6 +211,14 @@ for k,v in pairs(SMODS.Stickers) do end -- TARGET: evaluate your own repetition effects +if card.ability.repetitions and card.ability.repetitions > 0 then + ret.seals = ret.seals or { card = card, message = localize('k_again_ex') } + ret.seals.repetitions = (ret.seals.repetitions and ret.seals.repetitions + card.ability.repetitions) or card.ability.repetitions +end +if card.ability.perma_repetitions and card.ability.perma_repetitions > 0 then + ret.seals = ret.seals or { card = card, message = localize('k_again_ex') } + ret.seals.repetitions = (ret.seals.repetitions and ret.seals.repetitions + card.ability.perma_repetitions) or card.ability.perma_repetitions +end """ [[patches]] [patches.pattern] @@ -219,19 +233,21 @@ if card.ability.set == 'Enhanced' then ret.enhancement = enhancement end end +if context.extra_enhancement then return ret end if card.edition then local edition = card:calculate_edition(context) if edition then ret.edition = edition end end -if card.seal and not card.ability.extra_enhancement then +if card.seal then local seals = card:calculate_seal(context) if seals then ret.seals = seals end end -for k,v in pairs(SMODS.Stickers) do +for _,k in ipairs(SMODS.Sticker.obj_buffer) do + local v = SMODS.Stickers[k] local sticker = card:calculate_sticker(context, k) if sticker then ret[v] = sticker @@ -272,7 +288,7 @@ if card.area and area_set[card.area] then if type(jokers) ~= 'table' then jokers = nil end if jokers or triggered then ret.jokers = jokers - if not (context.retrigger_joker_check or context.retrigger_joker) and not (jokers and jokers.no_retrigger) then + if not (context.retrigger_joker_check or context.retrigger_joker) and not (jokers and jokers.no_retrigger) and not context.mod_probability and not context.fix_probability then local retriggers = SMODS.calculate_retriggers(card, context, ret) if next(retriggers) then ret.retriggers = retriggers @@ -441,9 +457,11 @@ if next(joker_eval) then if joker_eval.retriggers then for rt = 1, #joker_eval.retriggers do local rt_eval, rt_post = eval_card(_card, {cardarea = G.jokers, full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, joker_main = true, retrigger_joker = true}) - table.insert(effects, {joker_eval.retriggers[rt]}) - table.insert(effects, rt_eval) - for _, v in ipairs(rt_post) do effects[#effects+1] = v end + if next(rt_eval) then + table.insert(effects, {retriggers = joker_eval.retriggers[rt]}) + table.insert(effects, rt_eval) + for _, v in ipairs(rt_post) do effects[#effects+1] = v end + end end end end''' @@ -485,9 +503,11 @@ for _, _area in ipairs(SMODS.get_card_areas('jokers')) do if joker_eval.retriggers then for rt = 1, #joker_eval.retriggers do local rt_eval, rt_post = eval_card(_joker, {full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, [other_key] = _card, retrigger_joker = true}) - table.insert(effects, {joker_eval.retriggers[rt]}) - table.insert(effects, rt_eval) - for _, v in ipairs(rt_post) do effects[#effects+1] = v end + if next(rt_eval) then + table.insert(effects, {retriggers = joker_eval.retriggers[rt]}) + table.insert(effects, rt_eval) + for _, v in ipairs(rt_post) do effects[#effects+1] = v end + end end end end @@ -507,9 +527,11 @@ for _, _area in ipairs(SMODS.get_card_areas('individual')) do if _eval.retriggers then for rt = 1, #_eval.retriggers do local rt_eval, rt_post = SMODS.eval_individual(_area, {full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, [other_key] = _card, retrigger_joker = true}) - table.insert(effects, {_eval.retriggers[rt]}) - table.insert(effects, rt_eval) - for _, v in ipairs(rt_post) do effects[#effects+1] = v end + if next(rt_eval) then + table.insert(effects, {_eval.retriggers[rt]}) + table.insert(effects, rt_eval) + for _, v in ipairs(rt_post) do effects[#effects+1] = v end + end end end end @@ -534,7 +556,7 @@ match_indent = true position = "at" payload = ''' local effects = {} -SMODS.calculate_context({discard = true, other_card = G.hand.highlighted[i], full_hand = G.hand.highlighted}, effects) +SMODS.calculate_context({discard = true, other_card = G.hand.highlighted[i], full_hand = G.hand.highlighted, ignore_other_debuff = true}, effects) SMODS.trigger_effects(effects) for _, eval in pairs(effects) do if type(eval) == 'table' then @@ -566,7 +588,9 @@ payload = ''' -- context.before calculations SMODS.calculate_context({full_hand = G.play.cards, scoring_hand = scoring_hand, scoring_name = text, poker_hands = poker_hands, before = true}) --- TARGET: effects before scoring starts''' +-- TARGET: effects before scoring starts + +SMODS.displayed_hand = nil''' # context.final_scoring_step [[patches]] @@ -606,7 +630,7 @@ for j = 1, #G.jokers.cards do end -if SMODS.has_enhancement(scoring_hand[i], 'm_glass') and scoring_hand[i]:can_calculate() and pseudorandom('glass') < G.GAME.probabilities.normal/(scoring_hand[i].ability.name == 'Glass Card' and scoring_hand[i].ability.extra or G.P_CENTERS.m_glass.config.extra) then +if SMODS.has_enhancement(scoring_hand[i], 'm_glass') and scoring_hand[i]:can_calculate() and SMODS.pseudorandom_probability(scoring_hand[i], 'glass', 1, scoring_hand[i].ability.name == 'Glass Card' and scoring_hand[i].ability.extra or G.P_CENTERS.m_glass.config.extra) then destroyed = true end @@ -751,6 +775,35 @@ for _, area in ipairs(SMODS.get_card_areas('jokers')) do end ''' +# context.round_eval +[[patches]] +[patches.pattern] +target = 'functions/state_events.lua' +pattern = ''' +G.GAME.selected_back:trigger_effect({context = 'eval'}) +''' +position = 'before' +match_indent = true +payload = ''' +SMODS.calculate_context{round_eval = true} +''' + +# Add better `add_round_eval_row` support +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +match_indent = true +position = 'before' +pattern = ''' +elseif string.find(config.name, 'joker') then +''' +payload = ''' +elseif config.name == 'custom' then + if config.number then table.insert(left_text, {n=G.UIT.T, config={text = config.number, scale = 0.8*scale, colour = config.number_colour or G.C.FILTER, shadow = true, juice = true}}) end + table.insert(left_text, {n=G.UIT.O, config={object = DynaText({string = {" "..config.text}, colours = {config.text_colour or G.C.UI.TEXT_LIGHT}, shadow = true, pop_in = 0, scale = 0.4*scale, silent = true})}}) +''' + + # context.end_of_round [[patches]] [patches.pattern] @@ -774,7 +827,8 @@ match_indent = true payload = ''' -- context.end_of_round calculations SMODS.saved = false -SMODS.calculate_context({end_of_round = true, game_over = game_over }) +G.GAME.saved_text = nil +SMODS.calculate_context({end_of_round = true, game_over = game_over, beat_boss = G.GAME.blind.boss }) if SMODS.saved then game_over = false end -- TARGET: main end_of_round evaluation ''' @@ -787,10 +841,21 @@ position = 'at' pattern = '''(?[\t ]*)for i=1, #G\.hand\.cards do\n\s+--Check for hand doubling\n(.*\n)*?\s+delay\(0\.3\)''' line_prepend = '$indent' payload = '''for _,v in ipairs(SMODS.get_card_areas('playing_cards', 'end_of_round')) do - SMODS.calculate_end_of_round_effects({ cardarea = v, end_of_round = true }) + SMODS.calculate_end_of_round_effects({ cardarea = v, end_of_round = true, beat_boss = G.GAME.blind.boss }) end ''' +# store associated blind tag as a global object +[[patches]] +[patches.pattern] +target = "functions/button_callbacks.lua" +pattern = "G.GAME.round_resets.blind = e.config.ref_table" +position = "before" +payload = ''' +local _tag = e.UIBox:get_UIE_by_ID('tag_container') +G.GAME.round_resets.blind_tag = _tag and _tag.config and _tag.config.ref_table or nil +''' +match_indent = true # context.setting_blind [[patches]] @@ -842,9 +907,11 @@ for _,v in ipairs(post) do effects[#effects+1] = v end if eval.retriggers then for rt = 1, #eval.retriggers do local rt_eval, rt_post = eval_card(self, { selling_self = true, retrigger_joker = true}) - table.insert(effects, {eval.retriggers[rt]}) - table.insert(effects, rt_eval) - for _, v in ipairs(rt_post) do effects[#effects+1] = v end + if next(rt_eval) then + table.insert(effects, {eval.retriggers[rt]}) + table.insert(effects, rt_eval) + for _, v in ipairs(rt_post) do effects[#effects+1] = v end + end end end SMODS.trigger_effects(effects, self) @@ -984,6 +1051,37 @@ G.E_MANAGER:add_event(Event({ end })) ''' +[[patches]] +[patches.pattern] +target = 'functions/state_events.lua' +match_indent = true +position = 'at' +pattern = ''' +draw_card(G.deck,G.hand, i*100/hand_space,'up', true) +''' +payload = ''' +draw_card(G.deck,G.hand, i*100/hand_space,'up', true, cards_to_draw[i]) +''' + + +# context.hand_space +[[patches]] +[patches.pattern] +target = 'functions/state_events.lua' +match_indent = true +position = 'after' +pattern = ''' +if G.GAME.blind.name == 'The Serpent' and + not G.GAME.blind.disabled and + (G.GAME.current_round.hands_played > 0 or + G.GAME.current_round.discards_used > 0) then + hand_space = math.min(#G.deck.cards, 3) +end +''' +payload = ''' +local flags = SMODS.calculate_context({drawing_cards = true, amount = hand_space}) +hand_space = math.min(#G.deck.cards, flags.cards_to_draw or hand_space) +''' # Used to identify first hand of round # new_round @@ -1054,7 +1152,7 @@ position = 'at' match_indent = true payload = ''' G.E_MANAGER:add_event(Event({func = function() - local eval, post = eval_card(c1, {buying_card = true, card = c1}) + local eval, post = eval_card(c1, {buying_card = true, buying_self = true, card = c1}) -- buying_card left for back compat, buying_self recommended to use SMODS.trigger_effects({eval, post}, c1) return true end})) @@ -1151,14 +1249,13 @@ target = 'functions/button_callbacks.lua' match_indent = true position = 'before' pattern = ''' -if G.GAME.current_round.reroll_cost > 0 then +if G.GAME.current_round.reroll_cost > 0 then ''' payload = ''' local reroll_cost = G.GAME.current_round.reroll_cost ''' - # Fix purple seal calc [[patches]] [patches.pattern] @@ -1173,16 +1270,29 @@ if context.discard and context.other_card == self then if self.seal == 'Purple' and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then''' # Fix context.blueprint persisting +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = '''context.blueprint = (context.blueprint and (context.blueprint + 1)) or 1 +context.blueprint_card = context.blueprint_card or self +if context.blueprint > #G.jokers.cards + 1 then return end''' +payload = '''if (context.blueprint or 0) > #G.jokers.cards then return end +local old_context_blueprint = context.blueprint +context.blueprint = (context.blueprint and (context.blueprint + 1)) or 1 +local old_context_blueprint_card = context.blueprint_card +context.blueprint_card = context.blueprint_card or self +local eff_card = context.blueprint_card''' + [[patches]] [patches.pattern] target = 'card.lua' match_indent = true position = 'after' -pattern = 'local other_joker_ret = other_joker:calculate_joker(context)' -payload = ''' -context.blueprint = nil -local eff_card = context.blueprint_card or self -context.blueprint_card = nil''' +pattern = '''local other_joker_ret = other_joker:calculate_joker(context)''' +payload = '''context.blueprint = old_context_blueprint +context.blueprint_card = old_context_blueprint_card''' [[patches]] [patches.pattern] @@ -1257,6 +1367,17 @@ payload = '''percent = (i-0.999)/(#G.hand.cards-0.998) + (j-1)*0.1''' target = 'functions/common_events.lua' match_indent = true position = 'after' +pattern = 'local volume = 1' +payload = ''' +local trigger = 'before' +local blocking = nil +local blockable = nil +''' +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +match_indent = true +position = 'after' pattern = ''' volume = extra.edition and 0.3 or sound == 'multhit2' and 0.7 or 1 ''' @@ -1264,6 +1385,9 @@ payload = ''' sound = extra.sound or sound percent = extra.pitch or percent volume = extra.volume or volume +trigger = extra.trigger or 'before' +blocking = extra.blocking +blockable = extra.blockable ''' # Voucher cardarea @@ -1412,7 +1536,7 @@ for i=1, #G.play.cards do end end local effects = {} - SMODS.calculate_context({modify_scoring_hand = true, other_card = G.play.cards[i], full_hand = G.play.cards, scoring_hand = scoring_hand}, effects) + SMODS.calculate_context({modify_scoring_hand = true, other_card = G.play.cards[i], full_hand = G.play.cards, scoring_hand = scoring_hand, in_scoring = true}, effects) local flags = SMODS.trigger_effects(effects, G.play.cards[i]) if flags.add_to_hand then splashed = true end if flags.remove_from_hand then unsplashed = true end @@ -1443,7 +1567,7 @@ payload = ''' SMODS.calculate_context({ending_booster = true, booster = booster_obj}) ''' -# Fix playing_card_added jank +# Fix Certificate to use SMODS.poll_seal and use playing_card_added context correctly [[patches]] [patches.pattern] target = 'card.lua' @@ -1470,25 +1594,19 @@ G.E_MANAGER:add_event(Event({ playing_card_joker_effects({true}) ''' payload = ''' -local _card = create_playing_card({ - front = pseudorandom_element(G.P_CARDS, pseudoseed('cert_fr')), - center = G.P_CENTERS.c_base}, G.discard, true, nil, {G.C.SECONDARY_SET.Enhanced}, true) -local seal_type = pseudorandom(pseudoseed('certsl')) -if seal_type > 0.75 then _card:set_seal('Red', true) -elseif seal_type > 0.5 then _card:set_seal('Blue', true) -elseif seal_type > 0.25 then _card:set_seal('Gold', true) -else _card:set_seal('Purple', true) -end G.E_MANAGER:add_event(Event({ func = function() - G.hand:emplace(_card) - _card:start_materialize() + local _card = create_playing_card({ + front = pseudorandom_element(G.P_CARDS, pseudoseed('cert_fr')), + center = G.P_CENTERS.c_base}, G.hand, nil, nil, {G.C.SECONDARY_SET.Enhanced}) + _card:set_seal(SMODS.poll_seal({type_key = 'certsl', guaranteed = true}), nil, true) G.GAME.blind:debuff_card(_card) G.hand:sort() if context.blueprint_card then context.blueprint_card:juice_up() else self:juice_up() end + playing_card_joker_effects({_card}) + save_run() return true end})) -playing_card_joker_effects({_card}) ''' # create_playing_card @@ -1515,6 +1633,7 @@ payload = ''' if area and not skip_emplace then area:emplace(card) end ''' +## Fix Marble Joker to send the created card to playing_card_added correctly # Marble Joker [[patches]] [patches.pattern] @@ -1544,27 +1663,29 @@ G.E_MANAGER:add_event(Event({ playing_card_joker_effects({true}) ''' payload = ''' -local front = pseudorandom_element(G.P_CARDS, pseudoseed('marb_fr')) -G.playing_card = (G.playing_card and G.playing_card + 1) or 1 -local card = Card(G.discard.T.x + G.discard.T.w/2, G.discard.T.y, G.CARD_W, G.CARD_H, front, G.P_CENTERS.m_stone, {playing_card = G.playing_card}) G.E_MANAGER:add_event(Event({ func = function() - card:start_materialize({G.C.SECONDARY_SET.Enhanced}) - G.play:emplace(card) - table.insert(G.playing_cards, card) + local card = create_playing_card({ + front = pseudorandom_element(G.P_CARDS, pseudoseed('marb_fr')), + center = G.P_CENTERS.m_stone}, G.play, nil, nil, {G.C.SECONDARY_SET.Enhanced}) + SMODS.calculate_effect({message = localize('k_plus_stone'), colour = G.C.SECONDARY_SET.Enhanced}, context.blueprint_card or self) + G.E_MANAGER:add_event(Event({ + func = function() + draw_card(G.play,G.deck, 90,'up', nil) + return true + end})) + playing_card_joker_effects({card}) return true end})) -card_eval_status_text(context.blueprint_card or self, 'extra', nil, nil, nil, {message = localize('k_plus_stone'), colour = G.C.SECONDARY_SET.Enhanced}) - -G.E_MANAGER:add_event(Event({ - func = function() - G.deck.config.card_limit = G.deck.config.card_limit + 1 - return true - end})) - draw_card(G.play,G.deck, 90,'up', nil) - -playing_card_joker_effects({card}) ''' +# DNA +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = 'playing_cards_created = {true}' +payload = 'playing_cards_created = {_card}' ## Remove unneeded area check # Card:calculate_joker @@ -1577,8 +1698,276 @@ pattern = 'if context.cardarea == G.jokers then' payload = 'do' [[patches]] -[patches.regex] +[patches.pattern] target = 'game.lua' position = 'at' -pattern = 'G.GAME.blind:get_loc_debuff_text\(\)' -payload = 'SMODS.debuff_text or G.GAME.blind:get_loc_debuff_text()' \ No newline at end of file +pattern = '{n=G.UIT.O, config={object = DynaText({scale = 0.6, string = G.GAME.blind:get_loc_debuff_text(), maxw = 9, colours = {G.C.WHITE},float = true, shadow = true, silent = true, pop_in = 0, pop_in_rate = 6})}},' +payload = '{n=G.UIT.O, config={func = "update_blind_debuff_text", object = DynaText({scale = 0.6, string = SMODS.debuff_text or G.GAME.blind:get_loc_debuff_text(), maxw = 9, colours = {G.C.WHITE},float = true, shadow = true, silent = true, pop_in = 0, pop_in_rate = 6})}},' +match_indent = true + +# Custom saved message +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +match_indent = true +position = 'at' +pattern = ''' +{n=G.UIT.O, config={object = DynaText({string = {' '..localize('ph_mr_bones')..' '}, colours = {G.C.FILTER}, shadow = true, pop_in = 0, scale = 0.5*scale, silent = true})}} +''' +payload = ''' +{n=G.UIT.O, config={object = DynaText({string = {' '..(type(G.GAME.saved_text) == 'string' and (G.localization.misc.dictionary[G.GAME.saved_text] and localize(G.GAME.saved_text) or G.GAME.saved_text) or localize('ph_mr_bones'))..' '}, colours = {G.C.FILTER}, shadow = true, pop_in = 0, scale = 0.5*scale, silent = true})}} +''' + +# Customise dissolve colours from calculate +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'before' +pattern = ''' +local dissolve_time = 0.7*(dissolve_time_fac or 1) +''' +payload = ''' +dissolve_colours = dissolve_colours or (type(self.destroyed) == 'table' and self.destroyed.colours) or nil +dissolve_time_fac = dissolve_time_fac or (type(self.destroyed) == 'table' and self.destroyed.time) or nil +''' + +# Smart level up functionality +# G.FUNCS.evaluate_play() +[[patches]] +[patches.pattern] +target = 'functions/state_events.lua' +match_indent = false +position = 'after' +pattern = '''delay = G.GAME.current_round.current_hand.handname ~= disp_text and 0.4 or 0}, {handname=disp_text, level=G.GAME.hands[text].level, mult = G.GAME.hands[text].mult, chips = G.GAME.hands[text].chips})''' +payload = ''' SMODS.displayed_hand = text; SMODS.displaying_scoring = true''' +[[patches]] +[patches.pattern] +target = 'functions/state_events.lua' +match_indent = true +position = 'after' +pattern = '''hand_chips = mod_chips(0)''' +payload = '''SMODS.displayed_hand = nil''' +times = 1 +[[patches]] +[patches.pattern] +target = 'functions/state_events.lua' +match_indent = false +position = 'after' +pattern = ''' + func = (function() G.GAME.current_round.current_hand.handname = '';return true end) +})) +delay(0.3)''' +payload = ''' SMODS.displaying_scoring = nil''' + +# Adjust food jokers +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = ''' +G.E_MANAGER:add_event(Event({ + func = function() + play_sound('tarot1') + self.T.r = -0.2 + self:juice_up(0.3, 0.4) + self.states.drag.is = true + self.children.center.pinch.x = true + G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.3, blockable = false, + func = function() + G.jokers:remove_card(self) + self:remove() + self = nil + return true; end})) + return true + end +})) +''' +payload = ''' +SMODS.destroy_cards(self, nil, nil, true) +''' + +# Joker-type removed context added +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'after' +pattern = ''' +function Card:start_dissolve(dissolve_colours, silent, dissolve_time_fac, no_juice) +''' +payload = ''' + if self.getting_sliced and not (self.ability.set == 'Default' or self.ability.set == 'Enhanced') then + local flags = SMODS.calculate_context({joker_type_destroyed = true, card = self}) + if flags.no_destroy then self.getting_sliced = nil; return end + end + if self.skip_destroy_animation then + G.E_MANAGER:add_event(Event({ + func = function() + play_sound('tarot1') + self.T.r = -0.2 + self:juice_up(0.3, 0.4) + self.states.drag.is = true + self.children.center.pinch.x = true + G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.3, blockable = false, + func = function() + G.jokers:remove_card(self) + self:remove() + self = nil + return true; end})) + return true + end + })) + return + end +''' +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'after' +pattern = ''' +function Card:shatter() +''' +payload = ''' + if self.getting_sliced and not (self.ability.set == 'Default' or self.ability.set == 'Enhanced') then + local flags = SMODS.calculate_context({joker_type_destroyed = true, card = self, shatters = true}) + if flags.no_destroy then self.getting_sliced = nil; return end + end + if self.skip_destroy_animation then + G.E_MANAGER:add_event(Event({ + func = function() + play_sound('tarot1') + self.T.r = -0.2 + self:juice_up(0.3, 0.4) + self.states.drag.is = true + self.children.center.pinch.x = true + G.E_MANAGER:add_event(Event({trigger = 'after', delay = 0.3, blockable = false, + func = function() + G.jokers:remove_card(self) + self:remove() + self = nil + return true; end})) + return true + end + })) + return + end +''' + + +## Change eternal checks +# Ceremonial Dagger +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = ''' +if my_pos and G.jokers.cards[my_pos+1] and not self.getting_sliced and not G.jokers.cards[my_pos+1].ability.eternal and not G.jokers.cards[my_pos+1].getting_sliced then +''' +payload = ''' +if my_pos and G.jokers.cards[my_pos+1] and not self.getting_sliced and not SMODS.is_eternal(G.jokers.cards[my_pos+1], self) and not G.jokers.cards[my_pos+1].getting_sliced then +''' +# Madness +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = ''' +if G.jokers.cards[i] ~= self and not G.jokers.cards[i].ability.eternal and not G.jokers.cards[i].getting_sliced then destructable_jokers[#destructable_jokers+1] = G.jokers.cards[i] end +''' +payload = ''' +if G.jokers.cards[i] ~= self and not SMODS.is_eternal(G.jokers.cards[i], self) and not G.jokers.cards[i].getting_sliced then destructable_jokers[#destructable_jokers+1] = G.jokers.cards[i] end +''' +# Ankh +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = ''' +if not v.ability.eternal then deletable_jokers[#deletable_jokers + 1] = v end +''' +payload = ''' +if not SMODS.is_eternal(v, self) then deletable_jokers[#deletable_jokers + 1] = v end +''' +# Hex SMODS.is_eternal and card.getting_sliced +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = ''' +if v ~= eligible_card and (not v.ability.eternal) then v:start_dissolve(nil, _first_dissolve);_first_dissolve = true end +''' +payload = ''' +if v ~= eligible_card and (not SMODS.is_eternal(v, self)) then v.getting_sliced = true; v:start_dissolve(nil, _first_dissolve);_first_dissolve = true end +''' +# Card:can_sell() +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = ''' +not self.ability.eternal then +''' +payload = ''' +not SMODS.is_eternal(self, {from_sell = true}) then +''' + +# Adds tag_added context +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +match_indent = true +position = 'after' +pattern = ''' +G.GAME.tags[#G.GAME.tags+1] = _tag +''' +payload = ''' +if not _tag.from_load then SMODS.calculate_context({tag_added = _tag}) end +_tag.from_load = nil +''' + +# Prevent tag added context on reloading +[[patches]] +[patches.pattern] +target = 'tag.lua' +match_indent = true +position = 'after' +pattern = ''' +G.GAME.tag_tally = math.max(self.tally, G.GAME.tag_tally) + 1 +''' +payload = ''' +self.from_load = true +''' + +# Fix Campfire 'upgrading' when it is sold +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = ''' +if self.ability.name == 'Campfire' and not context.blueprint then +''' +payload = ''' +if self.ability.name == 'Campfire' and not context.blueprint and self ~= context.card then +''' + +# Support for ante contexts +[[patches]] +[patches.pattern] +target = 'functions/state_events.lua' +match_indent = true +pattern = ''' +delay(0.4); ease_ante(1); delay(0.4); check_for_unlock({type = 'ante_up', ante = G.GAME.round_resets.ante + 1}) +''' +position = 'at' +payload = ''' +delay(0.4); ease_ante(1, true); delay(0.4); check_for_unlock({type = 'ante_up', ante = G.GAME.round_resets.ante + 1}) +''' diff --git a/Steamodded/lovely/better_calc_fixes.toml b/Steamodded/lovely/better_calc_fixes.toml new file mode 100644 index 0000000..d572ff9 --- /dev/null +++ b/Steamodded/lovely/better_calc_fixes.toml @@ -0,0 +1,31 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +## Delayed references to context.blueprint_card should be saved in a variable +## because context is modified in better calc +## (this patch just changes all references) +# Card:calculate_joker(context) +[[patches]] +[patches.pattern] +target = 'card.lua' +position = 'after' +pattern = '''function Card:calculate_joker(context) + if self.debuff then return nil end +''' +payload = ' local context_blueprint_card = context.blueprint_card' +match_indent = true +[[patches]] +[patches.regex] +target = 'card.lua' +position = 'at' +pattern = 'card_eval_status_text\(context\.blueprint_card or self' +payload = 'card_eval_status_text(context_blueprint_card or self' +[[patches]] +[patches.pattern] +target = 'card.lua' +position = 'at' +pattern = 'if context.blueprint_card then context.blueprint_card:juice_up() else self:juice_up() end' +payload = 'if context_blueprint_card then context_blueprint_card:juice_up() else self:juice_up() end' +match_indent = true \ No newline at end of file diff --git a/Steamodded/lovely/blind.toml b/Steamodded/lovely/blind.toml index 4ec899e..65cf8f7 100644 --- a/Steamodded/lovely/blind.toml +++ b/Steamodded/lovely/blind.toml @@ -398,7 +398,7 @@ match_indent = true position = 'before' payload = ''' elseif v.in_pool and type(v.in_pool) == 'function' then - local res, options = v:in_pool() + local res, options = SMODS.add_to_pool(v) if ( ((G.GAME.round_resets.ante)%G.GAME.win_ante == 0 and G.GAME.round_resets.ante >= 2) == @@ -464,4 +464,36 @@ pattern = '''(?[\t ]*)elseif self\.name == 'Crimson Heart' and not self\ position = 'at' line_prepend = '$indent' payload = '''end -if self.name == 'Crimson Heart' and not self.disabled''' \ No newline at end of file +if self.name == 'Crimson Heart' and not self.disabled''' + +### Add blind.effect +# Blind.set_blind +[[patches]] +[patches.pattern] +target = "blind.lua" +match_indent = true +pattern = "self.config.blind = blind or {}" +position = "after" +payload = ''' +self.effect = type(self.config.blind.config) == "table" and copy_table(self.config.blind.config) or {} +''' +# Blind.load +[[patches]] +[patches.pattern] +target = "blind.lua" +match_indent = true +pattern = "function Blind:load(blindTable)" +position = "after" +payload = ''' +self.effect = blindTable.effect +''' +# Blind.save +[[patches]] +[patches.pattern] +target = "blind.lua" +match_indent = true +pattern = "local blindTable = {" +position = "after" +payload = ''' +effect = self.effect, +''' \ No newline at end of file diff --git a/Steamodded/lovely/booster.toml b/Steamodded/lovely/booster.toml index fd1af8a..3a681e0 100644 --- a/Steamodded/lovely/booster.toml +++ b/Steamodded/lovely/booster.toml @@ -36,9 +36,24 @@ if booster_obj and SMODS.Centers[booster_obj.key] then G.STATE = G.STATES.SMODS_BOOSTER_OPENED SMODS.OPENED_BOOSTER = self end -G.GAME.pack_choices = self.ability.choose or self.config.center.config.choose or 1 +G.GAME.pack_choices = math.min((self.ability.choose or self.config.center.config.choose or 1) + (G.GAME.modifiers.booster_choice_mod or 0), self.ability.extra and math.max(1, self.ability.extra + (G.GAME.modifiers.booster_size_mod or 0)) or self.config.center.extra and math.max(1, self.config.center.extra + (G.GAME.modifiers.booster_size_mod or 0)) or 1) """ +# Card:open +# Adds modifier for size of booster +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = ''' +local _size = self.ability.extra +''' +payload = ''' +local _size = math.max(1, self.ability.extra + (G.GAME.modifiers.booster_size_mod or 0)) +''' + + # Card:open [[patches]] [patches.regex] @@ -64,7 +79,8 @@ pattern = '''(?[\t ]*)self\.STATES = \{''' position = "after" payload = ''' - SMODS_BOOSTER_OPENED = 999,''' + SMODS_BOOSTER_OPENED = 999, + SMODS_REDEEM_VOUCHER = 998,''' line_prepend = '$indent' # Game:update @@ -233,7 +249,7 @@ end''' line_prepend = '$indent' # Add support for saving consumables -# comment +# G.UIDEF.use_and_sell_buttons() [[patches]] [patches.pattern] target = 'functions/UI_definitions.lua' @@ -255,7 +271,7 @@ if card.ability.consumeable and card.area == G.pack_cards and booster_obj and bo end ''' -# comment +# G.FUNCS.use_card() [[patches]] [patches.pattern] target = 'functions/button_callbacks.lua' @@ -279,7 +295,7 @@ if select_to then elseif card.ability.consumeable then if nc then ''' -# comment +# G.FUNCS.end_consumeable() [[patches]] [patches.pattern] target = 'functions/button_callbacks.lua' @@ -299,7 +315,7 @@ G.E_MANAGER:add_event(Event({trigger = 'after',delay = 0.2*delayfac, payload = ''' booster_obj = nil ''' -# comment +# G.FUNCS.skip_booster() [[patches]] [patches.pattern] target = 'functions/button_callbacks.lua' @@ -321,5 +337,15 @@ match_indent = true position = 'at' pattern = "if e.config.ref_table.ability.set ~= 'Joker' or (e.config.ref_table.edition and e.config.ref_table.edition.negative) or #G.jokers.cards < G.jokers.config.card_limit then" payload = '''local card = e.config.ref_table -local card_limit = card.edition and card.edition.card_limit or 0 +local card_limit = card.ability.card_limit if card.ability.set ~= 'Joker' or #G.jokers.cards < G.jokers.config.card_limit + card_limit then''' + +# Card:redeem() +# Specific G.STATE for when a Voucher is redeemed +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'after' +pattern = '''if self.shop_voucher then G.GAME.current_round.voucher = nil end''' +payload = '''G.STATE = G.STATES.SMODS_REDEEM_VOUCHER''' \ No newline at end of file diff --git a/Steamodded/lovely/calculate_card_added.toml b/Steamodded/lovely/calculate_card_added.toml index 478067b..caeac14 100644 --- a/Steamodded/lovely/calculate_card_added.toml +++ b/Steamodded/lovely/calculate_card_added.toml @@ -5,11 +5,14 @@ priority = -5 # Add card_added context [[patches]] -[patches.pattern] +[patches.regex] target = "card.lua" -pattern = '''if G.GAME.blind and G.GAME.blind.in_blind then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end''' +pattern = ''' +(?[\t ]*).*then G\.E_MANAGER:add_event\(Event\(\{ func = function\(\) G\.GAME\.blind:set_blind\(nil, true, nil\); return true end \}\)\) end +(?)[\s\S]* +function Card:remove_from_deck''' position = "after" -match_indent = true +line_prepend = "$indent" payload = ''' if not from_debuff and G.hand then local is_playing_card = self.ability.set == 'Default' or self.ability.set == 'Enhanced' @@ -22,4 +25,5 @@ if not from_debuff and G.hand then end end ''' +root_capture = '$root' times = 1 diff --git a/Steamodded/lovely/card_limit.toml b/Steamodded/lovely/card_limit.toml new file mode 100644 index 0000000..c9ffee7 --- /dev/null +++ b/Steamodded/lovely/card_limit.toml @@ -0,0 +1,311 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +# Set metatable +[[patches]] +[patches.pattern] +target = 'cardarea.lua' +match_indent = true +position = 'at' +pattern = ''' +self.config = config or {} +''' +payload = ''' +self.config = setmetatable({card_limits = {card_limit}}, { + __index = function(t, key) + if key == "card_limit" then + return t.card_limits.card_limit + end + end, + __newindex = function(t, key, value) + if key == 'card_limit' then + t.true_card_limit = t.true_card_limit or 0 + if not t.no_true_limit then rawset(t, 'true_card_limit', math.max(0, t.true_card_limit + value - (t.card_limits.card_limit or 0))) end + rawset(t.card_limits, key, value) + else + rawset(t, key, value) + end + end +}) + +SMODS.merge_defaults(self.config, config) +''' + +# Load metatable +[[patches]] +[patches.pattern] +target = 'cardarea.lua' +match_indent = true +position = 'at' +pattern = ''' +self.config = cardAreaTable.config +''' +payload = ''' +self.config = setmetatable(cardAreaTable.config, { + __index = function(t, key) + if key == "card_limit" then + return t.card_limits.card_limit + end + end, + __newindex = function(t, key, value) + if key == 'card_limit' then + t.true_card_limit = t.true_card_limit or 0 + if not t.no_true_limit then rawset(t, 'true_card_limit', math.max(0, t.true_card_limit + value - (t.card_limits.card_limit or 0))) end + rawset(t.card_limits, key, value) + else + rawset(t, key, value) + end + end +}) + +''' + +# Bypass CardArea:change_size() +[[patches]] +[patches.pattern] +target = 'cardarea.lua' +match_indent = true +position = 'after' +pattern = ''' +function CardArea:change_size(delta) +''' +payload = ''' + if true then + self:handle_card_limit(delta) + return + end +''' + + +# CardArea:init() +# Add real_card_limit parameter +[[patches]] +[patches.pattern] +target = 'cardarea.lua' +match_indent = true +position = 'after' +pattern = ''' +self.config.card_limit = config.card_limit or 52 +''' +payload = ''' +self.config.true_card_limit = self.config.card_limit +''' + + + +# CardArea:emplace() +# Modifies card_limit +[[patches]] +[patches.pattern] +target = 'cardarea.lua' +match_indent = true +position = 'after' +pattern = ''' +function CardArea:emplace(card, location, stay_flipped) +''' +payload = ''' + self:handle_card_limit(card.ability.card_limit, card.ability.extra_slots_used) +''' +# CardArea:update() +[[patches]] +[patches.pattern] +target = 'cardarea.lua' +match_indent = true +position = 'at' +pattern = ''' +if self == G.deck and self.config.card_limit > #G.playing_cards then self.config.card_limit = #G.playing_cards end +''' +payload = ''' +if self == G.deck and (self.config.card_limit ~= #G.playing_cards or self.config.true_card_limit ~= #G.playing_cards) then self.config.card_limit = #G.playing_cards; self.config.true_card_limit = #G.playing_cards end +''' + + + +# CardArea:remove_card() +[[patches]] +[patches.pattern] +target = 'cardarea.lua' +match_indent = true +position = 'after' +pattern = ''' +card:remove_from_area() +''' +payload = ''' +self:handle_card_limit(-1 * (card.ability.card_limit or 0), -1 * (card.ability.extra_slots_used or 0)) +''' + +# Card:add_to_deck() +# remove vanilla functionality +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = ''' +if self.edition and self.edition.negative then + if from_debuff then + self.ability.queue_negative_removal = nil + else + if self.ability.consumeable then + G.consumeables.config.card_limit = G.consumeables.config.card_limit + 1 + else + G.jokers.config.card_limit = G.jokers.config.card_limit + 1 + end + end + end +''' +payload = ''' +-- removed by SMODS +''' + +# Card:remove_from_deck() +# remove vanilla functionality +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = ''' +if self.edition and self.edition.negative and G.jokers then + if from_debuff then + self.ability.queue_negative_removal = true + else + if self.ability.consumeable then + G.consumeables.config.card_limit = G.consumeables.config.card_limit - 1 + else + G.jokers.config.card_limit = G.jokers.config.card_limit - 1 + end + end + end +''' +payload = ''' +-- removed by SMODS +''' + +# CardArea:update() +# Add support for extra_slots_used parameter +[[patches]] +[patches.pattern] +target = 'cardarea.lua' +match_indent = true +position = 'at' +pattern = ''' +self.config.card_count = #self.cards +''' +payload = ''' +self.config.card_count = self:count_extra_slots_used(self.cards) +''' + +# CardArea:draw() +# Change count display to use true_card_limit +[[patches]] +[patches.pattern] +target = 'cardarea.lua' +match_indent = true +position = 'at' +pattern = ''' +{n=G.UIT.T, config={ref_table = self.config, ref_value = 'card_limit', scale = 0.3, colour = G.C.WHITE}}, +''' +payload = ''' +{n=G.UIT.T, config={ref_table = self.config, ref_value = 'true_card_limit', scale = 0.3, colour = G.C.WHITE}}, +''' + +# Add negative info_queue support +[[patches]] +[patches.pattern] +target = 'game.lua' +match_indent = true +position = 'at' +pattern = ''' +{card_limit = self.GAME.starting_params.consumable_slots, type = 'joker', highlight_limit = 1}) +''' +payload = ''' +{card_limit = self.GAME.starting_params.consumable_slots, type = 'joker', highlight_limit = 1, negative_info = 'consumable'}) +''' +[[patches]] +[patches.pattern] +target = 'game.lua' +match_indent = true +position = 'at' +pattern = ''' +{card_limit = self.GAME.starting_params.joker_slots, type = 'joker', highlight_limit = 1}) +''' +payload = ''' +{card_limit = self.GAME.starting_params.joker_slots, type = 'joker', highlight_limit = 1, negative_info = 'joker'}) +''' +[[patches]] +[patches.pattern] +target = 'game.lua' +match_indent = true +position = 'at' +pattern = ''' +{card_limit = self.GAME.starting_params.hand_size, type = 'hand'}) +''' +payload = ''' +{card_limit = self.GAME.starting_params.hand_size, type = 'hand', negative_info = 'playing_card'}) +''' +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +match_indent = true +position = 'at' +pattern = ''' +{card_limit = G.GAME.shop.joker_max, type = 'shop', highlight_limit = 1}) +''' +payload = ''' +{card_limit = G.GAME.shop.joker_max, type = 'shop', highlight_limit = 1, negative_info = true}) +''' + + +# generate_card_ui() +# Adds info queue tooltips for generic card limit and slots used +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +match_indent = true +position = 'before' +pattern = ''' +if first_pass and not (_c.set == 'Edition') and badges then +''' +payload = ''' +if card and card.ability and (card.ability.extra_slots_used or 0) ~= 0 then + info_queue[#info_queue + 1] = {set = 'Other', key = 'generic_extra_slots', vars = {card.ability.extra_slots_used + 1}} +end +if card and card.ability and (card.ability.card_limit or 0) ~= 0 then + if not (card.edition and card.edition.card_limit == card.ability.card_limit) then + local amount = card.ability.card_limit - (card.edition and card.edition.card_limit or 0) + info_queue[#info_queue + 1] = {set = 'Other', key = amount == 1 and 'generic_card_limit' or 'generic_card_limit_plural', vars = {localize({type='variable', key= amount > 0 and 'a_chips' or 'a_chips_minus', vars ={math.abs(amount)}})}} + end +end +''' + + + +# G.FUNCS.draw_from_deck_to_hand() +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = "local hand_space = e or*" +position = "at" +payload = """local hand_space = e +local cards_to_draw = {} +if not hand_space then + local limit = G.hand.config.card_limit - #G.hand.cards + local unfixed = not G.hand.config.fixed_limit + local n = 0 + while n < #G.deck.cards do + local card = G.deck.cards[#G.deck.cards-n] + local mod = unfixed and (card.ability.card_limit - card.ability.extra_slots_used) or 0 + if limit - 1 + mod < 0 then + else + limit = limit - 1 + mod + table.insert(cards_to_draw, card) + if limit <= 0 then break end + end + n = n + 1 + end + hand_space = #cards_to_draw +end""" +match_indent = true \ No newline at end of file diff --git a/Steamodded/lovely/center.toml b/Steamodded/lovely/center.toml index e183c8e..e9b6a1f 100644 --- a/Steamodded/lovely/center.toml +++ b/Steamodded/lovely/center.toml @@ -102,7 +102,23 @@ position = 'before' match_indent = true payload = ''' elseif _c.generate_ui and type(_c.generate_ui) == 'function' then + local specific_vars = specific_vars or {} + if is_info_queue then specific_vars.is_info_queue = true end _c:generate_ui(info_queue, card, desc_nodes, specific_vars, full_UI_table) + if is_info_queue then + desc_nodes.loc_name = {} + local set = name_override and "Other" or _c.set + local key = name_override or _c.key + if set == "Seal" then + if G.localization.descriptions["Other"][_c.key.."_seal"] then set = "Other"; key = key.."_seal" end + else + if not G.localization.descriptions[set] or not G.localization.descriptions[set][_c.key] then set = "Other" end + end + + --localize{type = 'name', key = key, set = set, nodes = desc_nodes.loc_name, fixed_scale = 0.63, no_pop_in = true, no_shadow = true, y_offset = 0, no_spacing = true, no_bump = true, vars = (_c.create_fake_card and _c.loc_vars and (_c:loc_vars({}, _c:create_fake_card()) or {}).vars) or {colours = {}}} + --desc_nodes.loc_name = SMODS.info_queue_desc_from_rows(desc_nodes.loc_name, true) + --desc_nodes.loc_name.config.align = "cm" + end if specific_vars and specific_vars.pinned then info_queue[#info_queue+1] = {key = 'pinned_left', set = 'Other'} end if specific_vars and specific_vars.sticker then info_queue[#info_queue+1] = {key = string.lower(specific_vars.sticker)..'_sticker', set = 'Other'} end''' @@ -149,7 +165,6 @@ pattern = 'elseif desc_nodes ~= full_UI_table.main then' payload = 'elseif desc_nodes ~= full_UI_table.main and not desc_nodes.name then' - # check_for_unlock() [[patches]] [patches.regex] @@ -234,12 +249,15 @@ if obj and obj.set_badges and type(obj.set_badges) == 'function' then obj:set_badges(card, badges) end''' +# mod badges [[patches]] -[patches.regex] +[patches.pattern] target = 'functions/UI_definitions.lua' -pattern = "(?[\t ]*)if AUT.badges then\n([\t ]*.*\n){4}[\t ]*end" -line_prepend = '$indent' -position = 'after' +match_indent = true +position = 'before' +pattern = ''' +if AUT.info then +''' payload = ''' if AUT.card_type ~= 'Locked' and AUT.card_type ~= 'Undiscovered' then SMODS.create_mod_badges(card.config.center, badges) @@ -251,7 +269,8 @@ if AUT.card_type ~= 'Locked' and AUT.card_type ~= 'Undiscovered' then SMODS.create_mod_badges(SMODS.Tags[card.config.tag.key], badges) end badges.mod_set = nil -end''' +end +''' # set_discover_tallies() [[patches]] @@ -297,13 +316,13 @@ line_prepend = '$indent' position = 'before' payload = ''' local consumable_nodes = {} -if #SMODS.ConsumableType.ctype_buffer <= 3 then - for _, key in ipairs(SMODS.ConsumableType.ctype_buffer) do +if #SMODS.ConsumableType.visible_buffer <= 3 then + for _, key in ipairs(SMODS.ConsumableType.visible_buffer) do local id = 'your_collection_'..key:lower()..'s' consumable_nodes[#consumable_nodes+1] = UIBox_button({button = id, label = {localize('b_'..key:lower()..'_cards')}, count = G.DISCOVER_TALLIES[key:lower()..'s'], minw = 4, id = id, colour = G.C.SECONDARY_SET[key]}) end else - consumable_nodes[#consumable_nodes+1] = UIBox_button({ button = 'your_collection_consumables', label = {localize('b_stat_consumables'), localize{ type = 'variable', key = 'c_types', vars = {#SMODS.ConsumableType.ctype_buffer} } }, count = G.DISCOVER_TALLIES['consumeables'], minw = 4, minh = 4, id = 'your_collection_consumables', colour = G.C.FILTER }) + consumable_nodes[#consumable_nodes+1] = UIBox_button({ button = 'your_collection_consumables', label = {localize('b_stat_consumables'), localize{ type = 'variable', key = 'c_types', vars = {#SMODS.ConsumableType.visible_buffer} } }, count = G.DISCOVER_TALLIES['consumeables'], minw = 4, minh = 4, id = 'your_collection_consumables', colour = G.C.FILTER }) end ''' @@ -367,13 +386,22 @@ match_indent = true position = 'after' payload = ''' for _, v in ipairs(SMODS.Consumable.legendaries) do - if (_type == v.type.key or _type == v.soul_set) and not (G.GAME.used_jokers[v.key] and not next(find_joker("Showman")) and not v.can_repeat_soul) and (not v.in_pool or (type(v.in_pool) ~= "function") or v:in_pool()) then + if (_type == v.type.key or _type == v.soul_set) and not (G.GAME.used_jokers[v.key] and not SMODS.showman(v.key) and not v.can_repeat_soul) and SMODS.add_to_pool(v) then if pseudorandom('soul_'..v.key.._type..G.GAME.round_resets.ante) > (1 - v.soul_rate) then forced_key = v.key end end end''' +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = "local card = Card(area.T.x + area.T.w/2, area.T.y, G.CARD_W, G.CARD_H, front, center," +match_indent = true +position = 'at' +payload = ''' +local card = Card(area.T.x + area.T.w/2, area.T.y, G.CARD_W, G.CARD_H, SMODS.set_create_card_front or front, center,''' + [[patches]] [patches.pattern] target = 'functions/common_events.lua' @@ -401,6 +429,38 @@ position = 'at' payload = ''' discover = SMODS.bypass_create_card_discover or area==G.jokers or area==G.consumeables, ''' +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = '''not (G.GAME.used_jokers['c_soul'] and not next(find_joker("Showman"))) then''' +match_indent = true +position = 'at' +payload = ''' +not (G.GAME.used_jokers['c_soul'] and not SMODS.showman('c_soul')) then''' + +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = '''not (G.GAME.used_jokers['c_black_hole'] and not next(find_joker("Showman"))) then''' +match_indent = true +position = 'at' +payload = ''' +not (G.GAME.used_jokers['c_black_hole'] and not SMODS.showman('c_black_hole')) then''' + +# Fix vanilla copy_card back bug +# copy_card() +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = ''' +local new_card = new_card or Card(other.T.x, other.T.y, G.CARD_W*(card_scale or 1), G.CARD_H*(card_scale or 1), G.P_CARDS.empty, G.P_CENTERS.c_base, {playing_card = playing_card}) +''' +position = "at" +payload = ''' +local new_card = new_card or Card(other.T.x, other.T.y, G.CARD_W*(card_scale or 1), G.CARD_H*(card_scale or 1), G.P_CARDS.empty, G.P_CENTERS.c_base, {playing_card = playing_card, bypass_back = G.GAME.selected_back.pos}) +''' +match_indent = true + # Card:add_to_deck() [[patches]] [patches.regex] @@ -451,7 +511,7 @@ target = 'functions/button_callbacks.lua' match_indent = true position = 'before' pattern = ''' -if area and area.cards[1] then +if area and area.cards[1] then ''' payload = ''' if nc and not area then G.consumeables:emplace(card) end @@ -500,7 +560,7 @@ target = 'card.lua' match_indent = true position = 'at' pattern = 'if other_joker and other_joker ~= self then' -payload = 'if other_joker and other_joker ~= self and not context.no_blueprint then' +payload = 'if other_joker and other_joker ~= self and not other_joker.debuff and not context.no_blueprint then' # extract joker loc_vars [[patches]] @@ -530,9 +590,14 @@ payload = ''' local ability = copy_table(_c.config) ability.set = 'Joker' ability.name = _c.name + -- temporary stopgap. fake cards should be implemented better + ability.x_mult = _c['config'].Xmult or _c['config'].x_mult + if ability.name == 'To Do List' then + ability.to_do_poker_hand = "High Card" -- fallback + end local ret = {Card.generate_UIBox_ability_table({ ability = ability, config = { center = _c }, bypass_lock = true}, true)} specific_vars = ret[1] if ret[2] then desc_nodes[#desc_nodes+1] = ret[2] end main_end = ret[3] end - ''' \ No newline at end of file + ''' diff --git a/Steamodded/lovely/challenge.toml b/Steamodded/lovely/challenge.toml index 0db9203..40a521d 100644 --- a/Steamodded/lovely/challenge.toml +++ b/Steamodded/lovely/challenge.toml @@ -19,3 +19,64 @@ challenge_unlocked = challenge_unlocked or G.PROFILES[G.SETTINGS.profile].all_un """ match_indent = true + +# Add button colour +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = "UIBox_button({id = k, col = true, label = {challenge_unlocked and localize(v.id, 'challenge_names') or localize('k_locked'),}, button = challenge_unlocked and 'change_challenge_description' or 'nil', colour = challenge_unlocked and G.C.RED or G.C.GREY, minw = 4, scale = 0.4, minh = 0.6, focus_args = {snap_to = not snapped}})," +position = 'at' +match_indent = true +payload = ''' +UIBox_button({id = k, col = true, label = {challenge_unlocked and localize(v.id, 'challenge_names') or localize('k_locked'),}, button = challenge_unlocked and 'change_challenge_description' or 'nil', colour = challenge_unlocked and (v.button_colour or G.C.RED) or G.C.GREY, minw = 4, scale = 0.4, minh = 0.6, focus_args = {snap_to = not snapped}}), +''' + +[[patches]] +[patches.pattern] +target = "game.lua" +pattern = '''if _ch.restrictions.banned_cards then''' +position = "after" +payload = ''' if type(_ch.restrictions.banned_cards) == 'function' then + _ch.restrictions.banned_cards = _ch.restrictions.banned_cards() + end''' +match_indent = true +times = 1 + +[[patches]] +[patches.pattern] +target = "game.lua" +pattern = '''if _ch.restrictions.banned_tags then''' +position = "after" +payload = ''' + if type(_ch.restrictions.banned_tags) == 'function' then + _ch.restrictions.banned_tags = _ch.restrictions.banned_tags() + end''' +match_indent = true +times = 1 + +[[patches]] +[patches.pattern] +target = "game.lua" +pattern = '''if _ch.restrictions.banned_other then''' +position = "after" +payload = ''' + if type(_ch.restrictions.banned_other) == 'function' then + _ch.restrictions.banned_other = _ch.restrictions.banned_other() + end''' +match_indent = true +times = 1 + +# apply +[[patches]] +[patches.pattern] +target = "game.lua" +pattern = ''' +local _ch = args.challenge +''' +position = "after" +payload = ''' +if _ch.apply and type(_ch.apply) == "function" then + _ch:apply() +end +''' +match_indent = true \ No newline at end of file diff --git a/Steamodded/lovely/core.toml b/Steamodded/lovely/core.toml index 899b0cc..e61de98 100644 --- a/Steamodded/lovely/core.toml +++ b/Steamodded/lovely/core.toml @@ -22,3 +22,9 @@ sources = ["src/core.lua"] before = "main.lua" source = "version.lua" name = "SMODS.version" + +[[patches]] +[patches.module] +before = "main.lua" +source = "release.lua" +name = "SMODS.release" diff --git a/Steamodded/lovely/crash_handler.toml b/Steamodded/lovely/crash_handler.toml index cd590af..3f9dca2 100644 --- a/Steamodded/lovely/crash_handler.toml +++ b/Steamodded/lovely/crash_handler.toml @@ -18,3 +18,15 @@ position = "prepend" sources = [ "src/crash_handler.lua", ] + +[[patches]] +[patches.pattern] +target = 'game.lua' +match_indent = true +position = 'after' +pattern = ''' +local saveTable = args.savetext or nil +''' +payload = ''' +if G.SAVED_GAME then SMODS.save_game = G.SAVED_GAME.GAME.smods_version else SMODS.save_game = nil end +''' diff --git a/Steamodded/lovely/deck_skins.toml b/Steamodded/lovely/deck_skins.toml index c4e5c9f..f793b86 100644 --- a/Steamodded/lovely/deck_skins.toml +++ b/Steamodded/lovely/deck_skins.toml @@ -215,4 +215,53 @@ function create_UIBox_customize_deck() end ''' +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = ''' +if specific_vars.nominal_chips then + localize{type = 'other', key = 'card_chips', nodes = desc_nodes, vars = {specific_vars.nominal_chips}} +end +if specific_vars.bonus_chips then + localize{type = 'other', key = 'card_extra_chips', nodes = desc_nodes, vars = {specific_vars.bonus_chips}} +end +''' +position = "at" +payload = ''' +if card.area == G.cdds_cards and card.generate_ds_card_ui and type(card.generate_ds_card_ui) == 'function' and card.deckskin and card.palette then + card.generate_ds_card_ui(card, card.deckskin, card.palette, info_queue, desc_nodes, specific_vars, full_UI_table) +else + if specific_vars.nominal_chips then + localize{type = 'other', key = 'card_chips', nodes = desc_nodes, vars = {specific_vars.nominal_chips}} + end + if specific_vars.bonus_chips then + localize{type = 'other', key = 'card_extra_chips', nodes = desc_nodes, vars = {specific_vars.bonus_chips}} + end +end +''' +match_indent = true +#=======================# +# DeckSkin Crediting UI # +#=======================# +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = ''' +label = "Production", +chosen = true, +''' +position = "at" +payload = ''' +label = "Production", +chosen = not SMODS.init_collab_credits, +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = '''label = "Collabs",''' +position = "after" +payload = '''chosen = SMODS.init_collab_credits,''' +match_indent = true \ No newline at end of file diff --git a/Steamodded/lovely/edition.toml b/Steamodded/lovely/edition.toml index 4c502ed..efe8571 100644 --- a/Steamodded/lovely/edition.toml +++ b/Steamodded/lovely/edition.toml @@ -55,17 +55,21 @@ pattern = ''' position = 'at' payload = ''' v = (v == 'holographic' and 'holo' or v) -if v:sub(1,9) == 'negative_' then - info_queue[#info_queue+1] = {key = 'e_'..v, set = 'Edition', config = {extra = G.P_CENTERS['e_negative'].config.card_limit}} +local ed_key = v +if v:sub(v:len()-14) == '_SMODS_INTERNAL' then + if v:sub(1, 9) == 'negative_' then ed_key = 'negative' else ed_key = v:sub(1, v:find('_', v:find('_')+1)-1) end + v = v:sub(1, v:len()-15) end -if G.P_CENTERS[v] and G.P_CENTERS[v].set == 'Edition' then - info_queue[#info_queue + 1] = G.P_CENTERS[v] + +if G.P_CENTERS[ed_key] and G.P_CENTERS[ed_key].set == 'Edition' then + info_queue[#info_queue + 1] = G.P_CENTERS[ed_key] end -if G.P_CENTERS['e_'..v] and G.P_CENTERS['e_'..v].set == 'Edition' then +if G.P_CENTERS['e_'..ed_key] and G.P_CENTERS['e_'..ed_key].set == 'Edition' then local t = {key = 'e_'..v, set = 'Edition', config = {}} + if localize(SMODS.merge_defaults(t, {type = 'name_text'})) == 'ERROR' then t.key = 'e_'..ed_key end info_queue[#info_queue + 1] = t - if G.P_CENTERS['e_'..v].loc_vars and type(G.P_CENTERS['e_'..v].loc_vars) == 'function' then - local res = G.P_CENTERS['e_'..v]:loc_vars(info_queue, card) or {} + if G.P_CENTERS['e_'..ed_key].loc_vars and type(G.P_CENTERS['e_'..ed_key].loc_vars) == 'function' then + local res = G.P_CENTERS['e_'..ed_key]:loc_vars(info_queue, card) or {} t.vars = res.vars t.key = res.key or t.key t.set = res.set or t.set @@ -121,58 +125,6 @@ for k, v in pairs(G.P_CENTER_POOLS.Edition) do end''' line_prepend = "$indent" -## Fix card_limit logic -# Card:add_to_deck() -[[patches]] -[patches.regex] -target = "card.lua" -pattern = '''(?[\t ]*)if self\.edition[A-z\.\:\n\t _(',)~=+\-0-9]*limit \+ 1''' -position = "at" -payload = ''' -if true then - if from_debuff then - self.ability.joker_added_to_deck_but_debuffed = nil - else - if self.edition and self.edition.card_limit then - if self.ability.consumeable then - G.consumeables.config.card_limit = G.consumeables.config.card_limit + self.edition.card_limit - else - G.jokers.config.card_limit = G.jokers.config.card_limit + self.edition.card_limit - end''' -line_prepend = "$indent" -# Card:remove_from_deck() -[[patches]] -[patches.regex] -target = "card.lua" -pattern = '''(?[\t ]*)if self\.edition[A-z\.\:\n\t _(',)~=+\-0-9]*limit \- 1''' -position = "at" -payload = ''' -if G.jokers then - if from_debuff then - self.ability.joker_added_to_deck_but_debuffed = true - else - if self.edition and self.edition.card_limit then - if self.ability.consumeable then - G.consumeables.config.card_limit = G.consumeables.config.card_limit - self.edition.card_limit - elseif self.ability.set == 'Joker' then - G.jokers.config.card_limit = G.jokers.config.card_limit - self.edition.card_limit - end''' -line_prepend = "$indent" -# Card:remove() -[[patches]] -[patches.regex] -target = "card.lua" -pattern = '''(?[\t ]*)if self\.ability\.queue_neg[A-z\.\:\n\t _(',)~=+\-0-9]*limit \- 1''' -position = "at" -payload = ''' -if self.ability.joker_added_to_deck_but_debuffed then - if self.edition and self.edition.card_limit then - if self.ability.consumeable then - G.consumeables.config.card_limit = G.consumeables.config.card_limit - self.edition.card_limit - elseif self.ability.set == 'Joker' then - G.jokers.config.card_limit = G.jokers.config.card_limit - self.edition.card_limit - end''' -line_prepend = "$indent" # Card:save() [[patches]] [patches.pattern] @@ -182,61 +134,43 @@ position = "after" payload = "joker_added_to_deck_but_debuffed = self.joker_added_to_deck_but_debuffed," match_indent = true - -## Negative playing card logic -# CardArea:emplace() +## Buying card_limit cards fix +# G.FUNCS.check_for_buy_space [[patches]] [patches.pattern] -target = "cardarea.lua" -pattern = "function CardArea:emplace(*" -position = "after" -payload = ''' - if not card.debuff and card.edition and card.edition.card_limit and (self == G.hand) then - self.config.real_card_limit = (self.config.real_card_limit or self.config.card_limit) + card.edition.card_limit - self.config.card_limit = math.max(0, self.config.real_card_limit) - end''' -match_indent = true -# CardArea:remove_card() -[[patches]] -[patches.pattern] -target = "cardarea.lua" -pattern = "card:remove_from_area()" -position = "before" -payload = ''' -if not card.debuff and card.edition and card.edition.card_limit and (self == G.hand) then - self.config.real_card_limit = (self.config.real_card_limit or self.config.card_limit) - card.edition.card_limit - self.config.card_limit = math.max(0, self.config.real_card_limit) -end''' -match_indent = true - -# G.FUNCS.draw_from_deck_to_hand() -[[patches]] -[patches.pattern] -target = "functions/state_events.lua" -pattern = "local hand_space = e or*" +target = "functions/button_callbacks.lua" +pattern = " not (card.ability.consumeable and #G.consumeables.cards < G.consumeables.config.card_limit + ((card.edition and card.edition.negative) and 1 or 0)) then" position = "at" -payload = """local hand_space = e -if not hand_space then - local limit = G.hand.config.card_limit - #G.hand.cards - local n = 0 - while n < #G.deck.cards do - local card = G.deck.cards[#G.deck.cards-n] - limit = limit - 1 + (not card.debuff and card.edition and card.edition.card_limit or 0) - if limit < 0 then break end - n = n + 1 - end - hand_space = n -end""" match_indent = true +payload = ''' + not (card.ability.consumeable and #G.consumeables.cards < G.consumeables.config.card_limit + card.ability.card_limit - card.ability.extra_slots_used) then +''' +times = 1 + +# G.FUNCS.check_for_buy_space +[[patches]] +[patches.pattern] +target = "functions/button_callbacks.lua" +pattern = "not (card.ability.set == 'Joker' and #G.jokers.cards < G.jokers.config.card_limit + ((card.edition and card.edition.negative) and 1 or 0)) and" +position = "at" +match_indent = true +payload = ''' + not (card.ability.set == 'Joker' and #G.jokers.cards < G.jokers.config.card_limit + card.ability.card_limit - card.ability.extra_slots_used) and +''' +times = 1 [[patches]] [patches.pattern] target = "card.lua" -pattern = "badges[#badges + 1] = 'negative_consumable'" -position = "after" +pattern = ''' +if self.edition.type == 'negative' and self.ability.consumeable then + badges[#badges + 1] = 'negative_consumable' +''' +position = "at" payload = """ -elseif self.edition.type == 'negative' and (self.ability.set == 'Enhanced' or self.ability.set == 'Default') then - badges[#badges + 1] = 'negative_playing_card'""" +if self.edition.card_limit then + badges[#badges + 1] = SMODS.Edition.get_card_limit_key(self) +""" match_indent = true [[patches]] @@ -265,7 +199,11 @@ match_indent = true target = "functions/UI_definitions.lua" pattern = "if v == 'negative_consumable' then v = 'negative' end" position = "at" -payload = '''if v == 'negative_consumable' or v == 'negative_playing_card' then v = 'negative' end''' +payload = ''' +if v:sub(v:len()-14) == '_SMODS_INTERNAL' then + if v:sub(1, 9) == 'negative_' then v = 'negative' else v = v:sub(1, v:find('_', v:find('_')+1)-1) end +end +''' match_indent = true # @@ -276,6 +214,6 @@ pattern = '''(?[\t ]*)(?local edition = poll_edition\('edi'\.\.\(ke position = 'at' line_prepend = '$indent' payload = ''' -if not SMODS.bypass_create_card_edition then +if not SMODS.bypass_create_card_edition and not card.edition then $edi end''' diff --git a/Steamodded/lovely/enhancement.toml b/Steamodded/lovely/enhancement.toml index b8b0856..12e6f7e 100644 --- a/Steamodded/lovely/enhancement.toml +++ b/Steamodded/lovely/enhancement.toml @@ -23,8 +23,7 @@ pattern = ''' [\t ]* return self\.ability\.bonus \+ \(self\.ability\.perma_bonus or 0\) [\t ]*end''' position = "at" -payload = ''' -if self.ability.effect == 'Stone Card' or self.config.center.replace_base_card then +payload = '''if self.ability.effect == 'Stone Card' or self.config.center.replace_base_card then return self.ability.bonus + (self.ability.perma_bonus or 0) end''' line_prepend = '$indent' @@ -160,7 +159,7 @@ if delay_sprites then })) ''' payload = ''' -if delay_sprites == 'quantum' then +if delay_sprites == 'quantum' or delay_sprites == 'manual' then elseif delay_sprites then self.ability.delayed = true G.E_MANAGER:add_event(Event({ @@ -224,7 +223,7 @@ match_indent = true # Prevent blue seal effect on extra enhancements at end of round [[patches]] [patches.pattern] -target = "card" +target = "card.lua" pattern = "if self.seal == 'Blue' and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit then" position = "before" payload = ''' @@ -292,15 +291,48 @@ position = "after" payload = "SMODS.enh_cache:clear()" match_indent = true -# Invalidate enhancement cache when card changes +# Invalidate enhancement cache when card changes / replace_base_card fix pt1 [[patches]] [patches.pattern] target = "card.lua" pattern = "function Card:set_ability(center, initial, delay_sprites)" position = "after" -payload = "SMODS.enh_cache:write(self, nil)" +payload = ''' + SMODS.enh_cache:write(self, nil) + + if self.ability and not initial then + self.ability.card_limit = self.ability.card_limit - (self.config.center.card_limit or 0) + self.ability.extra_slots_used = self.ability.extra_slots_used - (self.config.center.extra_slots_used or 0) + if self.area then self.area:handle_card_limit(-1 * (self.config.center.card_limit or 0), -1 * (self.config.center.extra_slots_used or 0)) end + end + + if self.ability and not initial then + self.front_hidden = self:should_hide_front() + end +''' match_indent = true +# replace_base_card Fix Part 2 +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "self:set_sprites(center)" +position = "after" +payload = '''if self.ability and not initial then + self.front_hidden = self:should_hide_front() +end''' +match_indent = true + +# replace_base_card Fix Part 3 +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = "if not G.OVERLAY_MENU then " +position = "before" +payload = '''if self.ability and not initial then + self.front_hidden = self:should_hide_front() +end''' +match_indent = true [[patches]] [patches.pattern] target = "card.lua" @@ -314,7 +346,14 @@ match_indent = true target = "card.lua" pattern = "function Card:set_seal(_seal, silent, immediate)" position = "after" -payload = "SMODS.enh_cache:write(self, nil)" +payload = ''' + SMODS.enh_cache:write(self, nil) + if self.seal then + self.ability.card_limit = self.ability.card_limit - (self.ability.seal.card_limit or 0) + self.ability.extra_slots_used = self.ability.extra_slots_used - (self.ability.seal.extra_slots_used or 0) + if self.area then self.area:handle_card_limit(-1 * (self.ability.seal.card_limit or 0), -1 * (self.ability.seal.extra_slots_used or 0)) end + end +''' match_indent = true # safeguards an infloop with debuff context diff --git a/Steamodded/lovely/fixes.toml b/Steamodded/lovely/fixes.toml index 78e86a7..e4e1a59 100644 --- a/Steamodded/lovely/fixes.toml +++ b/Steamodded/lovely/fixes.toml @@ -70,16 +70,16 @@ position = 'at' payload = 'if not self.alignment.type_list then return end' line_prepend = '$indent' -## Prevent softlock if booster pack is empty -## Crashes the game when you skip too fast on this PR, along with being the culprit for allowing you to skip boosters early -# G.FUNCS.can_skip_booster() -# [[patches]] -# [patches.pattern] -# target = 'functions/button_callbacks.lua' -# pattern = 'if G.pack_cards and (G.pack_cards.cards[1]) and' -# position = 'at' -# payload = 'if G.pack_cards and' -# match_indent = true +## Don't save run while booster pack opened (always softlocks) +# save_run() +[[patches]] +[patches.pattern] +target = 'functions/misc_functions.lua' +pattern = "function save_run()" +position = "after" +payload = """ if G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.PLANET_PACK or G.STATE == G.STATES.SPECTRAL_PACK + or G.STATE == G.STATES.BUFFOON_PACK or G.STATE == G.STATES.STANDARD_PACK or G.STATE == G.STATES.SMODS_BOOSTER_OPENED then return end""" +match_indent = true ## Set `G.your_collection.config.collection` to true in all cases # create_UIBox_your_collection_seals() @@ -90,7 +90,7 @@ pattern = '''\{card_limit = 4, type = 'title', highlight_limit = 0\}''' position = 'at' payload = '''{card_limit = 4, type = 'title', highlight_limit = 0, collection = true}''' -## Save and load Card.unique_val +## Save and load Card.unique_val, edition options # Card:save() [[patches]] [patches.pattern] @@ -130,7 +130,13 @@ pattern = 'function generate_card_ui(_c, full_UI_table, specific_vars, card_type position = 'at' match_indent = true payload = '''function generate_card_ui(_c, full_UI_table, specific_vars, card_type, badges, hide_desc, main_start, main_end, card) - if _c.specific_vars then specific_vars = _c.specific_vars end''' + if _c.specific_vars then specific_vars = _c.specific_vars end + local is_info_queue = false + if specific_vars and specific_vars.is_info_queue then + is_info_queue = true + specific_vars = nil + end +''' [[patches]] [patches.pattern] @@ -165,12 +171,13 @@ position = 'at' match_indent = true payload = ''' if delay_sprites == 'quantum' then self.from_quantum = true end +local was_added_to_deck = false if self.added_to_deck and old_center and not self.debuff then self:remove_from_deck() - self.added_to_deck = true + was_added_to_deck = true end if type(center) == 'string' then - assert(G.P_CENTERS[center]) + assert(G.P_CENTERS[center], ("Could not find center \"%s\""):format(center)) center = G.P_CENTERS[center] end self.config.center = center @@ -183,8 +190,7 @@ pattern = "if G.consumeables and self.area == G.consumeables then" position = 'before' match_indent = true payload = ''' -if self.added_to_deck and old_center and not self.debuff then - self.added_to_deck = false +if was_added_to_deck and not self.debuff then self:add_to_deck() end self.from_quantum = nil''' @@ -211,7 +217,14 @@ self.ability.extra_value = self.ability.extra_value or 0 for k, v in pairs(new_ability) do self.ability[k] = v end --- reset keys do not persist an ability change + +-- handles card_limit/extra_slots_used changes +self.ability.card_limit = self.ability.card_limit + (center.config.card_limit or 0) +self.ability.extra_slots_used = self.ability.extra_slots_used + (center.config.extra_slots_used or 0) +if self.area then self.area:handle_card_limit(center.config.card_limit, center.config.extra_slots_used) end + + +-- reset keys do not persist on ability change local reset_keys = {'name', 'effect', 'set', 'extra', 'played_this_ante', 'perma_debuff'} for _, mod in ipairs(SMODS.mod_list) do if mod.set_ability_reset_keys then @@ -386,7 +399,7 @@ target = "functions/misc_functions.lua" pattern = '''if win_ante and (win_ante >= 8) then''' match_indent = true position = "at" -payload = '''if win_ante and (win_ante >= 8) or (v.in_pool and type(v.in_pool) == 'function' and not v:in_pool()) then''' +payload = '''if win_ante and (win_ante >= 8) or not SMODS.add_to_pool(v) then''' # # Fix G.GAME.blind:set_blind(nil, true, nil) @@ -629,10 +642,20 @@ match_indent = true [[patches]] [patches.pattern] target = 'functions/common_events.lua' -position = 'after' +position = 'at' match_indent = true pattern = 'new_card:set_edition(other.edition or {}, nil, true)' -payload = '''for k,v in pairs(other.edition or {}) do +payload = ''' +if other.edition then + new_card.ability.card_limit = new_card.ability.card_limit - (other.edition.card_limit or 0) + new_card.ability.extra_slots_used = new_card.ability.extra_slots_used - (other.edition.extra_slots_used or 0) +end +if other.seal then + new_card.ability.card_limit = new_card.ability.card_limit - (other.ability.seal.card_limit or 0) + new_card.ability.extra_slots_used = new_card.ability.extra_slots_used - (other.ability.seal.extra_slots_used or 0) +end +new_card:set_edition(other.edition or {}, nil, true) +for k,v in pairs(other.edition or {}) do if type(v) == 'table' then new_card.edition[k] = copy_table(v) else @@ -646,7 +669,7 @@ end''' target = "card.lua" pattern = "if next(find_joker('Smeared Joker')) and (self.base.suit == 'Hearts' or self.base.suit == 'Diamonds') == (suit == 'Hearts' or suit == 'Diamonds') then" position = "at" -payload = "if next(find_joker('Smeared Joker')) and SMODS.smeared_check(self, suit) then" +payload = "if SMODS.smeared_check(self, suit) then" overwrite = true match_indent = true @@ -694,3 +717,85 @@ payload = """if SMODS.seeing_double_check(context.scoring_hand, 'Clubs') then end""" overwrite = true match_indent = true + +# Card:get_end_of_round_effect +# prevents Blue Seal crash from a hand with no matching planet card (spawns random planet card) +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = """local card = create_card(card_type,G.consumeables, nil, nil, nil, nil, _planet, 'blusl')""" +position = 'before' +payload = """if _planet == 0 then _planet = nil end""" +match_indent = true + +## Fix remove_from_deck being called and unlocking stuff when exiting a run and +## clearing screen +# Game:delete_run() +[[patches]] +[patches.pattern] +target = "game.lua" +pattern = 'function Game:delete_run()' +position = 'after' +payload = ''' G.in_delete_run = true + booster_obj = nil''' +match_indent = true +[[patches]] +[patches.pattern] +target = "game.lua" +pattern = 'G.STATE = -1' +position = 'after' +payload = 'G.in_delete_run = false' +match_indent = true +# Card:remove() +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = 'if self.area then self.area:remove_card(self) end' +position = 'after' +payload = 'if G.in_delete_run then goto skip_game_actions_during_remove end' +match_indent = true +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = 'if G.playing_cards then' +position = 'before' +payload = '::skip_game_actions_during_remove::' +match_indent = true +# CardArea:remove_card() +[[patches]] +[patches.pattern] +target = "cardarea.lua" +pattern = ''' +self:set_ranks() +if self == G.deck then check_for_unlock({type = 'modify_deck', deck = self}) end''' +position = 'at' +payload = ''' +self:set_ranks() +if not G.in_delete_run and self == G.deck then check_for_unlock({type = 'modify_deck', deck = self}) end''' +match_indent = true + +# Assign `getting_sliced` to destruction events +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'after' +pattern = ''' +if v ~= chosen_joker then +''' +payload = ''' +v.getting_sliced = true +''' + +# Allow pseudoshuffle to take a string as a seed +[[patches]] +[patches.pattern] +target = 'functions/misc_functions.lua' +match_indent = true +position = 'after' +pattern = ''' +function pseudoshuffle(list, seed) +''' +payload = ''' + if seed and type(seed) == "string" then seed = pseudoseed(seed) end +''' \ No newline at end of file diff --git a/Steamodded/lovely/gradient.toml b/Steamodded/lovely/gradient.toml index 782aaf5..458165d 100644 --- a/Steamodded/lovely/gradient.toml +++ b/Steamodded/lovely/gradient.toml @@ -11,6 +11,46 @@ pattern = "self.C.EDITION[2] = 0.7+0.2*(1+math.sin(self.TIMERS.REAL*1.5 + 6))" position = "after" payload = ''' for _,v in pairs(SMODS.Gradients) do - v:update(dt) + v:update(dt) end''' -match_indent = true \ No newline at end of file +match_indent = true + +# Fix for effect messages +# attention_text +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = "args.colour = copy_table(args.colour or G.C.WHITE)" +position = "at" +payload = ''' +args.colour = SMODS.shallow_copy(args.colour or G.C.WHITE) +''' +match_indent = true + +# attention_text +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = ''' +args.cover_colour = copy_table(args.cover_colour or G.C.RED) +args.cover_colour_l = copy_table(lighten(args.cover_colour, 0.2)) +args.cover_colour_d = copy_table(darken(args.cover_colour, 0.2)) +''' +position = "at" +payload = ''' +args.cover_colour = SMODS.shallow_copy(args.cover_colour or G.C.RED) +args.cover_colour_l = SMODS.shallow_copy(lighten(args.cover_colour, 0.2)) +args.cover_colour_d = SMODS.shallow_copy(darken(args.cover_colour, 0.2)) +''' +match_indent = true + +# attention_text +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = "args.backdrop_colour = copy_table(args.backdrop_colour)" +position = "at" +payload = ''' +args.backdrop_colour = SMODS.shallow_copy(args.backdrop_colour) +''' +match_indent = true diff --git a/Steamodded/lovely/hand_limit.toml b/Steamodded/lovely/hand_limit.toml new file mode 100644 index 0000000..d6d8fb5 --- /dev/null +++ b/Steamodded/lovely/hand_limit.toml @@ -0,0 +1,93 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +# Add starting params +[[patches]] +[patches.pattern] +target = 'functions/misc_functions.lua' +match_indent = true +position = 'before' +pattern = ''' +consumable_slots = 2, +''' +payload = ''' +play_limit = 5, +discard_limit = 5, +no_limit = '', +''' +# Reset visual indicators +[[patches]] +[patches.pattern] +target = 'game.lua' +match_indent = true +position = 'after' +pattern = ''' +self.GAME = saveTable and saveTable.GAME or self:init_game_object() +''' +payload = ''' +SMODS.update_hand_limit_text(true, true) +''' + + +# Change hand limit +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +match_indent = true +position = 'at' +pattern = ''' +if #G.hand.highlighted <= 0 or G.GAME.blind.block_play or #G.hand.highlighted > 5 then +''' +payload = ''' +if #G.hand.highlighted <= 0 or G.GAME.blind.block_play or #G.hand.highlighted > math.max(G.GAME.starting_params.play_limit, 1) then +''' + +# Change discard limit +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +match_indent = true +position = 'at' +pattern = ''' +if G.GAME.current_round.discards_left <= 0 or #G.hand.highlighted <= 0 then +''' +payload = ''' +if G.GAME.current_round.discards_left <= 0 or #G.hand.highlighted <= 0 or #G.hand.highlighted > math.max(G.GAME.starting_params.discard_limit, 0) then +''' + +# Add play limit indicator to UI +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +match_indent = true +position = 'after' +pattern = ''' +{n=G.UIT.R, config={align = "bcm", padding = 0}, nodes={ + {n=G.UIT.T, config={text = localize('b_play_hand'), scale = text_scale, colour = G.C.UI.TEXT_LIGHT, focus_args = {button = 'x', orientation = 'bm'}, func = 'set_button_pip'}} +}}, +''' +payload = ''' +{n=G.UIT.R, config={align = "bcm", padding = 0}, nodes = { + {n=G.UIT.T, config={ref_table = SMODS.hand_limit_strings, ref_value = 'play', scale = text_scale * 0.65, colour = G.C.UI.TEXT_LIGHT}} +}}, +''' +# Add discard limit indicator to UI +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +match_indent = true +position = 'at' +pattern = ''' +{n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ + {n=G.UIT.T, config={text = localize('b_discard'), scale = text_scale, colour = G.C.UI.TEXT_LIGHT, focus_args = {button = 'y', orientation = 'bm'}, func = 'set_button_pip'}} +}}''' +payload = ''' +{n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ + {n=G.UIT.T, config={text = localize('b_discard'), scale = text_scale, colour = G.C.UI.TEXT_LIGHT, focus_args = {button = 'y', orientation = 'bm'}, func = 'set_button_pip'}} +}}, +{n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ + {n=G.UIT.T, config={ref_table = SMODS.hand_limit_strings, ref_value = 'discard', scale = text_scale * 0.65, colour = G.C.UI.TEXT_LIGHT}} +}}, +''' diff --git a/Steamodded/lovely/jimboquip.toml b/Steamodded/lovely/jimboquip.toml new file mode 100644 index 0000000..3d150b6 --- /dev/null +++ b/Steamodded/lovely/jimboquip.toml @@ -0,0 +1,202 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +# Select custom win quips +[[patches]] +[patches.pattern] +target = "functions/state_events.lua" +pattern = '''Jimbo = Card_Character({x = 0, y = 5}) +local spot = G.OVERLAY_MENU:get_UIE_by_ID('jimbo_spot') +spot.config.object:remove() +spot.config.object = Jimbo +Jimbo.ui_object_updated = true +Jimbo:add_speech_bubble('wq_'..math.random(1,7), nil, {quip = true}) +Jimbo:say_stuff(5) +''' +position = "at" +payload = ''' +local quip, extra = SMODS.quip("win") +extra.x = 0 +extra.y = 5 +Jimbo = Card_Character(extra) +local spot = G.OVERLAY_MENU:get_UIE_by_ID('jimbo_spot') +spot.config.object:remove() +spot.config.object = Jimbo +Jimbo.ui_object_updated = true +Jimbo:add_speech_bubble(quip, nil, {quip = true}, extra) +Jimbo:say_stuff((extra and extra.times) or 5, false, quip) +''' +match_indent = true + +# Select custom loss quips +[[patches]] +[patches.pattern] +target = "game.lua" +pattern = '''Jimbo = Card_Character({x = 0, y = 5}) +local spot = G.OVERLAY_MENU:get_UIE_by_ID('jimbo_spot') +spot.config.object:remove() +spot.config.object = Jimbo +Jimbo.ui_object_updated = true +Jimbo:add_speech_bubble('lq_'..math.random(1,10), nil, {quip = true}) +Jimbo:say_stuff(5) +''' +position = "at" +payload = ''' +local quip, extra = SMODS.quip("loss") +extra.x = 0 +extra.y = 5 +Jimbo = Card_Character(extra) +local spot = G.OVERLAY_MENU:get_UIE_by_ID('jimbo_spot') +spot.config.object:remove() +spot.config.object = Jimbo +Jimbo.ui_object_updated = true +Jimbo:add_speech_bubble(quip, nil, {quip = true}, extra) +Jimbo:say_stuff((extra and extra.times) or 5, false, quip) +''' +match_indent = true + +# Allow custom materialize colours +[[patches]] +[patches.pattern] +target = "card_character.lua" +pattern = '''self.children.card:start_materialize({G.C.BLUE, G.C.WHITE, G.C.RED})''' +position = "at" +payload = '''self.children.card:start_materialize({args.materialize_colours and args.materialize_colours[1] or G.C.BLUE, args.materialize_colours and args.materialize_colours[2] or G.C.WHITE, args.materialize_colours and args.materialize_colours[3] or G.C.RED})''' +match_indent = true + +# Allow custom particle_colours +[[patches]] +[patches.pattern] +target = "card_character.lua" +pattern = '''colours = {G.C.RED, G.C.BLUE, G.C.ORANGE},''' +position = "at" +payload = '''colours = {args.particle_colours and args.particle_colours[1] or G.C.RED, args.particle_colours and args.particle_colours[2] or G.C.BLUE, args.particle_colours and args.particle_colours[3] or G.C.ORANGE},''' +match_indent = true + +# Allow custom centers to be used for quips +[[patches]] +[patches.pattern] +target = 'card_character.lua' +match_indent = true +position = 'at' +pattern = ''' +self.children.card = Card(self.T.x, self.T.y, G.CARD_W, G.CARD_H, G.P_CARDS.empty, args.center or G.P_CENTERS.j_joker, {bypass_discovery_center = true}) +''' +payload = ''' +self.children.card = Card(self.T.x, self.T.y, G.CARD_W, G.CARD_H, G.P_CARDS.empty, args.center and G.P_CENTERS[args.center] or G.P_CENTERS.j_joker, {bypass_discovery_center = true}) +''' + +# Pass args into add_speech_bubble +[[patches]] +[patches.pattern] +target = 'card_character.lua' +match_indent = true +position = 'at' +pattern = ''' +function Card_Character:add_speech_bubble(text_key, align, loc_vars) +''' +payload = ''' +function Card_Character:add_speech_bubble(text_key, align, loc_vars, quip_args) + if quip_args and quip_args.text_key then text_key = quip_args.text_key end +''' + + + + +# Pass extra table into say_stuff +[[patches]] +[patches.pattern] +target = 'card_character.lua' +pattern = ''' +function Card_Character:say_stuff(n, not_first) +''' +position = 'at' +payload = ''' +function Card_Character:say_stuff(n, not_first, quip_key) + local quip = SMODS.JimboQuips[quip_key] or {} +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = 'card_character.lua' +pattern = ''' +self:say_stuff(n, true) +''' +position = 'at' +payload = ''' +self:say_stuff(n, true, quip_key) +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = 'card_character.lua' +pattern = ''' +self:say_stuff(n-1, true) +''' +position = 'at' +payload = ''' +self:say_stuff(n-1, true, quip_key) +''' +match_indent = true + + +# Allow custom sounds to be used for the voice +[[patches]] +[patches.pattern] +target = 'card_character.lua' +pattern = ''' +play_sound('voice'..math.random(1, 11), G.SPEEDFACTOR*(math.random()*0.2+1), 0.5) +''' +position = 'at' +payload = ''' +if quip.play_sounds and type(quip.play_sounds) == 'function' then + quip:play_sounds(n) +elseif quip.extra and quip.extra.sound then + local custom_pitch = quip.extra.pitch + if type(quip.extra.sound) == 'table' then + for k, v in pairs(quip.extra.sound) do + play_sound(v, custom_pitch or G.SPEEDFACTOR*(math.random()*0.2+1), 0.5) + end + elseif type(quip.extra.sound) == 'string' then + play_sound(quip.extra.sound, custom_pitch or G.SPEEDFACTOR*(math.random()*0.2+1), 0.5) + else + play_sound('voice'..math.random(1, 11), custom_pitch or G.SPEEDFACTOR*(math.random()*0.2+1), 0.5) + end +else + play_sound('voice'..math.random(1, 11), quip.extra and quip.extra.pitch or G.SPEEDFACTOR*(math.random()*0.2+1), 0.5) +end +''' +match_indent = true + + +# Allow custom delay between talking sounds +[[patches]] +[patches.pattern] +target = 'card_character.lua' +pattern = ''' +delay = 0.13, +''' +position = 'at' +payload = ''' +delay = quip.extra and quip.extra.delay or 0.13, +''' +match_indent = true + + +# Allow custom juice parameters +[[patches]] +[patches.pattern] +target = 'card_character.lua' +pattern = ''' +self.children.card:juice_up() +''' +position = 'at' +payload = ''' +local juice_params = quip.extra and quip.extra.juice or {nil, nil} +self.children.card:juice_up(juice_params[1], juice_params[2]) +''' +match_indent = true \ No newline at end of file diff --git a/Steamodded/lovely/joker_retriggers.toml b/Steamodded/lovely/joker_retriggers.toml index 72dfbdc..79a8324 100644 --- a/Steamodded/lovely/joker_retriggers.toml +++ b/Steamodded/lovely/joker_retriggers.toml @@ -44,7 +44,7 @@ pattern = '''[ \t]*if card\.ability\.invis_rounds then card\.ability\.invis_roun (?[ \t]*)G\.jokers:emplace\(card\)''' position = "after" line_prepend = '$indent' -payload = "return nil, true" +payload = "\nreturn nil, true" # Campfire [[patches]] @@ -81,11 +81,11 @@ if self.ability.name == 'Flash Card' and not context.blueprint then return nil, [[patches]] [patches.regex] target = "card.lua" -pattern = '''[ \t]*card_eval_status_text\(context\.blueprint_card or self, 'extra', nil, nil, nil, \{message = localize\('k_duplicated_ex'\)\}\) +pattern = '''[ \t]*card_eval_status_text\(context[._]blueprint_card or self, 'extra', nil, nil, nil, \{message = localize\('k_duplicated_ex'\)\}\) (?[ \t]*)end''' position = "at" line_prepend = '$indent' -payload = ''' card_eval_status_text(context.blueprint_card or self, 'extra', nil, nil, nil, {message = localize('k_duplicated_ex')}) +payload = ''' card_eval_status_text(context_blueprint_card or self, 'extra', nil, nil, nil, {message = localize('k_duplicated_ex')}) return nil, true end''' @@ -99,7 +99,7 @@ pattern = ''' (?[ \t]*)elseif context\.skipping_booster''' position = "before" line_prepend = '$indent' -payload = "return nil, true" +payload = " return nil, true\n" # Red Card [[patches]] @@ -111,7 +111,7 @@ pattern = ''' (?[ \t]*)elseif context\.playing_card_added''' position = "before" line_prepend = '$indent' -payload = "return nil, true" +payload = " return nil, true\n" # Hologram [[patches]] @@ -122,7 +122,7 @@ pattern = ''' (?[ \t]*)elseif context\.first_hand_drawn''' position = "before" line_prepend = '$indent' -payload = "return nil, true" +payload = " return nil, true\n" # Certificate [[patches]] @@ -133,7 +133,7 @@ pattern = ''' (?[ \t]*)if self\.ability\.name == 'DNA' and not context\.blueprint''' position = "before" line_prepend = '$indent' -payload = "return nil, true" +payload = " return nil, true\n" # Chicot [[patches]] @@ -144,7 +144,7 @@ pattern = ''' (?[ \t]*)if self\.ability\.name == 'Madness' ''' position = "before" line_prepend = '$indent' -payload = "return nil, true" +payload = " return nil, true\n" # Madness [[patches]] @@ -155,7 +155,7 @@ pattern = ''' (?[ \t]*)if self\.ability\.name == 'Burglar' ''' position = "before" line_prepend = '$indent' -payload = "return nil, true" +payload = " return nil, true\n" # Burglar [[patches]] @@ -166,7 +166,7 @@ pattern = ''' (?[ \t]*)if self\.ability\.name == 'Riff-raff' ''' position = "before" line_prepend = '$indent' -payload = "return nil, true" +payload = " return nil, true\n" # Riff-raff [[patches]] @@ -177,7 +177,7 @@ pattern = ''' (?[ \t]*)if self\.ability\.name == 'Cartomancer' ''' position = "before" line_prepend = '$indent' -payload = "return nil, true" +payload = " return nil, true\n" # Cartomancer [[patches]] @@ -188,7 +188,7 @@ pattern = ''' (?[ \t]*)if self\.ability\.name == 'Ceremonial Dagger' and not context.blueprint''' position = "before" line_prepend = '$indent' -payload = "return nil, true" +payload = " return nil, true\n" # Ceremonial Dagger [[patches]] @@ -200,7 +200,7 @@ pattern = ''' (?[ \t]*)if self\.ability\.name == 'Marble Joker' ''' position = "before" line_prepend = '$indent' -payload = "return nil, true" +payload = " return nil, true\n" # Marble Joker [[patches]] @@ -212,7 +212,7 @@ pattern = ''' (?[ \t]*)elseif context.destroying_card''' position = "before" line_prepend = '$indent' -payload = "return nil, true" +payload = " return nil, true\n" # Caino [[patches]] @@ -222,7 +222,7 @@ pattern = '''[ \t]*func = function\(\) card_eval_status_text\(self, 'extra', nil (?[ \t]*)end\}\)\)''' position = "after" line_prepend = '$indent' -payload = "return nil, true" +payload = "\nreturn nil, true" # Glass Joker [[patches]] @@ -234,7 +234,7 @@ pattern = '''glass_cards\}\}\}\) (?[ \t]*)\}\)\)''' position = "after" line_prepend = '$indent' -payload = "return nil, true" +payload = "\nreturn nil, true" [[patches]] [patches.regex] @@ -246,7 +246,7 @@ pattern = ''' (?[ \t]*)if self\.ability\.name == 'Fortune Teller' and not context\.blueprint''' position = "before" line_prepend = '$indent' -payload = "return nil, true" +payload = " return nil, true\n" # Fortune Teller [[patches]] @@ -257,7 +257,7 @@ pattern = ''' (?[ \t]*)if self\.ability\.name == 'Constellation' and not context\.blueprint''' position = "before" line_prepend = '$indent' -payload = "return nil, true" +payload = " return nil, true\n" # Constellation [[patches]] @@ -269,7 +269,7 @@ pattern = ''' (?[ \t]*)elseif context.debuffed_hand''' position = "before" line_prepend = '$indent' -payload = "nil, true" +payload = " nil, true\n" # Burnt Joker [[patches]] @@ -280,7 +280,7 @@ pattern = ''' (?[ \t]*)elseif context.discard''' position = "before" line_prepend = '$indent' -payload = "return nil, true" +payload = " return nil, true\n" # Faceless Joker [[patches]] @@ -293,7 +293,7 @@ pattern = ''' (?[ \t]*)elseif context.end_of_round''' position = "before" line_prepend = '$indent' -payload = "nil, true" +payload = " nil, true\n" # Yorick [[patches]] diff --git a/Steamodded/lovely/listed_probabilities.toml b/Steamodded/lovely/listed_probabilities.toml new file mode 100644 index 0000000..6569890 --- /dev/null +++ b/Steamodded/lovely/listed_probabilities.toml @@ -0,0 +1,162 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -5 + +# Listed pseudorandom probabilities in cards +[[patches]] +[patches.regex] +target = 'card.lua' +pattern = '''pseudorandom\((.*?)\) ?< ?G\.GAME\.probabilities\.normal ?\/ ?(.*?)( |\)|$)''' +position = 'at' +payload = "SMODS.pseudorandom_probability(self, $1, 1, $2)$3" + +# The Wheel +# Don't have to modify loc_debuff_text since that's already done via override +# Also don't have for HUD_blind_debuff_prefix since SMODS makes it unused +[[patches]] +[patches.pattern] +target = "blind.lua" +pattern = '''if self.name == 'The Wheel' and pseudorandom(pseudoseed('wheel')) < G.GAME.probabilities.normal/7 then''' +position = "at" +match_indent = true +payload = '''if self.name == 'The Wheel' and SMODS.pseudorandom_probability(self, pseudoseed('wheel'), 1, 7, 'wheel') then''' + +# Space Joker prob vars +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = '''elseif self.ability.name == 'Space Joker' then loc_vars = {''..(G.GAME and G.GAME.probabilities.normal or 1), self.ability.extra}''' +position = 'at' +payload = '''elseif self.ability.name == 'Space Joker' then loc_vars = {SMODS.get_probability_vars(self, 1, self.ability.extra, 'space')}''' +match_indent = true + +# 8 ball prob vars +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = '''elseif self.ability.name == '8 Ball' then loc_vars = {''..(G.GAME and G.GAME.probabilities.normal or 1),self.ability.extra}''' +position = 'at' +payload = '''elseif self.ability.name == '8 Ball' then loc_vars = {SMODS.get_probability_vars(self, 1, self.ability.extra, '8ball')}''' +match_indent = true + +# Gros michel prob vars +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = '''elseif self.ability.name == 'Gros Michel' then loc_vars = {self.ability.extra.mult, ''..(G.GAME and G.GAME.probabilities.normal or 1), self.ability.extra.odds}''' +position = 'at' +payload = '''elseif self.ability.name == 'Gros Michel' then loc_vars = {self.ability.extra.mult, SMODS.get_probability_vars(self, 1, self.ability.extra.odds, 'gros_michel')}''' +match_indent = true + +# Business card prob vars +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = '''elseif self.ability.name == 'Business Card' then loc_vars = {''..(G.GAME and G.GAME.probabilities.normal or 1), self.ability.extra}''' +position = 'at' +payload = '''elseif self.ability.name == 'Business Card' then loc_vars = {SMODS.get_probability_vars(self, 1, self.ability.extra, 'business')}''' +match_indent = true + +# Bloodstone prob vars +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = '''elseif self.ability.name == 'Bloodstone' then loc_vars = {''..(G.GAME and G.GAME.probabilities.normal or 1), self.ability.extra.odds, self.ability.extra.Xmult}''' +position = 'at' +payload = '''elseif self.ability.name == 'Bloodstone' then + local a, b = SMODS.get_probability_vars(self, 1, self.ability.extra.odds, 'bloodstone') + loc_vars = {a, b, self.ability.extra.Xmult}''' +match_indent = true + +# Cavendish prob vars +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = '''elseif self.ability.name == 'Cavendish' then loc_vars = {self.ability.extra.Xmult, ''..(G.GAME and G.GAME.probabilities.normal or 1), self.ability.extra.odds}''' +position = 'at' +payload = '''elseif self.ability.name == 'Cavendish' then loc_vars = {self.ability.extra.Xmult, SMODS.get_probability_vars(self, 1, self.ability.extra.odds, 'cavendish')}''' +match_indent = true + +# Reserved parking prob vars +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = '''elseif self.ability.name == 'Reserved Parking' then loc_vars = {self.ability.extra.dollars, ''..(G.GAME and G.GAME.probabilities.normal or 1), self.ability.extra.odds}''' +position = 'at' +payload = '''elseif self.ability.name == 'Reserved Parking' then loc_vars = {self.ability.extra.dollars, SMODS.get_probability_vars(self, 1, self.ability.extra.odds, 'parking')}''' +match_indent = true + +# Hallucination prob vars +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = '''elseif self.ability.name == 'Hallucination' then loc_vars = {G.GAME.probabilities.normal, self.ability.extra}''' +position = 'at' +payload = '''elseif self.ability.name == 'Hallucination' then loc_vars = {SMODS.get_probability_vars(self, 1, self.ability.extra, 'halu'..G.GAME.round_resets.ante)}''' +match_indent = true + +# Glass card prob vars +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = '''elseif _c.effect == 'Glass Card' then loc_vars = {cfg.Xmult, G.GAME.probabilities.normal, cfg.extra}''' +position = 'at' +payload = '''elseif _c.effect == 'Glass Card' then loc_vars = {cfg.Xmult, SMODS.get_probability_vars(card, 1, cfg.extra, 'glass')}''' +match_indent = true + +# Wheel prob vars +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = '''elseif _c.name == "The Wheel of Fortune" then loc_vars = {G.GAME.probabilities.normal, cfg.extra}; info_queue[#info_queue+1] = G.P_CENTERS.e_foil; info_queue[#info_queue+1] = G.P_CENTERS.e_holo; info_queue[#info_queue+1] = G.P_CENTERS.e_polychrome;''' +position = 'at' +payload = '''elseif _c.name == "The Wheel of Fortune" then + loc_vars = {SMODS.get_probability_vars(card, 1, cfg.extra, 'wheel_of_fortune')} + info_queue[#info_queue+1] = G.P_CENTERS.e_foil + info_queue[#info_queue+1] = G.P_CENTERS.e_holo + info_queue[#info_queue+1] = G.P_CENTERS.e_polychrome''' +match_indent = true + +# Modify Oops All 6s! behaviour - removed for back compat for now +# [[patches]] +# [patches.pattern] +# target = 'card.lua' +# match_indent = true +# position = 'at' +# pattern = ''' +# for k, v in pairs(G.GAME.probabilities) do +# G.GAME.probabilities[k] = v*2 +# end +# ''' +# payload = ''' +# -- removed by smods +# ''' +# [[patches]] +# [patches.pattern] +# target = 'card.lua' +# match_indent = true +# position = 'at' +# pattern = ''' +# for k, v in pairs(G.GAME.probabilities) do +# G.GAME.probabilities[k] = v/2 +# end +# ''' +# payload = ''' +# -- removed by smods +# ''' +# Add Opps All 6s! calculation +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'after' +pattern = ''' +elseif context.buying_card then +''' +payload = ''' +elseif context.mod_probability and not context.blueprint and self.config.center_key == 'j_oops' then + return { + numerator = context.numerator * 2 + } +''' diff --git a/Steamodded/lovely/multi_box_descriptions.toml b/Steamodded/lovely/multi_box_descriptions.toml new file mode 100644 index 0000000..af23ca8 --- /dev/null +++ b/Steamodded/lovely/multi_box_descriptions.toml @@ -0,0 +1,160 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +# Handle multi boxes in localize +[[patches]] +[patches.pattern] +target = 'functions/misc_functions.lua' +match_indent = true +position = 'before' +pattern = ''' +for _, lines in ipairs(args.type == 'unlocks' and loc_target.unlock_parsed or args.type == 'name' and loc_target.name_parsed or (args.type == 'text' or args.type == 'tutorial' or args.type == 'quips') and loc_target or loc_target.text_parsed) do +''' +payload = ''' +args.AUT = args.AUT or {} +args.AUT.box_colours = {} +if (args.type == 'descriptions' or args.type == 'other') and type(loc_target.text) == 'table' and type(loc_target.text[1]) == 'table' then + if not args.is_info_queue then + args.AUT.multi_box = {} + end + for i, box in ipairs(loc_target.text_parsed) do + for j, line in ipairs(box) do + local final_line = SMODS.localize_box(line, args) + if i == 1 or next(args.AUT.info) then + args.nodes[#args.nodes+1] = final_line -- Sends main box to AUT.main + if not next(args.AUT.info) then args.nodes.main_box_flag = true end + elseif not next(args.AUT.info) then + args.AUT.multi_box[i-1] = args.AUT.multi_box[i-1] or {} + args.AUT.multi_box[i-1][#args.AUT.multi_box[i-1]+1] = final_line + end + if not next(args.AUT.info) then args.AUT.box_colours[i] = args.vars.box_colours and args.vars.box_colours[i] or G.C.UI.BACKGROUND_WHITE end + end + end + return +end +''' + +# Patch importing localizations +[[patches]] +[patches.pattern] +target = 'functions/misc_functions.lua' +match_indent = true +position = 'at' +pattern = ''' +for _, line in ipairs(center.text) do + center.text_parsed[#center.text_parsed+1] = loc_parse_string(line) +end +''' +payload = ''' +for _, line in ipairs(center.text) do + if type(line) == 'table' then + center.text_parsed[#center.text_parsed+1] = {} + for _, new_line in ipairs(line) do + center.text_parsed[#center.text_parsed][#center.text_parsed[#center.text_parsed]+1] = loc_parse_string(new_line) + end + else + center.text_parsed[#center.text_parsed+1] = loc_parse_string(line) + end +end +''' + +# Create extra boxes +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +match_indent = true +position = 'before' +pattern = ''' +if AUT.info then +''' +payload = ''' +AUT.main.background_colour = AUT.main.background_colour or AUT.box_colours and AUT.box_colours[1] or nil +local multi_boxes = {} +if AUT.multi_box then + for i, box in ipairs(AUT.multi_box) do + box.background_colour = box.background_colour or AUT.box_colours and AUT.box_colours[i+1] or nil + multi_boxes[#multi_boxes+1] = desc_from_rows(box) + end +end +''' + +# Change return so it can be modified +# Includes some info_boxes patch that got munched +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +match_indent = true +position = 'at' +pattern = ''' +return {n=G.UIT.ROOT, config = {align = 'cm', colour = G.C.CLEAR}, nodes={ + {n=G.UIT.C, config={align = "cm", func = 'show_infotip',object = Moveable(),ref_table = next(info_boxes) and info_boxes or nil}, nodes={ +''' +payload = ''' +local cols +if #info_boxes <= 3 then + cols = 1 +elseif #info_boxes <= 10 then + cols = 2 +elseif #info_boxes <= 24 then + cols = 3 +else + cols = 4 +end +local nodes_per_col = math.ceil(#info_boxes/cols) +local info_cols = {} +for i = 0, cols-1 do + local col = {} + for j = 1, nodes_per_col do + local info_box = info_boxes[i*nodes_per_col+j] + if info_box then + table.insert(col, info_box) + else break end + end + table.insert(info_cols, {n=G.UIT.C, config = {align="cm"}, nodes = col}) +end +info_boxes = {{n=G.UIT.R, config = {align="cm", padding = 0.05, card_pos = card.T.x }, nodes = info_cols}} +local ret_val = {n=G.UIT.ROOT, config = {align = 'cm', colour = G.C.CLEAR}, nodes={ + {n=G.UIT.C, config={align = "cm", func = 'show_infotip',object = Moveable(),ref_table = next(info_boxes) and info_boxes or nil}, nodes={ +''' + +# Add multi boxes to return table +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +match_indent = true +position = 'after' +pattern = ''' + badges[1] and {n=G.UIT.R, config={align = "cm", padding = 0.03}, nodes=badges} or nil, + }} + }} + }}, +}} +''' +payload = ''' +if multi_boxes[1] then + for i=1, #ret_val.nodes[1].nodes[1].nodes[1].nodes do -- find the main box + if ret_val.nodes[1].nodes[1].nodes[1].nodes[i] and ret_val.nodes[1].nodes[1].nodes[1].nodes[i].config and ret_val.nodes[1].nodes[1].nodes[1].nodes[i].config.main_box_flag then + for j=#multi_boxes, 1, -1 do -- add the extra boxes + table.insert(ret_val.nodes[1].nodes[1].nodes[1].nodes, i+1, multi_boxes[j]) + end + break + end + end + +end + +return ret_val +''' + +# Add main_box_flag to the main box +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +match_indent = true +position = 'at' +pattern = ''' +return {n=G.UIT.R, config={align = "cm", colour = empty and G.C.CLEAR or G.C.UI.BACKGROUND_WHITE, r = 0.1, padding = 0.04, minw = 2, minh = 0.8, emboss = not empty and 0.05 or nil, filler = true}, nodes={''' +payload = ''' +return {n=G.UIT.R, config={align = "cm", colour = empty and G.C.CLEAR or G.C.UI.BACKGROUND_WHITE, r = 0.1, padding = 0.04, minw = 2, minh = 0.8, emboss = not empty and 0.05 or nil, filler = true, main_box_flag = desc_nodes.main_box_flag and true or nil}, nodes={''' diff --git a/Steamodded/lovely/perma_bonus.toml b/Steamodded/lovely/perma_bonus.toml index 6bf2387..fc888fc 100644 --- a/Steamodded/lovely/perma_bonus.toml +++ b/Steamodded/lovely/perma_bonus.toml @@ -39,34 +39,7 @@ match_indent = true target = "functions/common_events.lua" pattern = "elseif _c.set == 'Enhanced' then" position = "before" -payload = ''' -if specific_vars and specific_vars.bonus_x_chips then - localize{type = 'other', key = 'card_x_chips', nodes = desc_nodes, vars = {specific_vars.bonus_x_chips}} -end -if specific_vars and specific_vars.bonus_mult then - localize{type = 'other', key = 'card_extra_mult', nodes = desc_nodes, vars = {SMODS.signed(specific_vars.bonus_mult)}} -end -if specific_vars and specific_vars.bonus_x_mult then - localize{type = 'other', key = 'card_x_mult', nodes = desc_nodes, vars = {specific_vars.bonus_x_mult}} -end -if specific_vars and specific_vars.bonus_h_chips then - localize{type = 'other', key = 'card_extra_h_chips', nodes = desc_nodes, vars = {SMODS.signed(specific_vars.bonus_h_chips)}} -end -if specific_vars and specific_vars.bonus_h_x_chips then - localize{type = 'other', key = 'card_h_x_chips', nodes = desc_nodes, vars = {specific_vars.bonus_h_x_chips}} -end -if specific_vars and specific_vars.bonus_h_mult then - localize{type = 'other', key = 'card_extra_h_mult', nodes = desc_nodes, vars = {SMODS.signed(specific_vars.bonus_h_mult)}} -end -if specific_vars and specific_vars.bonus_h_x_mult then - localize{type = 'other', key = 'card_h_x_mult', nodes = desc_nodes, vars = {specific_vars.bonus_h_x_mult}} -end -if specific_vars and specific_vars.bonus_p_dollars then - localize{type = 'other', key = 'card_extra_p_dollars', nodes = desc_nodes, vars = {SMODS.signed_dollars(specific_vars.bonus_p_dollars)}} -end -if specific_vars and specific_vars.bonus_h_dollars then - localize{type = 'other', key = 'card_extra_h_dollars', nodes = desc_nodes, vars = {SMODS.signed_dollars(specific_vars.bonus_h_dollars)}} -end''' +payload = '''SMODS.localize_perma_bonuses(specific_vars, desc_nodes)''' match_indent = true overwrite = false @@ -94,34 +67,7 @@ payload = "localize{type = 'other', key = 'card_extra_chips', nodes = desc_nodes target = "functions/common_events.lua" pattern = "elseif _c.set == 'Booster' then" position = "before" -payload = ''' -if specific_vars and specific_vars.bonus_x_chips then - localize{type = 'other', key = 'card_x_chips', nodes = desc_nodes, vars = {specific_vars.bonus_x_chips}} -end -if specific_vars and specific_vars.bonus_mult and _c.effect ~= 'Mult Card' then - localize{type = 'other', key = 'card_extra_mult', nodes = desc_nodes, vars = {SMODS.signed(specific_vars.bonus_mult)}} -end -if specific_vars and specific_vars.bonus_x_mult then - localize{type = 'other', key = 'card_x_mult', nodes = desc_nodes, vars = {specific_vars.bonus_x_mult}} -end -if specific_vars and specific_vars.bonus_h_chips then - localize{type = 'other', key = 'card_extra_h_chips', nodes = desc_nodes, vars = {SMODS.signed(specific_vars.bonus_h_chips)}} -end -if specific_vars and specific_vars.bonus_h_x_chips then - localize{type = 'other', key = 'card_h_x_chips', nodes = desc_nodes, vars = {specific_vars.bonus_h_x_chips}} -end -if specific_vars and specific_vars.bonus_h_mult then - localize{type = 'other', key = 'card_extra_h_mult', nodes = desc_nodes, vars = {SMODS.signed(specific_vars.bonus_h_mult)}} -end -if specific_vars and specific_vars.bonus_h_x_mult then - localize{type = 'other', key = 'card_h_x_mult', nodes = desc_nodes, vars = {specific_vars.bonus_h_x_mult}} -end -if specific_vars and specific_vars.bonus_p_dollars then - localize{type = 'other', key = 'card_extra_p_dollars', nodes = desc_nodes, vars = {SMODS.signed_dollars(specific_vars.bonus_p_dollars)}} -end -if specific_vars and specific_vars.bonus_h_dollars and _c.effect ~= 'Gold Card' then - localize{type = 'other', key = 'card_extra_h_dollars', nodes = desc_nodes, vars = {SMODS.signed_dollars(specific_vars.bonus_h_dollars)}} -end''' +payload = '''SMODS.localize_perma_bonuses(specific_vars, desc_nodes)''' match_indent = true overwrite = false @@ -153,7 +99,8 @@ bonus_h_x_mult = self.ability.perma_h_x_mult ~= 0 and (self.ability.perma_h_x_mu bonus_p_dollars = self.ability.perma_p_dollars ~= 0 and self.ability.perma_p_dollars or nil, bonus_h_dollars = self.ability.perma_h_dollars ~= 0 and self.ability.perma_h_dollars or nil, total_h_dollars = total_h_dollars ~= 0 and total_h_dollars or nil, -bonus_chips = bonus_chips ~= 0 and bonus_chips or nil,''' +bonus_chips = bonus_chips ~= 0 and bonus_chips or nil, +bonus_repetitions = self.ability.perma_repetitions ~= 0 and self.ability.perma_repetitions or nil,''' match_indent = true overwrite = false @@ -169,6 +116,7 @@ x_mult = center.config.Xmult or center.config.x_mult or 1, h_chips = center.config.h_chips or 0, x_chips = center.config.x_chips or 1, h_x_chips = center.config.h_x_chips or 1, +repetitions = center.config.repetitions or 0, ''' match_indent = true overwrite = false @@ -185,14 +133,27 @@ perma_mult = self.ability and self.ability.perma_mult or 0, perma_x_mult = self.ability and self.ability.perma_x_mult or 0, perma_h_chips = self.ability and self.ability.perma_h_chips or 0, perma_h_x_chips = self.ability and self.ability.perma_h_x_chips or 0, -perma_h_mult = self.ability and self.ability.perma_hmult or 0, +perma_h_mult = self.ability and self.ability.perma_h_mult or 0, perma_h_x_mult = self.ability and self.ability.perma_h_x_mult or 0, perma_p_dollars = self.ability and self.ability.perma_p_dollars or 0, perma_h_dollars = self.ability and self.ability.perma_h_dollars or 0, +perma_repetitions = self.ability and self.ability.perma_repetitions or 0, +card_limit = self.ability and self.ability.card_limit or 0, +extra_slots_used = self.ability and self.ability.extra_slots_used or 0, ''' match_indent = true overwrite = false +# Card:get_chip_bonus +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''function Card:get_chip_bonus(*''' +position = "after" +match_indent = true +payload = ''' + if self.ability.extra_enhancement then return self.ability.bonus end''' + # Card:get_chip_mult [[patches]] [patches.pattern] @@ -209,9 +170,9 @@ else end''' position = "at" match_indent = true -payload = '''local ret = self.ability.perma_mult or 0 +payload = '''local ret = (not self.ability.extra_enhancement and self.ability.perma_mult) or 0 if self.ability.effect == "Lucky Card" then - if pseudorandom('lucky_mult') < G.GAME.probabilities.normal/5 then + if SMODS.pseudorandom_probability(self, 'lucky_mult', 1, 5) then self.lucky_trigger = true ret = ret + self.ability.mult end @@ -229,7 +190,7 @@ pattern = '''if self.ability.x_mult <= 1 then return 0 end return self.ability.x_mult''' position = "at" match_indent = true -payload = '''local ret = SMODS.multiplicative_stacking(self.ability.x_mult or 1, self.ability.perma_x_mult or 0) +payload = '''local ret = SMODS.multiplicative_stacking(self.ability.x_mult or 1, (not self.ability.extra_enhancement and self.ability.perma_x_mult) or 0) -- TARGET: get_chip_x_mult return ret ''' @@ -241,7 +202,7 @@ target = "card.lua" pattern = 'return self.ability.h_mult' position = "at" match_indent = true -payload = '''local ret = (self.ability.h_mult or 0) + (self.ability.perma_h_mult or 0) +payload = '''local ret = (self.ability.h_mult or 0) + ((not self.ability.extra_enhancement and self.ability.perma_h_mult) or 0) -- TARGET: get_chip_h_mult return ret ''' @@ -253,7 +214,7 @@ target = "card.lua" pattern = 'return self.ability.h_x_mult' position = "at" match_indent = true -payload = '''local ret = SMODS.multiplicative_stacking(self.ability.h_x_mult or 1, self.ability.perma_h_x_mult or 0) +payload = '''local ret = SMODS.multiplicative_stacking(self.ability.h_x_mult or 1, (not self.ability.extra_enhancement and self.ability.perma_h_x_mult) or 0) -- TARGET: get_chip_h_x_mult return ret ''' @@ -271,28 +232,28 @@ match_indent = true payload = ''' function Card:get_chip_x_bonus() if self.debuff then return 0 end - local ret = SMODS.multiplicative_stacking(self.ability.x_chips or 1, self.ability.perma_x_chips or 0) + local ret = SMODS.multiplicative_stacking(self.ability.x_chips or 1, (not self.ability.extra_enhancement and self.ability.perma_x_chips) or 0) -- TARGET: get_chip_x_bonus return ret end function Card:get_chip_h_bonus() if self.debuff then return 0 end - local ret = (self.ability.h_chips or 0) + (self.ability.perma_h_chips or 0) + local ret = (self.ability.h_chips or 0) + ((not self.ability.extra_enhancement and self.ability.perma_h_chips) or 0) -- TARGET: get_chip_h_bonus return ret end function Card:get_chip_h_x_bonus() if self.debuff then return 0 end - local ret = SMODS.multiplicative_stacking(self.ability.h_x_chips or 1, self.ability.perma_h_x_chips or 0) + local ret = SMODS.multiplicative_stacking(self.ability.h_x_chips or 1, (not self.ability.extra_enhancement and self.ability.perma_h_x_chips) or 0) -- TARGET: get_chip_h_x_bonus return ret end function Card:get_h_dollars() if self.debuff then return 0 end - local ret = (self.ability.h_dollars or 0) + (self.ability.perma_h_dollars or 0) + local ret = (self.ability.h_dollars or 0) + ((not self.ability.extra_enhancement and self.ability.perma_h_dollars) or 0) -- TARGET: get_h_dollars return ret end @@ -310,7 +271,7 @@ match_indent = true payload = '''elseif self.ability.p_dollars < 0 then ret = ret + self.ability.p_dollars end -ret = ret + (self.ability.perma_p_dollars) or 0 +ret = ret + ((not self.ability.extra_enhancement and self.ability.perma_p_dollars) or 0) -- TARGET: get_p_dollars if ret ~= 0 then G.GAME.dollar_buffer = (G.GAME.dollar_buffer or 0) + ret''' @@ -333,5 +294,4 @@ if h_dollars ~= 0 then ret.h_dollars = h_dollars ret.card = self end -''' -times = 1 +''' \ No newline at end of file diff --git a/Steamodded/lovely/playing_card.toml b/Steamodded/lovely/playing_card.toml index 8889bb6..38848fe 100644 --- a/Steamodded/lovely/playing_card.toml +++ b/Steamodded/lovely/playing_card.toml @@ -37,8 +37,8 @@ pattern = 'local _ = nil' position = 'before' match_indent = true payload = ''' -if type(SMODS.Ranks[v.value].in_pool) == 'function' and not SMODS.Ranks[v.value]:in_pool({initial_deck = true, suit = v.suit}) -or type(SMODS.Suits[v.suit].in_pool) == 'function' and not SMODS.Suits[v.suit]:in_pool({initial_deck = true, rank = v.value}) then +if not SMODS.add_to_pool(SMODS.Ranks[v.value], {initial_deck = true, suit = v.suit}) +or not SMODS.add_to_pool(SMODS.Suits[v.suit], {initial_deck = true, rank = v.value}) then goto continue end''' @@ -100,14 +100,43 @@ payload = ''' # get_flush() [[patches]] -[patches.regex] +[patches.pattern] target = "functions/misc_functions.lua" -pattern = '(?[\t ]*)local suits = \{\n[\t ]*"Spades",\n[\t ]*"Hearts",\n[\t ]*"Clubs",\n[\t ]*"Diamonds"\n[\t ]*\}\n[\t ]*if #hand > 5 or (?#hand < \(5 - \(four_fingers and 1 or 0\)\) then return ret else)' +pattern = ''' +local suits = { + "Spades", + "Hearts", + "Clubs", + "Diamonds" + } +''' position = 'at' -line_prepend = '$indent' -payload = ''' -local suits = SMODS.Suit.obj_buffer -if $restcond''' +payload = 'local suits = SMODS.Suit.obj_buffer' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = "local four_fingers = next(find_joker('Four Fingers'))" +position = 'at' +payload = "local four_fingers = SMODS.four_fingers('flush')" +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = "if #hand > 5 or #hand < (5 - (four_fingers and 1 or 0)) then return ret else" +position = 'at' +payload = "if #hand < four_fingers then return ret else" +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = "if flush_count >= (5 - (four_fingers and 1 or 0)) then" +position = 'at' +payload = "if flush_count >= four_fingers then" +match_indent = true # get_X_same() [[patches]] @@ -256,10 +285,10 @@ pattern = 'local keep, _e, _d, _g = true, nil, nil, nil' position = 'after' match_indent = true payload = ''' -if type(SMODS.Ranks[v.value].in_pool) == 'function' and not SMODS.Ranks[v.value]:in_pool({initial_deck = true, suit = v.suit}) then +if not SMODS.add_to_pool(SMODS.Ranks[v.value], {initial_deck = true, suit = v.suit}) then keep = false end -if type(SMODS.Suits[v.suit].in_pool) == 'function' and not SMODS.Suits[v.suit]:in_pool({initial_deck = true, rank = v.value}) then +if not SMODS.add_to_pool(SMODS.Suits[v.suit], {initial_deck = true, rank = v.value}) then keep = false end''' @@ -300,3 +329,19 @@ payload = '''if card_type == 'Default' or card_type == 'Enhanced' and not _c.rep end ''' + +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = '''function Card:set_base(card, initial)''' +position = 'at' +match_indent = true +payload = '''function Card:set_base(card, initial, manual_sprites)''' + +[[patches]] +[patches.pattern] +target = 'card.lua' +pattern = '''if next(card) then''' +position = 'at' +match_indent = true +payload = '''if next(card) and not manual_sprites then''' \ No newline at end of file diff --git a/Steamodded/lovely/poker_hand.toml b/Steamodded/lovely/poker_hand.toml index d6f0f05..ebe5033 100644 --- a/Steamodded/lovely/poker_hand.toml +++ b/Steamodded/lovely/poker_hand.toml @@ -58,3 +58,48 @@ for _, v in ipairs(G.handlist) do end end''' match_indent = true + +## is_visible + +# create_UIBox_blind_choice +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = '''if v.visible then _poker_hands[#_poker_hands+1] = k end''' +position = "at" +payload = ''' +if SMODS.is_poker_hand_visible(k) then _poker_hands[#_poker_hands+1] = k end +''' +match_indent = true + +# card:calculate_joker +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''if k ~= context.scoring_name and v.played >= play_more_than and v.visible then''' +position = "at" +payload = ''' +if k ~= context.scoring_name and v.played >= play_more_than and SMODS.is_poker_hand_visible(k) then +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''if v.visible and k ~= self.ability.to_do_poker_hand then _poker_hands[#_poker_hands+1] = k end''' +position = "at" +payload = ''' +if SMODS.is_poker_hand_visible(k) and k ~= self.ability.to_do_poker_hand then _poker_hands[#_poker_hands+1] = k end +''' +match_indent = true + +# card:set_ability +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''if v.visible then _poker_hands[#_poker_hands+1] = k end''' +position = "at" +payload = ''' +if SMODS.is_poker_hand_visible(k) then _poker_hands[#_poker_hands+1] = k end +''' +match_indent = true diff --git a/Steamodded/lovely/poker_hand_screen.toml b/Steamodded/lovely/poker_hand_screen.toml new file mode 100644 index 0000000..03b192d --- /dev/null +++ b/Steamodded/lovely/poker_hand_screen.toml @@ -0,0 +1,41 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +# Add enhancements to poker hand screen +# create_UIBox_hand_tip +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = '''local card = Card(0,0, 0.5*G.CARD_W, 0.5*G.CARD_H, G.P_CARDS[v[1]], G.P_CENTERS.c_base)''' +position = "at" +payload = ''' +local card = Card(0,0, 0.5*G.CARD_W, 0.5*G.CARD_H, G.P_CARDS[v[1]], G.P_CENTERS[v.enhancement or 'c_base']) +if v.edition then card:set_edition(v.edition, true, true) end +if v.seal then card:set_seal(v.seal, true, true) end +''' +match_indent = true + +# Add text styling to poker hand screen +# create_popup_UIBox_tooltip +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = '''local r = {n=G.UIT.R, config={align = "cm", padding = 0.03}, nodes={ + {n=G.UIT.T, config={text = text[i],colour = G.C.UI.TEXT_DARK, scale = 0.4}}}}''' +position = "at" +payload = ''' +local r = {n=G.UIT.R, config={align = "cm", padding = 0.03}, nodes=SMODS.localize_box(loc_parse_string(text[i]), {scale = 1.25})} +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = '''return (G.GAME.hands[handname].visible) and''' +position = "at" +payload = ''' +return SMODS.is_poker_hand_visible(handname) and +''' +match_indent = true \ No newline at end of file diff --git a/Steamodded/lovely/pool.toml b/Steamodded/lovely/pool.toml index 2480665..16b7c18 100644 --- a/Steamodded/lovely/pool.toml +++ b/Steamodded/lovely/pool.toml @@ -13,6 +13,7 @@ target = "functions/misc_functions.lua" pattern = "function pseudorandom_element(_t, seed)" position = "at" payload = """function pseudorandom_element(_t, seed, args) + if seed and type(seed) == "string" then seed = pseudoseed(seed) end -- TODO special cases for now -- Preserves reverse nominal order for Suits, nominal+face_nominal order for Ranks -- for vanilla RNG @@ -32,16 +33,16 @@ pattern = "keys[#keys+1] = {k = k,v = v}" position = "at" payload = """ local keep = true -local in_pool_func = +local in_pool_func = args and args.in_pool or type(v) == 'table' and type(v.in_pool) == 'function' and v.in_pool or _t == G.P_CARDS and function(c) --Handles special case for Erratic Deck local initial_deck = args and args.starting_deck or false - + return not ( - type(SMODS.Ranks[c.value].in_pool) == 'function' and not SMODS.Ranks[c.value]:in_pool({initial_deck = initial_deck, suit = c.suit}) - or type(SMODS.Suits[c.suit].in_pool) == 'function' and not SMODS.Suits[c.suit]:in_pool({initial_deck = initial_deck, rank = c.value}) + not SMODS.add_to_pool(SMODS.Ranks[c.value], {initial_deck = initial_deck, suit = c.suit}) + or not SMODS.add_to_pool(SMODS.Suits[c.suit], {initial_deck = initial_deck, rank = c.value}) ) end if in_pool_func then @@ -109,20 +110,31 @@ pattern = "if _type == 'Enhanced' then" match_indent = true position = 'before' payload = ''' -local in_pool, pool_opts -if v.in_pool and type(v.in_pool) == 'function' then - in_pool, pool_opts = v:in_pool({ source = _append }) -end +local in_pool, pool_opts = SMODS.add_to_pool(v, { source = _append }) pool_opts = pool_opts or {} ''' +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = ''' +if _type == 'Enhanced' then + add = true +''' +match_indent = true +position = 'after' +payload = ''' +elseif _type == 'Edition' then + if v.in_shop then add = true end +''' + [[patches]] [patches.pattern] target = 'functions/common_events.lua' pattern = 'elseif not (G.GAME.used_jokers[v.key] and not next(find_joker("Showman"))) and' match_indent = true position = 'at' -payload = '''elseif not (G.GAME.used_jokers[v.key] and not pool_opts.allow_duplicates and not next(find_joker("Showman"))) and''' +payload = '''elseif not (G.GAME.used_jokers[v.key] and not pool_opts.allow_duplicates and not SMODS.showman(v.key)) and''' [[patches]] [patches.pattern] @@ -136,6 +148,18 @@ if v.in_pool and type(v.in_pool) == 'function' then end ''' +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = ''' +elseif _type == 'Tag' then _pool[#_pool + 1] = "tag_handy" +''' +match_indent = true +position = 'after' +payload = ''' +elseif _type == 'Edition' then _pool[#_pool + 1] = "e_foil" +''' + ## G.GAME.used_jokers now checks keys, not names # Card:set_ability() # Remove the old center from `used_jokers` if set_ability overrides @@ -145,7 +169,7 @@ target = "card.lua" pattern = "self.config.center = center" position = 'after' payload = ''' -if old_center and not next(SMODS.find_card(old_center.key, true)) then +if not G.OVERLAY_MENU and old_center and not next(SMODS.find_card(old_center.key, true)) then G.GAME.used_jokers[old_center.key] = nil end''' match_indent = true diff --git a/Steamodded/lovely/rarity.toml b/Steamodded/lovely/rarity.toml index efaef67..6b426ee 100644 --- a/Steamodded/lovely/rarity.toml +++ b/Steamodded/lovely/rarity.toml @@ -57,5 +57,5 @@ local rarity = _rarity or SMODS.poll_rarity("Joker", 'rarity'..G.GAME.round_rese target = "card.lua" pattern = "if self.ability.name == 'Baseball Card' and context.other_joker.config.center.rarity == 2 and self ~= context.other_joker then" position = "at" -payload = '''if self.ability.name == 'Baseball Card' and (context.other_joker.config.center.rarity == 2 or context.other_joker.config.center.rarity == "Uncommon") and self ~= context.other_joker then''' +payload = '''if self.ability.name == 'Baseball Card' and self ~= context.other_joker and context.other_joker:is_rarity("Uncommon") then''' match_indent = true diff --git a/Steamodded/lovely/scaling.toml b/Steamodded/lovely/scaling.toml new file mode 100644 index 0000000..b6635c2 --- /dev/null +++ b/Steamodded/lovely/scaling.toml @@ -0,0 +1,657 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +# Ceremonial Dagger +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = ''' +self.ability.mult = self.ability.mult + sliced_card.sell_cost*2 +''' +payload = ''' +''' + +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = '''card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize{type = 'variable', key = 'a_mult', vars = {self.ability.mult+2*sliced_card.sell_cost}}, colour = G.C.RED, no_juice = true})''' +position = 'at' +match_indent = true +payload = ''' +SMODS.scale_card(self, { + ref_table = self.ability, + ref_value = "mult", + scalar_table = sliced_card, + scalar_value = "sell_cost", + operation = function(ref_table, ref_value, initial, scaling) + ref_table[ref_value] = initial + 2*scaling + end, + scaling_message = { + message = localize{type = 'variable', key = 'a_mult', vars = {self.ability.mult+2*sliced_card.sell_cost}}, + colour = G.C.RED, + no_juice = true + } +}) +''' + +# Flash Card +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = ''' +self.ability.mult = self.ability.mult + self.ability.extra +G.E_MANAGER:add_event(Event({ + func = (function() + card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize{type = 'variable', key = 'a_mult', vars = {self.ability.mult}}, colour = G.C.MULT}) + return true +end)})) +''' +payload = ''' +SMODS.scale_card(self, { + ref_table = self.ability, + ref_value = "mult", + scalar_value = "extra", + message_key = 'a_mult', + message_colour = G.C.RED +}) +''' +# Red Card +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = ''' +self.ability.mult = self.ability.mult + self.ability.extra + G.E_MANAGER:add_event(Event({ + func = function() + card_eval_status_text(self, 'extra', nil, nil, nil, { + message = localize{type = 'variable', key = 'a_mult', vars = {self.ability.extra}}, + colour = G.C.RED, + delay = 0.45, + card = self + }) + return true + end})) +''' +payload = ''' +SMODS.scale_card(self, { + ref_table = self.ability, + ref_value = "mult", + scalar_value = "extra", + message_key = 'a_mult', + message_colour = G.C.RED +}) +''' +# Spare Trousers +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = ''' +self.ability.mult = self.ability.mult + self.ability.extra +return { + message = localize('k_upgrade_ex'), + colour = G.C.RED, + card = self +} +''' +payload = ''' +SMODS.scale_card(self, { + ref_table = self.ability, + ref_value = "mult", + scalar_value = "extra", + message_colour = G.C.RED +}) +''' +# Ride The Bus +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = ''' +else + self.ability.mult = self.ability.mult + self.ability.extra +end +''' +payload = ''' +else + SMODS.scale_card(self, { + ref_table = self.ability, + ref_value = "mult", + scalar_value = "extra", + no_message = true + }) +end +''' + +# Egg +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +self.ability.extra_value = self.ability.extra_value + self.ability.extra +self:set_cost() +return { + message = localize('k_val_up'), + colour = G.C.MONEY +} +''' +position = 'at' +match_indent = true +payload = ''' +SMODS.scale_card(self, { + ref_table = self.ability, + ref_value = "extra_value", + scalar_value = "extra", + scaling_message = { + message = localize('k_val_up'), + colour = G.C.MONEY + } +}) +self:set_cost() +''' + +# Runner/Square Joker/Castle +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +self.ability.extra.chips = self.ability.extra.chips + self.ability.extra.chip_mod +return { + message = localize('k_upgrade_ex'), + colour = G.C.CHIPS, + card = self +} +''' +position = 'at' +match_indent = true +payload = ''' +SMODS.scale_card(self, { + ref_table = self.ability.extra, + ref_value = "chips", + scalar_value = "chip_mod", +}) +''' + +# Wee Joker +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +self.ability.extra.chips = self.ability.extra.chips + self.ability.extra.chip_mod + +return { + extra = {focus = self, message = localize('k_upgrade_ex')}, + card = self, + colour = G.C.CHIPS +} +''' +position = 'at' +match_indent = true +payload = ''' +SMODS.scale_card(self, { + ref_table = self.ability.extra, + ref_value = "chips", + scalar_value = "chip_mod", + scaling_message = { + extra = {focus = self, message = localize('k_upgrade_ex')}, + colour = G.C.CHIPS + } +}) +''' + +# Ice Cream +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +self.ability.extra.chips = self.ability.extra.chips - self.ability.extra.chip_mod +return { + message = localize{type='variable',key='a_chips_minus',vars={self.ability.extra.chip_mod}}, + colour = G.C.CHIPS +} +''' +position = 'at' +match_indent = true +payload = ''' +SMODS.scale_card(self, { + ref_table = self.ability.extra, + ref_value = "chips", + scalar_value = "chip_mod", + operation = "-", + message_key = 'a_chips_minus' +}) +''' + +# Madness +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +if self.ability.name == 'Madness' and not context.blueprint and not context.blind.boss then + self.ability.x_mult = self.ability.x_mult + self.ability.extra +''' +position = 'at' +match_indent = true +payload = ''' +if self.ability.name == 'Madness' and not context.blueprint and not context.blind.boss then +''' +# Madness pt2 +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = ''' +if not (context.blueprint_card or self).getting_sliced then + card_eval_status_text((context.blueprint_card or self), 'extra', nil, nil, nil, {message = localize{type = 'variable', key = 'a_xmult', vars = {self.ability.x_mult}}}) +end +''' +payload = ''' +if not (context.blueprint_card or self).getting_sliced then + SMODS.scale_card(context.blueprint_card or self, { + ref_table = self.ability, + ref_value = "x_mult", + scalar_value = "extra", + message_key = 'a_xmult' + }) +end +''' + +# Constellation +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +if self.ability.name == 'Constellation' and not context.blueprint and context.consumeable.ability.set == 'Planet' then + self.ability.x_mult = self.ability.x_mult + self.ability.extra + G.E_MANAGER:add_event(Event({ + func = function() card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize{type='variable',key='a_xmult',vars={self.ability.x_mult}}}); return true + end})) +''' +position = 'at' +match_indent = true +payload = ''' +if self.ability.name == 'Constellation' and not context.blueprint and context.consumeable.ability.set == 'Planet' then + SMODS.scale_card(self, { + ref_table = self.ability, + ref_value = "x_mult", + scalar_value = "extra", + message_key = 'a_xmult' + }) +''' +# Campfire +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = ''' +self.ability.x_mult = self.ability.x_mult + self.ability.extra +G.E_MANAGER:add_event(Event({ + func = function() card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize('k_upgrade_ex')}); return true + end})) +''' +payload = ''' +SMODS.scale_card(self, { + ref_table = self.ability, + ref_value = "x_mult", + scalar_value = "extra", + message_colour = G.C.FILTER +}) +''' +# Lucky Cat +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = ''' +self.ability.x_mult = self.ability.x_mult + self.ability.extra +return { + extra = {focus = self, message = localize('k_upgrade_ex'), colour = G.C.MULT}, + card = self +} +''' +payload = ''' +SMODS.scale_card(self, { + ref_table = self.ability, + ref_value = "x_mult", + scalar_value = "extra", + message_colour = G.C.MULT +}) +''' +# Obelisk +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = ''' +else + self.ability.x_mult = self.ability.x_mult + self.ability.extra +end +''' +payload = ''' +else + SMODS.scale_card(self, { + ref_table = self.ability, + ref_value = "x_mult", + scalar_value = "extra", + no_message = true + }) +end +''' + +# Hit the Road/Lucky Cat/Obelisk +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +self.ability.x_mult = self.ability.x_mult + self.ability.extra +return { + message = localize{type='variable',key='a_xmult',vars={self.ability.x_mult}}, + colour = G.C.RED, + delay = 0.45, + card = self +} +''' +position = 'at' +match_indent = true +payload = ''' +SMODS.scale_card(self, { + ref_table = self.ability, + ref_value = "x_mult", + scalar_value = "extra", + message_key = 'a_xmult', + message_colour = G.C.RED +}) +''' + +# Green Joker: Subtraction +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +self.ability.mult = math.max(0, self.ability.mult - self.ability.extra.discard_sub) +if self.ability.mult ~= prev_mult then + return { + message = localize{type='variable',key='a_mult_minus',vars={self.ability.extra.discard_sub}}, + colour = G.C.RED, + card = self + } +end +''' +position = 'at' +match_indent = true +payload = ''' +if self.ability.mult ~= 0 then + SMODS.scale_card(self, { + ref_table = self.ability, + ref_value = "mult", + scalar_table = self.ability.extra, + scalar_value = "discard_sub", + operation = function(ref_table, ref_value, initial, change) + ref_table[ref_value] = math.max(0, initial - change) + end, + message_key = 'a_mult_minus', + message_colour = G.C.RED + }) +end +''' + +# Green Joker: Addition +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +self.ability.mult = self.ability.mult + self.ability.extra.hand_add +return { + card = self, + message = localize{type='variable',key='a_mult',vars={self.ability.extra.hand_add}} +} +''' +position = 'at' +match_indent = true +payload = ''' +SMODS.scale_card(self, { + ref_table = self.ability, + ref_value = "mult", + scalar_table = self.ability.extra, + scalar_value = "hand_add" +}) +''' + +# Vampire +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +self.ability.x_mult = self.ability.x_mult + self.ability.extra*#enhanced +return { + message = localize{type='variable',key='a_xmult',vars={self.ability.x_mult}}, + colour = G.C.MULT, + card = self +} +''' +position = 'at' +match_indent = true +payload = ''' +SMODS.scale_card(self, { + ref_table = self.ability, + ref_value = "x_mult", + scalar_value = "extra", + message_key = 'a_xmult', + message_colour = G.C.MULT, + operation = function(ref_table, ref_value, initial, scaling) + ref_table[ref_value] = initial + scaling*#enhanced + end +}) +''' + +# Hologram +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +self.ability.x_mult = self.ability.x_mult + #context.cards*self.ability.extra +card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize{type = 'variable', key = 'a_xmult', vars = {self.ability.x_mult}}}) +''' +position = 'at' +match_indent = true +payload = ''' +SMODS.scale_card(self, { + ref_table = self.ability, + ref_value = "x_mult", + scalar_value = "extra", + message_key = 'a_xmult', + operation = function(ref_table, ref_value, initial, scaling) + ref_table[ref_value] = initial + scaling*#context.cards + end +}) +''' + +# Rocket +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +self.ability.extra.dollars = self.ability.extra.dollars + self.ability.extra.increase +return { + message = localize('k_upgrade_ex'), + colour = G.C.MONEY +} +''' +position = 'at' +match_indent = true +payload = ''' +SMODS.scale_card(self, { + ref_table = self.ability.extra, + ref_value = "dollars", + scalar_value = "increase", + message_colour = G.C.MONEY +}) +''' + +# Turtle Bean +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +self.ability.extra.h_size = self.ability.extra.h_size - self.ability.extra.h_mod +G.hand:change_size(- self.ability.extra.h_mod) +return { + message = localize{type='variable',key='a_handsize_minus',vars={self.ability.extra.h_mod}}, + colour = G.C.FILTER +} +''' +position = 'at' +match_indent = true +payload = ''' +SMODS.scale_card(self, { + ref_table = self.ability.extra, + ref_value = "h_size", + scalar_value = "h_mod", + message_key = 'a_handsize_minus', + operation = function(ref_table, ref_value, initial, change) + ref_table[ref_value] = initial - change + G.hand:change_size(- change) + end +}) +''' + +# Popcorn +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +self.ability.mult = self.ability.mult - self.ability.extra +return { + message = localize{type='variable',key='a_mult_minus',vars={self.ability.extra}}, + colour = G.C.MULT +} +''' +position = 'at' +match_indent = true +payload = ''' +SMODS.scale_card(self, { + ref_table = self.ability, + ref_value = "mult", + scalar_value = "extra", + message_key = 'a_mult_minus', + colour = G.C.MULT, + operation = '-' +}) +''' + +# Ramen +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +self.ability.x_mult = self.ability.x_mult - self.ability.extra +return { + delay = 0.2, + card = self, + message = localize{type='variable',key='a_xmult_minus',vars={self.ability.extra}}, + colour = G.C.RED +} +''' +position = 'at' +match_indent = true +payload = ''' +SMODS.scale_card(self, { + ref_table = self.ability, + ref_value = "x_mult", + scalar_value = "extra", + operation = "-", + message_key = 'a_xmult_minus', + colour = G.C.RED +}) +''' + +# Yorick +[[patches]] +[patches.pattern] +target = "card.lua" +pattern = ''' +self.ability.x_mult = self.ability.x_mult + self.ability.extra.xmult +return { + card = self, + delay = 0.2, + message = localize{type='variable',key='a_xmult',vars={self.ability.x_mult}}, + colour = G.C.RED +} +''' +position = 'at' +match_indent = true +payload = ''' +SMODS.scale_card(self, { + ref_table = self.ability, + ref_value = "x_mult", + scalar_table = self.ability.extra, + scalar_value = "xmult", + message_key = 'a_xmult', + message_colour = G.C.RED +}) +''' + +# Canio +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = ''' +self.ability.caino_xmult = self.ability.caino_xmult + face_cards*self.ability.extra +G.E_MANAGER:add_event(Event({ +func = function() card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize{type = 'variable', key = 'a_xmult', vars = {self.ability.caino_xmult}}}); return true +end})) +''' +payload = ''' +SMODS.scale_card(self, { + ref_table = self.ability, + ref_value = 'caino_xmult', + scalar_value = 'extra', + operation = function(ref_table, ref_value, initial, change) + ref_table[ref_value] = initial + face_cards*change + end, + message_key = 'a_xmult' +}) +''' + +# Glass Joker +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'at' +pattern = ''' +G.E_MANAGER:add_event(Event({ + func = function() + self.ability.x_mult = self.ability.x_mult + self.ability.extra*glass_cards + return true + end +})) +card_eval_status_text(self, 'extra', nil, nil, nil, {message = localize{type = 'variable', key = 'a_xmult', vars = {self.ability.x_mult + self.ability.extra*glass_cards}}}) +''' +payload = ''' +SMODS.scale_card(self, { + ref_table = self.ability, + ref_value = 'x_mult', + scalar_value = 'extra', + operation = function(ref_table, ref_value, initial, change) + ref_table[ref_value] = initial + glass_cards*change + end, + message_key = 'a_xmult' +}) +''' diff --git a/Steamodded/lovely/scoring_calculation.toml b/Steamodded/lovely/scoring_calculation.toml new file mode 100644 index 0000000..cf5175f --- /dev/null +++ b/Steamodded/lovely/scoring_calculation.toml @@ -0,0 +1,308 @@ +[manifest] +version = "1.0.0" +dump_lua = true +priority = -10 + +[[patches]] +[patches.regex] +target = "functions/state_events.lua" +pattern = "^(.*)hand_chips\\s*\\*\\s*mult(.*)$" +position = "at" +payload = '''$1 SMODS.calculate_round_score() $2''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = "G.ARGS.score_intensity.earned_score = G.GAME.current_round.current_hand.chips*G.GAME.current_round.current_hand.mult" +position = "at" +payload = '''G.ARGS.score_intensity.earned_score = SMODS.calculate_round_score(true)''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = '''contents.hand =''' +position = "before" +payload = '''--[[''' +match_indent = false + +# Replace contexts.hand +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +match_indent = true +position = 'before' +pattern = ''' +contents.dollars_chips = {n=G.UIT.R, config={align = "cm",r=0.1, padding = 0,colour = G.C.DYN_UI.BOSS_MAIN, emboss = 0.05, id = 'row_dollars_chips'}, nodes={ +''' +payload = ''' +--]] +contents.hand = SMODS.GUI.hand_score_display_ui(scale) +''' + +# Add operator set up/loading +[[patches]] +[patches.pattern] +target = 'game.lua' +match_indent = true +position = 'after' +pattern = ''' +self.GAME.selected_back_key = selected_back +''' +payload = ''' + +if saveTable then + self.GAME.current_scoring_calculation = SMODS.Scoring_Calculations[saveTable.SCORING_CALC.key]:load({ + config = saveTable.SCORING_CALC.config + }) +else + self.GAME.current_scoring_calculation = SMODS.Scoring_Calculations['multiply']:new() +end +''' + +# Operator saving +[[patches]] +[patches.pattern] +target = 'functions/misc_functions.lua' +match_indent = true +position = 'after' +pattern = ''' +BLIND = G.GAME.blind:save(), +''' +payload = ''' +SCORING_CALC = G.GAME.current_scoring_calculation:save(), +''' + +# UIElement remove functions +[[patches]] +[patches.pattern] +target = 'engine/ui.lua' +match_indent = true +position = 'before' +pattern = ''' +if self == G.CONTROLLER.text_input_hook then +''' +payload = ''' +if self.config and self.config.func then + self.config.func = nil +end + +''' + +# Add Scoring_Parameters to update_hand_text +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +match_indent = true +position = 'before' +pattern = ''' +if vals.handname and G.GAME.current_round.current_hand.handname ~= vals.handname then +''' +payload = ''' +for name, parameter in pairs(SMODS.Scoring_Parameters) do + if vals[name] and G.GAME.current_round.current_hand[name] ~= vals[name] then + local delta = (type(vals[name]) == 'number' and type(G.GAME.current_round.current_hand[name]) == 'number') and (vals[name] - G.GAME.current_round.current_hand[name]) or 0 + if delta < 0 then delta = ''..delta; col = G.C.RED + elseif delta > 0 then delta = '+'..delta + else delta = ''..delta + end + if type(vals[name]) == 'string' then delta = vals[name] end + G.GAME.current_round.current_hand[name] = vals[name] + G.hand_text_area[name] = G.hand_text_area[name] or G.HUD:get_UIE_by_ID('hand_'..name..'_area') or nil + if G.hand_text_area[name] then + G.hand_text_area[name]:update(0) + if vals.StatusText then + attention_text({ + text =delta, + scale = 0.8, + hold = 1, + cover = G.hand_text_area[name].parent, + cover_colour = mix_colours(parameter.colour, col, 0.1), + emboss = 0.05, + align = 'cm', + cover_align = 'cm' + }) + end + end + end +end +''' + +# Reset other values +[[patches]] +[patches.pattern] +target = 'cardarea.lua' +match_indent = true +position = 'after' +pattern = ''' +update_hand_text({immediate = true, nopulse = true, delay = 0}, {mult = 0, chips = 0, level = '', handname = ''}) +''' +payload = ''' +for name, parameter in pairs(SMODS.Scoring_Parameters) do + update_hand_text({immediate = true, nopulse = true, delay = 0}, {[name] = parameter.default_value}) +end +''' + +# Reset display after hand played +[[patches]] +[patches.pattern] +target = 'functions/state_events.lua' +match_indent = true +position = 'before' +pattern = ''' +check_and_set_high_score('hand', hand_chips*mult) +''' +payload = ''' +for name, parameter in pairs(SMODS.Scoring_Parameters) do + update_hand_text({delay = 0}, {[name] = parameter.default_value}) +end +''' + +# Set based on hand selected +[[patches]] +[patches.pattern] +target = 'cardarea.lua' +match_indent = true +position = 'before' +pattern = ''' +update_hand_text({immediate = true, nopulse = nil, delay = 0}, {handname=disp_text, level=G.GAME.hands[text].level, mult = G.GAME.hands[text].mult, chips = G.GAME.hands[text].chips}) +''' +payload = ''' +for name, parameter in pairs(SMODS.Scoring_Parameters) do + parameter.current = G.GAME.hands[text][name] or parameter.default_value + update_hand_text({immediate = true, nopulse = nil, delay = 0}, {[name] = parameter.current}) +end +''' + +# Reset values after hand played +[[patches]] +[patches.pattern] +target = 'functions/state_events.lua' +match_indent = false +position = 'after' +pattern = ''' + func = (function() G.GAME.current_round.current_hand.handname = '';return true end) +})) +delay(0.3) +''' +payload = ''' + SMODS.last_hand_oneshot = SMODS.calculate_round_score() > G.GAME.blind.chips + G.E_MANAGER:add_event(Event({ + trigger = 'immediate', + func = (function() + for name, parameter in pairs(SMODS.Scoring_Parameters) do + parameter.current = parameter.default_value + end + return true + end) + })) + +''' + +# Level Up Hand uses scoring parameters +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +match_indent = true +position = 'at' +pattern = ''' +G.GAME.hands[hand].mult = math.max(G.GAME.hands[hand].s_mult + G.GAME.hands[hand].l_mult*(G.GAME.hands[hand].level - 1), 1) +G.GAME.hands[hand].chips = math.max(G.GAME.hands[hand].s_chips + G.GAME.hands[hand].l_chips*(G.GAME.hands[hand].level - 1), 0) +''' +payload = ''' +for name, parameter in pairs(SMODS.Scoring_Parameters) do + if G.GAME.hands[hand][name] then parameter:level_up_hand(amount, G.GAME.hands[hand]) end +end +''' + +# Face down hands +[[patches]] +[patches.pattern] +target = 'cardarea.lua' +match_indent = true +position = 'after' +pattern = ''' +update_hand_text({immediate = true, nopulse = nil, delay = 0}, {handname='????', level='?', mult = '?', chips = '?'}) +''' +payload = ''' +for name, parameter in pairs(SMODS.Scoring_Parameters) do + update_hand_text({immediate = true, nopulse = nil, delay = 0}, {[name] = '?'}) +end +''' + +# Handle flame_handler +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +match_indent = true +position = 'at' +pattern = ''' +G.C.UI_CHIPLICK = G.C.UI_CHIPLICK or {1, 1, 1, 1} + G.C.UI_MULTLICK = G.C.UI_MULTLICK or {1, 1, 1, 1} + for i=1, 3 do + G.C.UI_CHIPLICK[i] = math.min(math.max(((G.C.UI_CHIPS[i]*0.5+G.C.YELLOW[i]*0.5) + 0.1)^2, 0.1), 1) + G.C.UI_MULTLICK[i] = math.min(math.max(((G.C.UI_MULT[i]*0.5+G.C.YELLOW[i]*0.5) + 0.1)^2, 0.1), 1) + end + + G.ARGS.flame_handler = G.ARGS.flame_handler or { + chips = { + id = 'flame_chips', + arg_tab = 'chip_flames', + colour = G.C.UI_CHIPS, + accent = G.C.UI_CHIPLICK + }, + mult = { + id = 'flame_mult', + arg_tab = 'mult_flames', + colour = G.C.UI_MULT, + accent = G.C.UI_MULTLICK + } + } +''' +payload = ''' +G.ARGS.flame_handler = G.ARGS.flame_handler or {} + +for key, parameter in pairs(SMODS.Scoring_Parameters) do + for i=1, 3 do + parameter.lick[i] = math.min(math.max(((parameter.colour[i]*0.5+G.C.YELLOW[i]*0.5) + 0.1)^2, 0.1), 1) + end + G.ARGS.flame_handler[key] = G.ARGS.flame_handler[key] or parameter:flame_handler() +end +''' +# pt2 +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +match_indent = true +position = 'at' +pattern = ''' +e.config.object = Sprite(0, 0, 2.5, 2.5, G.ASSET_ATLAS["ui_1"], {x = 2, y = 0}) +''' +payload = ''' +e.config.object = Sprite(0, 0, e.config._w, e.config._h, G.ASSET_ATLAS["ui_1"], {x = 2, y = 0}) +''' + +# Patch mod_chips/mod_mult +[[patches]] +[patches.pattern] +target = 'functions/misc_functions.lua' +match_indent = true +position = 'before' +pattern = ''' +return _mult +''' +payload = ''' +SMODS.Scoring_Parameters.mult:modify(nil, _mult - (mult or 0)) +''' +[[patches]] +[patches.pattern] +target = 'functions/misc_functions.lua' +match_indent = true +position = 'before' +pattern = ''' +return _chips +''' +payload = ''' +SMODS.Scoring_Parameters.chips:modify(nil, _chips - (hand_chips or 0)) +''' diff --git a/Steamodded/lovely/seal.toml b/Steamodded/lovely/seal.toml index 62054ea..cbff000 100644 --- a/Steamodded/lovely/seal.toml +++ b/Steamodded/lovely/seal.toml @@ -22,22 +22,7 @@ pattern = ''' position = 'at' line_prepend = '$indent' payload = ''' -card:set_seal(SMODS.poll_seal({mod = 10}))''' - -# Card:calculate_joker() -[[patches]] -[patches.regex] -target = 'card.lua' -pattern = ''' -(?[\t ]*)local seal_type = pseudorandom\(pseudoseed\('certsl'\)\) -[\n\t ]*if seal_type > 0.75 then _card:set_seal\('Red', true\) -[\n\t ]*elseif seal_type > 0.5 then _card:set_seal\('Blue', true\) -[\n\t ]*elseif seal_type > 0.25 then _card:set_seal\('Gold', true\) -[\n\t ]*else _card:set_seal\('Purple', true\) -[\n\t ]*end''' -position = 'at' -line_prepend = '$indent' -payload = '''_card:set_seal(SMODS.poll_seal({guaranteed = true, type_key = 'certsl'}))''' +card:set_seal(SMODS.poll_seal({mod = 10}), true, true)''' # get_badge_colour() [[patches]] @@ -84,17 +69,22 @@ if obj.update and type(obj.update) == 'function' then end''' # Card:get_p_dollars() +# Also, Gold Seal respects quantum enhancements +# Patch is here to avoid conflict [[patches]] [patches.regex] target = "card.lua" -pattern = '''(?[\t ]*)if (?self\.seal == 'Gold' then\n)''' +pattern = '''(?[\t ]*)if self\.seal == 'Gold' then''' position = 'at' line_prepend = '$indent' payload = ''' local obj = G.P_SEALS[self.seal] or {} if obj.get_p_dollars and type(obj.get_p_dollars) == 'function' then ret = ret + obj:get_p_dollars(self) -elseif $cond''' +elseif self.seal == 'Gold' and not self.ability.extra_enhancement then''' +# note for later: the Card:get_xxx functions sometimes take context and sometimes don't, +# which is annoying for enhancements +# this should probably be changed to be consistent in better calc # generate_card_ui() [[patches]] @@ -106,7 +96,14 @@ position = 'before' payload = ''' local seal = G.P_SEALS[v] or G.P_SEALS[SMODS.Seal.badge_to_key[v] or ''] if seal then - info_queue[#info_queue+1] = seal + local t = {key = v, set = 'Other', config = {}} + info_queue[#info_queue + 1] = t + if seal.loc_vars and type(seal.loc_vars) == 'function' then + local res = seal:loc_vars(info_queue, card) or {} + t.vars = res.vars + t.key = res.key or t.key + t.set = res.set or t.set + end else''' [[patches]] [patches.pattern] @@ -186,7 +183,9 @@ target = 'card.lua' pattern = '''play_sound('gold_seal', 1.2, 0.4)''' position = 'at' match_indent = true -payload = '''play_sound(sound.sound, sound.per, sound.vol)''' +payload = ''' +self.ability.delay_seal = false +play_sound(sound.sound, sound.per, sound.vol)''' ## Populate Seal Ability Table [[patches]] [patches.pattern] @@ -203,8 +202,27 @@ for k, v in pairs(G.P_SEALS[_seal].config or {}) do self.ability.seal[k] = v end end + +self.ability.delay_seal = not silent ''' +# card_limit support +[[patches]] +[patches.pattern] +target = 'card.lua' +match_indent = true +position = 'before' +pattern = ''' +end + if self.ability.name == 'Gold Card' and self.seal == 'Gold' and self.playing_card then +''' +payload = ''' + self.ability.card_limit = self.ability.card_limit + (self.ability.seal.card_limit or 0) + self.ability.extra_slots_used = self.ability.extra_slots_used + (self.ability.seal.extra_slots_used or 0) + if self.area then self.area:handle_card_limit(self.ability.seal.card_limit, self.ability.seal.extra_slots_used) end +''' + + [[patches]] [patches.pattern] target = 'functions/common_events.lua' @@ -221,4 +239,4 @@ if other.seal then end end end -''' \ No newline at end of file +''' diff --git a/Steamodded/lovely/shop.toml b/Steamodded/lovely/shop.toml index fa8c4f2..8adf718 100644 --- a/Steamodded/lovely/shop.toml +++ b/Steamodded/lovely/shop.toml @@ -105,10 +105,10 @@ target = 'card.lua' match_indent = true position = 'at' pattern = ''' -if self.shop_voucher then G.GAME.current_round.voucher = nil end +if self.shop_voucher then G.GAME.current_round.voucher = nil end ''' payload = ''' -if self.shop_voucher then G.GAME.current_round.voucher.spawn[self.config.center_key] = false end +if self.shop_voucher then G.GAME.current_round.voucher.spawn[self.config.center_key] = false end if self.from_tag then G.GAME.current_round.voucher.spawn[G.GAME.current_round.voucher[1]] = false end ''' [[patches]] @@ -148,7 +148,6 @@ card.from_tag = true ''' - # Free Rerolls [[patches]] [patches.pattern] @@ -235,3 +234,20 @@ payload = ''' self.shop_voucher = cardTable.shop_voucher ''' match_indent = true + +# poll_edition for playing cards in shop +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +pattern = ''' +local edition_poll = pseudorandom(pseudoseed('illusion')) +local edition = {} +if edition_poll > 1 - 0.15 then edition.polychrome = true +elseif edition_poll > 0.5 then edition.holo = true +else edition.foil = true +end +card:set_edition(edition) +''' +position = 'at' +match_indent = true +payload = '''card:set_edition(poll_edition('illusion', nil, true, true))''' diff --git a/Steamodded/lovely/stake.toml b/Steamodded/lovely/stake.toml index 839175f..66d8514 100644 --- a/Steamodded/lovely/stake.toml +++ b/Steamodded/lovely/stake.toml @@ -123,7 +123,7 @@ match_indent = true target = "functions/misc_functions.lua" pattern = 'function get_blind_amount(ante)' position = "after" -payload = '''if G.GAME.modifiers.scaling and G.GAME.modifiers.scaling > 3 then return SMODS.get_blind_amount(ante) end''' +payload = '''if G.GAME.modifiers.scaling and (G.GAME.modifiers.scaling ~= 1 and G.GAME.modifiers.scaling ~= 2 and G.GAME.modifiers.scaling ~= 3) then return SMODS.get_blind_amount(ante) end''' match_indent = true # set_joker_usage @@ -188,3 +188,39 @@ pattern = 'G.viewed_stake = math.min(max_stake+1, G.viewed_stake)' position = "after" payload = '''if G.viewed_stake > #G.P_CENTER_POOLS.Stake then G.viewed_stake = #G.P_CENTER_POOLS.Stake end''' match_indent = true + +# Fix stake select in run start +[[patches]] +[patches.pattern] +target = 'functions/button_callbacks.lua' +match_indent = true +position = 'at' +pattern = ''' +local max_stake = get_deck_win_stake(G.GAME.viewed_back.effect.center.key) or 0 +G.viewed_stake = math.min(G.viewed_stake, max_stake + 1) +''' +payload = ''' +-- local max_stake = get_deck_win_stake(G.GAME.viewed_back.effect.center.key) or 0 +-- G.viewed_stake = math.min(G.viewed_stake, max_stake + 1) +''' + +# pt 2 +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +match_indent = true +position = 'at' +pattern = ''' +local max_stake = get_deck_win_stake(G.GAME.viewed_back.effect.center.key) +if G.PROFILES[G.SETTINGS.profile].all_unlocked then max_stake = #G.P_CENTER_POOLS['Stake'] end + +G.viewed_stake = math.min(max_stake+1, G.viewed_stake) +''' +payload = ''' +--[[ +local max_stake = get_deck_win_stake(G.GAME.viewed_back.effect.center.key) +if G.PROFILES[G.SETTINGS.profile].all_unlocked then max_stake = #G.P_CENTER_POOLS['Stake'] end + +G.viewed_stake = math.min(max_stake+1, G.viewed_stake) +]]-- +''' diff --git a/Steamodded/lovely/tag.toml b/Steamodded/lovely/tag.toml index 7a885e3..7d878fd 100644 --- a/Steamodded/lovely/tag.toml +++ b/Steamodded/lovely/tag.toml @@ -5,6 +5,7 @@ priority = -10 ### Tag API # Tag:apply_to_run() +# Adds prevent_tag_trigger context [[patches]] [patches.pattern] target = "tag.lua" @@ -13,6 +14,8 @@ position = 'after' match_indent = true payload = ''' if self.triggered then return end + local flags = SMODS.calculate_context({prevent_tag_trigger = self, other_context = _context}) + if flags.prevent_trigger then return end local obj = SMODS.Tags[self.key] local res if obj and obj.apply and type(obj.apply) == 'function' then diff --git a/Steamodded/lovely/ui.toml b/Steamodded/lovely/ui.toml index fa6714a..48591f8 100644 --- a/Steamodded/lovely/ui.toml +++ b/Steamodded/lovely/ui.toml @@ -35,7 +35,25 @@ line_prepend = '$indent' target = "functions/UI_definitions.lua" pattern = '''local t = create_UIBox_generic_options({ back_func = 'your_collection', contents = {''' position = "at" -payload = '''local t = create_UIBox_generic_options({ back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or 'your_collection', contents = {''' +payload = '''local t = create_UIBox_generic_options({ +colour = G.ACTIVE_MOD_UI and ((G.ACTIVE_MOD_UI.ui_config or {}).collection_colour or + (G.ACTIVE_MOD_UI.ui_config or {}).colour), +bg_colour = G.ACTIVE_MOD_UI and ((G.ACTIVE_MOD_UI.ui_config or {}).collection_bg_colour or + (G.ACTIVE_MOD_UI.ui_config or {}).bg_colour), +back_colour = G.ACTIVE_MOD_UI and ((G.ACTIVE_MOD_UI.ui_config or {}).collection_back_colour or + (G.ACTIVE_MOD_UI.ui_config or {}).back_colour), +outline_colour = G.ACTIVE_MOD_UI and ((G.ACTIVE_MOD_UI.ui_config or {}).collection_outline_colour or + (G.ACTIVE_MOD_UI.ui_config or {}).outline_colour), +back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or 'your_collection', contents = {''' +match_indent = true + +# create_UIBox_your_collection_decks() +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = '''create_option_cycle({options = ordered_names, opt_callback = 'change_viewed_back', current_option = 1, colour = G.C.RED, w = 4.5, focus_args = {snap_to = true}, mid = ''' +position = "at" +payload = '''create_option_cycle({options = ordered_names, opt_callback = 'change_viewed_back', current_option = 1, colour = G.ACTIVE_MOD_UI and (G.ACTIVE_MOD_UI.ui_config or {}).collection_option_cycle_colour or G.C.RED, w = 4.5, focus_args = {snap_to = true}, mid = ''' match_indent = true # G.FUNCS.your_collection_deck_page @@ -83,46 +101,12 @@ target = 'engine/controller.lua' pattern = "function Controller:key_press_update(key, dt)" position = "after" payload = ''' - if key == "escape" and G.ACTIVE_MOD_UI then + if key == "escape" and (G.ACTIVE_MOD_UI or SMODS.IN_MODS_TAB) then G.FUNCS.exit_mods() end ''' match_indent = true -[[patches]] -[patches.regex] -target = 'functions/UI_definitions.lua' -position = 'before' -line_prepend = '$indent' -pattern = ''' -(?[\t ]*)return \{n=G\.UIT\.ROOT, config = \{align = 'cm', colour = G\.C\.CLEAR\}, nodes=\{ -[\t ]*\{n=G\.UIT\.C,''' -payload = ''' -local cols -if #info_boxes <= 3 then - cols = 1 -elseif #info_boxes <= 10 then - cols = 2 -elseif #info_boxes <= 24 then - cols = 3 -else - cols = 4 -end -local nodes_per_col = math.ceil(#info_boxes/cols) -local info_cols = {} -for i = 0, cols-1 do - local col = {} - for j = 1, nodes_per_col do - local info_box = info_boxes[i*nodes_per_col+j] - if info_box then - table.insert(col, info_box) - else break end - end - table.insert(info_cols, {n=G.UIT.C, config = {align="cm"}, nodes = col}) -end -info_boxes = {{n=G.UIT.R, config = {align="cm", padding = 0.05, card_pos = card.T.x }, nodes = info_cols}} -''' - [[patches]] [patches.pattern] target = 'functions/button_callbacks.lua' @@ -191,6 +175,15 @@ position = 'at' pattern = "if not v.omit then" payload = "if not v.omit and not v.no_collection then" +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = "if v.set == 'Joker' then" +position = "at" +payload = "if v.set == 'Joker' and not v.no_collection and not v.omit then " +match_indent = true +times = 1 + [[patches]] [patches.regex] target = 'functions/misc_functions.lua' @@ -248,4 +241,166 @@ target = 'functions/misc_functions.lua' match_indent = true position = 'at' pattern = 'colour = loc_colour(part.control.C or nil),' -payload = 'colour = part.control.V and args.vars.colours[tonumber(part.control.V)] or loc_colour(part.control.C or nil),' \ No newline at end of file +payload = 'colour = part.control.V and args.vars.colours[tonumber(part.control.V)] or loc_colour(part.control.C or nil),' + +[[patches]] +[patches.pattern] +target = "functions/common_events.lua" +pattern = ''' +G.E_MANAGER:add_event(Event({ --Add bonus chips from this card + trigger = 'before', + delay = delay, +''' +position = "at" +payload = ''' +G.E_MANAGER:add_event(Event({ --Add bonus chips from this card + trigger = trigger, + delay = delay, + blocking = blocking, + blockable = blockable, +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/UI_definitions.lua" +pattern = ''' if args.info then + t = {n=args.col and G.UIT.C or G.UIT.R, config={align = "cm"}, nodes={''' +position = "before" +payload = """if args.hide_label then + local t2 = {} + for i = 1, #t.nodes do + if i ~= 1 then table.insert(t2, t.nodes[i]) end + end + t.nodes = t2 +end""" +match_indent = true + +# UIBox_button(): +# the counters on collection buttons use text_colour instead of being hardcoded to white +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +pattern = "{n=G.UIT.T, config={scale = 0.35,text = args.count.tally..' / '..args.count.of, colour = {1,1,1,0.9}}}" +position = "at" +match_indent = true +payload = "{n=G.UIT.T, config={scale = 0.35,text = args.count.tally..' / '..args.count.of, colour = args.text_colour}}" + +# G.UIDEF.card_h_popup(): +# add a "card_type_text_colour" variable +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +pattern = 'local card_type_colour = get_type_colour(card.config.center or card.config, card)' +position = 'after' +match_indent = true +payload = 'local card_type_text_colour = (AUT.card_type and SMODS.ConsumableTypes[AUT.card_type] and SMODS.ConsumableTypes[AUT.card_type].text_colour) or G.C.UI.TEXT_LIGHT' + +# G.UIDEF.card_h_popup(): +# pass "card_type_text_colour" variable to create_badge() when creating the badge for a card type +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +pattern = "badges[#badges + 1] = create_badge(((card.ability.name == 'Pluto' or card.ability.name == 'Ceres' or card.ability.name == 'Eris') and localize('k_dwarf_planet')) or (card.ability.name == 'Planet X' and localize('k_planet_q') or card_type),card_type_colour, nil, 1.2)" +position = 'at' +match_indent = true +payload = "badges[#badges + 1] = create_badge(((card.ability.name == 'Pluto' or card.ability.name == 'Ceres' or card.ability.name == 'Eris') and localize('k_dwarf_planet')) or (card.ability.name == 'Planet X' and localize('k_planet_q') or card_type), card_type_colour, card_type_text_colour, 1.2)" + +# Fixing description error when info_queue has multi-box descriptions. + + +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = ''' +generate_card_ui(v, full_UI_table) +''' +position = "at" +payload = ''' +generate_card_ui(v, full_UI_table, {is_info_queue = true}) +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = 'functions/misc_functions.lua' +pattern = ''' +bump = true, +silent = true, +pop_in = 0, +pop_in_rate = 4, +maxw = 5, +shadow = true, +y_offset = -0.6, +''' +position = "at" +payload = ''' +bump = not args.no_bump, +silent = not args.no_silent, +pop_in = (not args.no_pop_in and (args.pop_in or 0)) or nil, +pop_in_rate = (not args.no_pop_in and (args.pop_in_rate or 4)) or nil, +maxw = args.maxw or 5, +shadow = not args.no_shadow, +y_offset = args.y_offset or -0.6,''' +match_indent = true + +[[patches]] +[patches.pattern] +target = 'functions/common_events.lua' +pattern = ''' +desc_nodes.name = localize{type = 'name_text', key = name_override or _c.key, set = name_override and 'Other' or _c.set} +''' +position = "after" +payload = ''' +local set = name_override and "Other" or _c.set +local key = name_override or _c.key +if set == "Seal" then + if G.localization.descriptions["Other"][_c.key.."_seal"] then set = "Other"; key = key.."_seal" end +else + if not G.localization.descriptions[set][_c.key] then set = "Other" end +end +desc_nodes.loc_name = {} +localize{type = 'name', key = key, set = set, nodes = desc_nodes.loc_name, fixed_scale = 0.63, no_pop_in = true, no_shadow = true, y_offset = 0, no_spacing = true, no_bump = true, vars = (_c.create_fake_card and _c.loc_vars and (_c:loc_vars({}, _c:create_fake_card()) or {}).vars) or {colours = {}}} +desc_nodes.loc_name = SMODS.info_queue_desc_from_rows(desc_nodes.loc_name, true) +desc_nodes.loc_name.config.align = "cm" +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +pattern = ''' +function info_tip_from_rows(desc_nodes, name) +''' +position = "after" +payload = ''' + local name_nodes = {} + local function deep_find(t, index) + if t[index] then return true end + for i,v in pairs(t) do + if i == index then return true end + if type(v) == "table" then + return deep_find(v, index) + end + end + return false + end + if not desc_nodes.loc_name or not deep_find(desc_nodes.loc_name, "object") then + name_nodes = {{n=G.UIT.T, config={text = name, scale = 0.32, colour = G.C.UI.TEXT_LIGHT}}} + else + name_nodes = {desc_nodes.loc_name} + end +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +pattern = ''' +{n=G.UIT.R, config={align = "tm", minh = 0.36, padding = 0.03}, nodes={{n=G.UIT.T, config={text = name, scale = 0.32, colour = G.C.UI.TEXT_LIGHT}}}}, +''' +position = "at" +payload = ''' +{n=G.UIT.R, config={align = "tm", minh = 0.36, padding = 0.03}, nodes=name_nodes}, +''' +match_indent = true diff --git a/Steamodded/lovely/ui_additional_text_props.toml b/Steamodded/lovely/ui_additional_text_props.toml new file mode 100644 index 0000000..9b342d2 --- /dev/null +++ b/Steamodded/lovely/ui_additional_text_props.toml @@ -0,0 +1,361 @@ +[manifest] +version = "1.2" +dump_lua = true +priority = -10 + +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = """spacing = math.max(0, 0.32*(17 - #assembled_string)),""" +position = "after" +payload = """font = SMODS.Fonts[part.control.f] or G.FONTS[tonumber(part.control.f)],""" +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = """spacing = _spacing,""" +position = "after" +payload = """font = SMODS.Fonts[part.control.f] or G.FONTS[tonumber(part.control.f)],""" +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = """text = assembled_string,""" +position = "after" +payload = """font = SMODS.Fonts[part.control.f] or G.FONTS[tonumber(part.control.f)],""" +match_indent = true + +# descsacle +[[patches]] +[patches.pattern] +target = 'functions/misc_functions.lua' +match_indent = true +position = 'at' +pattern = ''' +local desc_scale = G.LANG.font.DESCSCALE +''' +payload = ''' +local desc_scale = (SMODS.Fonts[part.control.f] or G.FONTS[tonumber(part.control.f)] or G.LANG.font).DESCSCALE +''' + + +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = """loc_target = G.localization.descriptions[(args.set or args.node.config.center.set)][args.key or args.node.config.center.key]""" +position = "at" +payload = """ +loc_target = loc_target or {} +if pcall(function() loc_target.name_parsed = {loc_parse_string(G.localization.descriptions[(args.set or args.node.config.center.set)][args.key or args.node.config.center.key].name)} end) then +else loc_target.name_parsed = {} end""" +match_indent = true + +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = """if ret_string then return ret_string end""" +position = "before" +payload = """if ret_string and type(ret_string) == 'string' then ret_string = string.gsub(ret_string, "{.-}", "") end""" +match_indent = true + +# Replace all instances of the language font +[[patches]] +[patches.regex] +target = "engine/ui.lua" +pattern = ''' +self.config.lang.font''' +position = "at" +payload = '''(self.config.font or self.config.lang.font)''' +line_prepend = "$indent" + +[[patches]] +[patches.regex] +target = "engine/ui.lua" +pattern = ''' +node.config.lang.font''' +position = "at" +payload = '''(node.config.font or node.config.lang.font)''' +line_prepend = "$indent" + +# Fix name scale when using formatting +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = ''' +local final_line = {} +''' +position = 'after' +match_indent = true +payload = ''' +local final_name_assembled_string = '' +if args.type == 'name' and loc_target.name_parsed then + for _, part in ipairs(lines) do + local assembled_string_part = '' + for _, subpart in ipairs(part.strings) do + assembled_string_part = assembled_string_part..(type(subpart) == 'string' and subpart or format_ui_value(args.vars[tonumber(subpart[1])]) or 'ERROR') + end + final_name_assembled_string = final_name_assembled_string..assembled_string_part + end +end +''' + +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = ''' +spacing = math.max(0, 0.32*(17 - #assembled_string)), +''' +position = 'at' +match_indent = true +payload = ''' +spacing = (not args.no_spacing and math.max(0, 0.32*(17 - #(final_name_assembled_string or assembled_string)))) or nil, +''' + +[[patches]] +[patches.pattern] +target = 'functions/misc_functions.lua' +position = 'at' +match_indent = true +pattern = 'scale = (0.55 - 0.004*#assembled_string)*(part.control.s and tonumber(part.control.s) or 1)' +payload = 'scale = (0.55 - 0.004*#(final_name_assembled_string or assembled_string))*(part.control.s and tonumber(part.control.s) or 1)*(args.fixed_scale or 1)' + +# Add support for multi line name +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = ''' +if pcall(function() loc_target.name_parsed = {loc_parse_string(G.localization.descriptions[(args.set or args.node.config.center.set)][args.key or args.node.config.center.key].name)} end) then +''' +position = 'at' +match_indent = true +payload = ''' +if pcall(function() +local name = G.localization.descriptions[(args.set or args.node.config.center.set)][args.key or args.node.config.center.key] +loc_target.name_parsed = name.name_parsed or {loc_parse_string(name.name)} +end) then +''' + +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = ''' +if pcall(function() ret_string = G.localization.descriptions[(args.set or args.node.config.center.set)][args.key or args.node.config.center.key].name end) then +''' +position = 'at' +match_indent = true +payload = ''' +if pcall(function() + local name_text = G.localization.descriptions[(args.set or args.node.config.center.set)][args.key or args.node.config.center.key].name + if type(name_text) == "table" then + ret_string = "" + for i, line in ipairs(name_text) do + ret_string = ret_string.. (i ~= 1 and " " or "")..line + end + else + ret_string = name_text + end +end) then +''' + +[[patches]] +[patches.pattern] +target = "functions/misc_functions.lua" +pattern = ''' + if args.type == 'name' or args.type == 'text' then return final_line end + args.nodes[#args.nodes+1] = final_line +end +''' +position = 'at' +match_indent = true +payload = ''' + if args.type == 'text' then return final_line end + if not args.nodes and args.type == 'name' then args.nodes = {} end + args.nodes[#args.nodes+1] = final_line +end +if args.type == 'name' then + local final_name = {} + + for _, line in ipairs(args.nodes or {}) do + final_name[#final_name+1] = {n=G.UIT.R, config={align = "m"}, nodes=line} + end + + return final_name +end +''' + +# Marquee text in DynaText +# Adjust width when marquee is enabled +[[patches]] +[patches.pattern] +target = 'engine/text.lua' +match_indent = true +position = 'at' +pattern = ''' +if self.strings[k].W > self.config.W then self.config.W = self.strings[k].W; self.strings[k].W_offset = 0 end +''' +payload = ''' +if self.strings[k].W > self.config.W then + self.config.W = self.strings[k].W + self.strings[k].W_offset = 0 + if self.config.marquee and self.config.maxw then + if self.config.W > self.config.maxw then + self.config.marquee_width = self.config.W/self.config.maxw + self.config.W = self.config.maxw + else + self.config.marquee = 'no' + end + end +end +''' +# Adjust width when marquee is enabled +[[patches]] +[patches.pattern] +target = 'engine/text.lua' +match_indent = true +position = 'at' +pattern = ''' +if self.config.maxw and self.config.W > self.config.maxw then +''' +payload = ''' +if self.config.maxw and self.config.W > self.config.maxw and not self.config.marquee then +''' +# Adjust width when marquee is enabled +[[patches]] +[patches.pattern] +target = 'engine/text.lua' +match_indent = true +position = 'at' +pattern = ''' +v.W_offset = 0.5*(self.config.W - v.W) +''' +payload = ''' +v.W_offset = 0.5*(self.config.W - (self.config.marquee and self.config.maxw and self.config.maxw < v.W and self.config.maxw or v.W)) +''' + +# Add start/end index calculation +[[patches]] +[patches.pattern] +target = 'engine/text.lua' +match_indent = true +position = 'after' +pattern = ''' +if self.children.particle_effect then self.children.particle_effect:draw() end +''' +payload = ''' +local start_index = 1 +local end_index = #self.strings[self.focused_string].letters +if self.config.marquee and self.config.marquee ~= 'no' then + local padding = math.floor(#self.strings[self.focused_string].letters / (self.config.marquee_width or 1)) - 1 + if self.dt and (self.dt - self.config.hold) / self.config.scroll_speed > (#self.strings[self.focused_string].letters + math.ceil(padding/4)) then self.dt = 0 end + if self.dt and self.dt > self.config.hold then + start_index = 1 + (math.floor((self.dt - self.config.hold) / self.config.scroll_speed) % (#self.strings[self.focused_string].letters + math.ceil(padding/4))) + end + end_index = math.min(start_index + padding, #self.strings[self.focused_string].letters) +end +''' + +# Use start/end index +[[patches]] +[patches.pattern] +target = 'engine/text.lua' +match_indent = true +position = 'at' +pattern = ''' +for k, letter in ipairs(self.strings[self.focused_string].letters) do + local real_pop_in = self.config.min_cycle_time == 0 and 1 or letter.pop_in +''' +payload = ''' +for k=start_index, end_index do + local letter = self.strings[self.focused_string].letters[k] + local real_pop_in = self.config.min_cycle_time == 0 and 1 or letter.pop_in +''' + +# Update dt +[[patches]] +[patches.pattern] +target = 'engine/text.lua' +match_indent = true +position = 'at' +pattern = ''' +function DynaText:update(dt) +''' +payload = ''' +function DynaText:update(dt, real_dt) +if self.config.marquee then + self.dt = (self.dt or 0) + real_dt +end +''' + +# Ensure hold is present +[[patches]] +[patches.pattern] +target = 'engine/text.lua' +match_indent = true +position = 'after' +pattern = ''' +self.silent = (config.silent) +''' +payload = ''' +self.config.marquee = self.config.marquee and not G.SETTINGS.reduced_motion +self.config.hold = self.config.hold or self.config.marquee and 1.5 or nil +self.config.scroll_speed = self.config.scroll_speed or self.config.marquee and 0.1 or nil +''' + +# Pass real_dt to update function +[[patches]] +[patches.pattern] +target = 'game.lua' +match_indent = true +position = 'at' +pattern = ''' +v:update(dt*self.SPEEDFACTOR) +''' +payload = ''' +v:update(dt*self.SPEEDFACTOR, self.real_dt) +''' + + +# Add underline property for text +[[patches]] +[patches.pattern] +target = 'engine/ui.lua' +match_indent = true +position = 'before' +pattern = ''' +--Draw the 'chosen triangle' +''' +payload = ''' +if self.config.underline and self.config.underline[4] > 0.01 then + prep_draw(self, 1) + love.graphics.scale(1/(G.TILESIZE)) + love.graphics.setLineWidth(1) + love.graphics.setColor(self.config.underline) + self:draw_pixellated_under('line', parallax_dist) + love.graphics.pop() +end +''' +[[patches]] +[patches.pattern] +target = 'functions/misc_functions.lua' +match_indent = true +position = 'after' +pattern = ''' +font = SMODS.Fonts[part.control.f] or G.FONTS[tonumber(part.control.f)], +''' +payload = ''' +underline = part.control.u and loc_colour(part.control.u), +''' +# DynaText compat +[[patches]] +[patches.pattern] +target = 'functions/misc_functions.lua' +match_indent = true +position = 'after' +pattern = ''' +final_line[#final_line].nodes[1] = {n=G.UIT.O, config={ +''' +payload = ''' +underline = part.control.u and loc_colour(part.control.u), +''' \ No newline at end of file diff --git a/Steamodded/lovely/ui_elements.toml b/Steamodded/lovely/ui_elements.toml index 875959b..45cf935 100644 --- a/Steamodded/lovely/ui_elements.toml +++ b/Steamodded/lovely/ui_elements.toml @@ -128,3 +128,24 @@ pattern = "if self.highlighted[1] then" position = "at" payload = "if #self.highlighted >= self.config.highlighted_limit then" match_indent = true + +# Deck unlock popup shows custom unlock descriptions +# create_UIBox_deck_unlock() +[[patches]] +[patches.pattern] +target = 'functions/UI_definitions.lua' +pattern = "if deck_center.unlock_condition.type == 'win_deck' then" +position = "before" +payload = """ +if deck_center.check_for_unlock and type(deck_center.check_for_unlock) == "function" then + local loc_args = {} + local key_override + if deck_center.locked_loc_vars and type(deck_center.locked_loc_vars) == 'function' then + local res = deck_center:locked_loc_vars() or {} + loc_args = res.vars or {} + key_override = res.key + end + localize{type = 'unlocks', key = key_override or deck_center.key, set = "Back", nodes = deck_criteria, vars = loc_args, default_col = G.C.WHITE, shadow = true} +end +""" +match_indent = true diff --git a/Steamodded/lsp_def/classes/back.lua b/Steamodded/lsp_def/classes/back.lua index 8269345..e21c420 100644 --- a/Steamodded/lsp_def/classes/back.lua +++ b/Steamodded/lsp_def/classes/back.lua @@ -17,7 +17,8 @@ ---@field take_ownership? fun(self: SMODS.Back|table, key: string, obj: SMODS.Back|table, silent?: boolean): nil|table|SMODS.Back Takes control of vanilla objects. Child class must have get_obj for this to function ---@field get_obj? fun(self: SMODS.Back|table, key: string): SMODS.Back|table? Returns an object if one matches the `key`. ---@field calculate? fun(self: SMODS.Back|table, back: Back|table, context: CalcContext|table): table?, boolean? Calculates effects based on parameters in `context`. See [SMODS calculation](https://github.com/Steamodded/smods/wiki/calculate_functions) docs for details. ----@field apply? fun(self: SMODS.Back|table, back: Back|table) Applied modifiers at the start of a run. +---@field apply? fun(self: SMODS.Back|table, back: Back|table) Applied modifiers at the start of a run. +---@field quip_filter? fun(quip: SMODS.JimboQuip|table, quip_type: string): boolean?, table? Allows configuring a quip is allowed to appear. ---@overload fun(self: SMODS.Back): SMODS.Back SMODS.Back = setmetatable({}, { __call = function(self) diff --git a/Steamodded/lsp_def/classes/blind.lua b/Steamodded/lsp_def/classes/blind.lua index 4455507..e725f56 100644 --- a/Steamodded/lsp_def/classes/blind.lua +++ b/Steamodded/lsp_def/classes/blind.lua @@ -34,9 +34,9 @@ ---@field drawn_to_hand? fun(self: SMODS.Blind|table) Handles effects when cards are drawn to hand. ---@field press_play? fun(self: SMODS.Blind|table) Handles effects when a hand is played. ---@field recalc_debuff? fun(self: SMODS.Blind|table, card: Card|table, from_blind: boolean): boolean? Determines if a card should be debuffed by this blind. ----@field debuff_hand? fun(self: SMODS.Blind|table, cards: table, hand: table, handname: string, check: nil|boolean): boolean? Determines if the hand is debuffed. +---@field debuff_hand? fun(self: SMODS.Blind|table, cards: table, hand: table, handname: PokerHands|string, check: nil|boolean): boolean? Determines if the hand is debuffed. ---@field stay_flipped? fun(self: SMODS.Blind|table, area: CardArea|table, card: Card|table): boolean? Determines if a card is drawn face down. ----@field modify_hand? fun(self: SMODS.Blind|table, cards: table, poker_hands: table, text: string, mult: number, hand_chips: number): number?, number?, boolean? Handles modifications of the base score for played poker hand. +---@field modify_hand? fun(self: SMODS.Blind|table, cards: table, poker_hands: table, text: PokerHands|string, mult: number, hand_chips: number): number?, number?, boolean? Handles modifications of the base score for played poker hand. ---@field get_loc_debuff_text? fun(self: SMODS.Blind|table): string? Handles text displayed for debuff warnings or invalid hands. ---@field loc_vars? fun(self: SMODS.Blind|table): table? Provides control over displaying the Blind descriptions. See [SMODS.Blind `loc_vars` implementation](https://github.com/Steamodded/smods/wiki/SMODS.Blind#api-methods) documentation for return value details. ---@field collection_loc_vars? fun(self: SMODS.Blind|table): table? Provides control over displaying the Blind description in the collections menu. diff --git a/Steamodded/lsp_def/classes/booster.lua b/Steamodded/lsp_def/classes/booster.lua index 89458ae..338157f 100644 --- a/Steamodded/lsp_def/classes/booster.lua +++ b/Steamodded/lsp_def/classes/booster.lua @@ -2,7 +2,7 @@ ---@class SMODS.Booster: SMODS.Center ---@field super? SMODS.Center|table Parent class. ----@field loc_txt? table|{name: string, text: string[], group_name: string} Contains strings used to display text relating to this object. +---@field loc_txt? table|{name: string|string[], text: string[]|string[][], group_name: string} Contains strings used to display text relating to this object. ---@field group_key? string Key to the group name. Grabs from `G.localization.misc.dictionary[group_key]`. ---@field draw_hand? boolean Sets if playing cards are drawn when booster pack is opened. ---@field kind? string Groups pack types together. For example, this can be used in `get_pack()` to generate a booster pack of a specific type. diff --git a/Steamodded/lsp_def/classes/center.lua b/Steamodded/lsp_def/classes/center.lua index 3f2b613..2ece9f3 100644 --- a/Steamodded/lsp_def/classes/center.lua +++ b/Steamodded/lsp_def/classes/center.lua @@ -9,7 +9,7 @@ ---@field unlocked? boolean Sets the unlock state of the center. ---@field discovered? boolean Sets the discovery state of the center. ---@field no_collection? boolean Sets whether the card shows up in the collections menu. ----@field loc_txt? table|{name: string, text: string[]} Contains strings used for displaying text related to this object. +---@field loc_txt? table|{name: string|string[], text: string[]|string[][]} Contains strings used for displaying text related to this object. ---@field pools? string[] Array of keys to ObjectTypes this center will be added to. ---@field cost? number Sell cost of this center. ---@field no_pool_flag? string Key to a pool flag defined in `G.GAME.pool_flags`. This center is removed from pools as long as this flag is `true`. @@ -38,7 +38,7 @@ ---@field locked_loc_vars? fun(self: SMODS.Center|table, info_queue: table, card: Card|table): table Provides simple control over displaying descriptions and toolips of this center when not unlocked. ---@field check_for_unlock? fun(self: SMODS.Center|table, args: table): boolean? Configures unlock conditions. See vanilla implementation of `check_for_unlock` for details on `args` parameters. ---@field set_badges? fun(self: SMODS.Center|table, card: Card|table, badges: table) Append `badges` for additional badges on the UI display of the card. To override the rarity/card type badge, see `SMODS.Center:set_card_type_badge()`. ----@field set_card_type_badge? fun(self: SMODS.Center|table, card: Card|table, badges: table) Overrides the rarity/card type badges, allowing you to Append `badges` to replace them. To add extra badges, see `SMODS.Center:sset_badges()`. +---@field set_card_type_badge? fun(self: SMODS.Center|table, card: Card|table, badges: table) Overrides the rarity/card type badges, allowing you to Append `badges` to replace them. To add extra badges, see `SMODS.Center:set_badges()`. ---@field draw? fun(self: SMODS.Center|table, card: Card|table, layer: string) Draws the sprite and shader of the card. ---@field update? fun(self: SMODS.Center|table, card: Card|table, dt: number) Allows logic for this card to be run per-frame. ---@field set_sprites? fun(self: SMODS.Center|table, card: Card|table, front?: Card|table) Used for setting and manipulating sprites of the card when created or loaded. diff --git a/Steamodded/lsp_def/classes/challenge.lua b/Steamodded/lsp_def/classes/challenge.lua index 3e7326a..a7cb6a4 100644 --- a/Steamodded/lsp_def/classes/challenge.lua +++ b/Steamodded/lsp_def/classes/challenge.lua @@ -1,30 +1,33 @@ ---@meta ---@class SMODS.Challenge: SMODS.GameObject ----@field obj_table? table Table of objects registered to this class. ----@field loc_txt? table|{name: string} Contains strings used for displaying text related to this object. ----@field super? SMODS.GameObject|table Parent class. ----@field rules? table|{custom?: table[]|{id: string, value?: any}[], modifiers?: table[]|{id: string, value?: any}} List of tables setting custom rules and modifiers. Each rule/modifier has an `id`, with optional `value` param (defaults to `true`). See [SMODS.Challenge](https://github.com/Steamodded/smods/wiki/SMODS.Challenge) Documentation for default rules/modifiers. ----@field jokers? table[]|{id: string, edition?: string, eternal?: boolean, pinned?: boolean}[] List of tables setting jokers to start with. ----@field consumeables? table[]|{id: string, edition?: string, eternal?: boolean}[] List of tables setting consumables to start with. ----@field vouchers? table[]|{id: string}[] List of tables setting vouchers to start with. ----@field restrictions? table|{banned_cards?: table[]|{id: string}[], banned_tags?: table[]|{id: string}[], banned_other?: table[]|{id: string, type: "blind"}[]} Contains IDs to objects to ban from the challenge. ----@field deck? table|{type?: string|"Challenge Deck", cards?: table[], yes_ranks?: table, yes_suits?: table, no_ranks?: table, no_suits?: table, enhancement?: string, edition?: string, seal?: string} Defines the Challenge's deck. See [SMODS.Challenge](https://github.com/Steamodded/smods/wiki/SMODS.Challenge) Documentation for details. +---@field obj_table? table Table of objects registered to this class. +---@field loc_txt? table|{name: string} Contains strings used for displaying text related to this object. +---@field super? SMODS.GameObject|table Parent class. +---@field rules? table|{custom?: table[]|{id: string, value?: any}[], modifiers?: table[]|{id: string, value?: any}} List of tables setting custom rules and modifiers. Each rule/modifier has an `id`, with optional `value` param (defaults to `true`). See [SMODS.Challenge](https://github.com/Steamodded/smods/wiki/SMODS.Challenge) Documentation for default rules/modifiers. +---@field jokers? table[]|{id: string, edition?: string, eternal?: boolean, pinned?: boolean}[] List of tables setting jokers to start with. +---@field consumeables? table[]|{id: string, edition?: string, eternal?: boolean}[] List of tables setting consumables to start with. +---@field vouchers? table[]|{id: string}[] List of tables setting vouchers to start with. +---@field restrictions? table|{banned_cards?: table[]|{id: string}[], banned_tags?: table[]|{id: string}[], banned_other?: table[]|{id: string, type: "blind"}[]} Contains IDs to objects to ban from the challenge. +---@field deck? table|{type?: string|"Challenge Deck", cards?: table[], yes_ranks?: table, yes_suits?: table, no_ranks?: table, no_suits?: table, enhancement?: string, edition?: string, seal?: string} Defines the Challenge's deck. See [SMODS.Challenge](https://github.com/Steamodded/smods/wiki/SMODS.Challenge) Documentation for details. ---@field __call? fun(self: SMODS.Challenge|table, o: SMODS.Challenge|table): nil|table|SMODS.Challenge ----@field extend? fun(self: SMODS.Challenge|table, o: SMODS.Challenge|table): table Primary method of creating a class. ----@field check_duplicate_register? fun(self: SMODS.Challenge|table): boolean? Ensures objects already registered will not register. ----@field check_duplicate_key? fun(self: SMODS.Challenge|table): boolean? Ensures objects with duplicate keys will not register. Checked on `__call` but not `take_ownership`. For take_ownership, the key must exist. ----@field register? fun(self: SMODS.Challenge|table) Registers the object. ----@field check_dependencies? fun(self: SMODS.Challenge|table): boolean? Returns `true` if there's no failed dependencies. ----@field process_loc_text? fun(self: SMODS.Challenge|table) Called during `inject_class`. Handles injecting loc_text. ----@field send_to_subclasses? fun(self: SMODS.Challenge|table, func: string, ...: any) Starting from this class, recusively searches for functions with the given key on all subordinate classes and run all found functions with the given arguments. ----@field pre_inject_class? fun(self: SMODS.Challenge|table) Called before `inject_class`. Injects and manages class information before object injection. ----@field post_inject_class? fun(self: SMODS.Challenge|table) Called after `inject_class`. Injects and manages class information after object injection. ----@field inject_class? fun(self: SMODS.Challenge|table) Injects all direct instances of class objects by calling `obj:inject` and `obj:process_loc_text`. Also injects anything necessary for the class itself. Only called if class has defined both `obj_table` and `obj_buffer`. ----@field inject? fun(self: SMODS.Challenge|table, i?: number) Called during `inject_class`. Injects the object into the game. +---@field extend? fun(self: SMODS.Challenge|table, o: SMODS.Challenge|table): table Primary method of creating a class. +---@field check_duplicate_register? fun(self: SMODS.Challenge|table): boolean? Ensures objects already registered will not register. +---@field check_duplicate_key? fun(self: SMODS.Challenge|table): boolean? Ensures objects with duplicate keys will not register. Checked on `__call` but not `take_ownership`. For take_ownership, the key must exist. +---@field register? fun(self: SMODS.Challenge|table) Registers the object. +---@field check_dependencies? fun(self: SMODS.Challenge|table): boolean? Returns `true` if there's no failed dependencies. +---@field process_loc_text? fun(self: SMODS.Challenge|table) Called during `inject_class`. Handles injecting loc_text. +---@field send_to_subclasses? fun(self: SMODS.Challenge|table, func: string, ...: any) Starting from this class, recusively searches for functions with the given key on all subordinate classes and run all found functions with the given arguments. +---@field pre_inject_class? fun(self: SMODS.Challenge|table) Called before `inject_class`. Injects and manages class information before object injection. +---@field post_inject_class? fun(self: SMODS.Challenge|table) Called after `inject_class`. Injects and manages class information after object injection. +---@field inject_class? fun(self: SMODS.Challenge|table) Injects all direct instances of class objects by calling `obj:inject` and `obj:process_loc_text`. Also injects anything necessary for the class itself. Only called if class has defined both `obj_table` and `obj_buffer`. +---@field inject? fun(self: SMODS.Challenge|table, i?: number) Called during `inject_class`. Injects the object into the game. ---@field take_ownership? fun(self: SMODS.Challenge|table, key: string, obj: SMODS.Challenge|table, silent?: boolean): nil|table|SMODS.Challenge Takes control of vanilla objects. Child class must have get_obj for this to function ----@field get_obj? fun(self: SMODS.Challenge|table, key: string): SMODS.Challenge|table? Returns an object if one matches the `key`. +---@field get_obj? fun(self: SMODS.Challenge|table, key: string): SMODS.Challenge|table? Returns an object if one matches the `key`. ---@field unlocked? fun(self: SMODS.Challenge|table): boolean +---@field button_colour? table HEX color of the button on the challenge list. +---@field calculate? fun(self: SMODS.Challenge|table, context: CalcContext|table): table?, boolean? Calculates effects based on parameters in `context`. See [SMODS calculation](https://github.com/Steamodded/smods/wiki/calculate_functions) docs for details. +---@field apply? fun(self: SMODS.Challenge|table) Applied modifiers at the start of a run. ---@overload fun(self: SMODS.Challenge): SMODS.Challenge SMODS.Challenge = setmetatable({}, { __call = function(self) @@ -33,4 +36,4 @@ SMODS.Challenge = setmetatable({}, { }) ---@type table -SMODS.Challenges = {} \ No newline at end of file +SMODS.Challenges = {} diff --git a/Steamodded/lsp_def/classes/consumable.lua b/Steamodded/lsp_def/classes/consumable.lua index adff780..68e746d 100644 --- a/Steamodded/lsp_def/classes/consumable.lua +++ b/Steamodded/lsp_def/classes/consumable.lua @@ -23,7 +23,8 @@ ---@field get_obj? fun(self: SMODS.Consumable|table, key: string): SMODS.Consumable|table? Returns an object if one matches the `key`. ---@field use? fun(self: SMODS.Consumable|table, card: Card|table, area: CardArea|table, copier?: table) Defines behaviour when this consumable is used. ---@field can_use? fun(self: SMODS.Consumable|table, card: Card|table): boolean? Return `true` if the consumable is allowed to be used. ----@field keep_on_use? fun(self: SMODS.Consumable|table, card: Card|table): boolean? Return `true` if the consumable should stay after use. +---@field keep_on_use? fun(self: SMODS.Consumable|table, card: Card|table): boolean? Return `true` if the consumable should stay after use. +---@field calc_scaling? fun(self: SMODS.Consumable|table, card: Card|table, other_card: Card|table, scaling_value: number, scalar_value: number, args: table): table? Called by `SMODS.scale_card`. Allows detection and modification of cards when scaling values. The return may include a `scaling_value` or `scalar_value` field to modify those values or any standard calculation return. ---@overload fun(self: SMODS.Consumable): SMODS.Consumable SMODS.Consumable = setmetatable({}, { __call = function(self) diff --git a/Steamodded/lsp_def/classes/consumable_type.lua b/Steamodded/lsp_def/classes/consumable_type.lua index 93115c4..11c55aa 100644 --- a/Steamodded/lsp_def/classes/consumable_type.lua +++ b/Steamodded/lsp_def/classes/consumable_type.lua @@ -6,9 +6,11 @@ ---@field super? SMODS.ObjectType|table Parent class. ---@field primary_colour? table HEX color used as the primary color. Set as `G.C.SET[self.key]`. ---@field secondary_colour? table HEX color used as the seconary color. Set as `G.C.SECONDARY_COLOUR[self.key]`. +---@field text_colour? table HEX color used as the text color. Set as `G.C.UI[self.key]`. ---@field collection_rows? number[] Array of numbers indicating how many rows and how many cards per row this ConsumableType's collection has. ---@field shop_rate? nil|number Defining this value allows cards part of this ConsumableType to appear in the shop. Defined as `G.GAME[key:lower()..'_rate']`. ---@field ctype_buffer? string[] Array of keys to all objects registered to the ConsumableType class. +---@field visible_buffer? string[] Array of keys to all ConsumableType objects allowed to appear in collections menu. ---@field __call? fun(self: SMODS.ConsumableType|table, o: SMODS.ConsumableType|table): nil|table|SMODS.ConsumableType ---@field extend? fun(self: SMODS.ConsumableType|table, o: SMODS.ConsumableType|table): table Primary method of creating a class. ---@field check_duplicate_register? fun(self: SMODS.ConsumableType|table): boolean? Ensures objects already registered will not register. diff --git a/Steamodded/lsp_def/classes/edition.lua b/Steamodded/lsp_def/classes/edition.lua index 3b4c525..8105463 100644 --- a/Steamodded/lsp_def/classes/edition.lua +++ b/Steamodded/lsp_def/classes/edition.lua @@ -1,7 +1,9 @@ ---@meta ---@class SMODS.Edition: SMODS.Center ----@field loc_txt? table|{name: string, text: string[], label: string} Contains strings used for displaying text related to this object. +---@field obj_buffer? Editions|string[] Array of keys to all objects registered to this class. +---@field obj_table? table Table of objects registered to this class. +---@field loc_txt? table|{name: string|string[], text: string[]|string[][], label: string} Contains strings used for displaying text related to this object. ---@field shader? string|false Key to the shader drawn on cards with this Edition. If set to `false`, a shader will not be drawn. ---@field atlas? string Defines the atlas for the card this Edition is drawn on in the collection. ---@field pos? table|{x: integer, y: integer} Defined the position of the card's sprite this Edition is drawn on in the collection. @@ -49,7 +51,7 @@ SMODS.Edition = setmetatable({}, { function Card:calculate_edition(context) end ---@param self Card|table ----@param edition string|{[string]: true}? Both `string` values are the key of the edition to apply. +---@param edition? Editions|string|{[string]: true} Both `string` values are the key of the edition to apply. ---@param immediate? boolean ---@param silent? boolean ---@param delay? boolean @@ -61,6 +63,6 @@ function Card:set_edition(edition, immediate, silent, delay) end ---@param _no_neg? boolean Exclude negative from edition polling. ---@param _guaranteed? boolean Function will always return an Edition. ---@param _options? string[]|{name: string, weight: number}[] Allows defining options for what editions should be polled. ----@return string? +---@return Editions|string? --- Polls editions. Returns the key of the edition if successful. function poll_edition(_key, _mod, _no_neg, _guaranteed, _options) end diff --git a/Steamodded/lsp_def/classes/enhancement.lua b/Steamodded/lsp_def/classes/enhancement.lua index de96941..26b81fb 100644 --- a/Steamodded/lsp_def/classes/enhancement.lua +++ b/Steamodded/lsp_def/classes/enhancement.lua @@ -1,7 +1,9 @@ ---@meta ---@class SMODS.Enhancement: SMODS.Center ----@field super? SMODS.Center|table Parent class. +---@field super? SMODS.Center|table Parent class. +---@field obj_buffer? Enhancements|string[] Array of keys to all objects registered to this class. +---@field obj_table? table Table of objects registered to this class. ---@field replace_base_card? boolean Don't draw base card sprite or give base chips. ---@field no_rank? boolean Enhanced cards have no rank ---@field no_suit? boolean Enhanced cards have no suit. @@ -38,6 +40,6 @@ SMODS.Enhancement = setmetatable({}, { function Card:calculate_enhancement(context) end ---@param args table|{key?: string, type_key?: string, mod?: number, guaranteed?: true, options?: table} ----@return string? +---@return Enhancements|string? --- Polls all Enhancements with `args` for additional settings, and returns the key to a selected enhancement. function SMODS.poll_enhancement(args) end diff --git a/Steamodded/lsp_def/classes/font.lua b/Steamodded/lsp_def/classes/font.lua new file mode 100644 index 0000000..7e7e45c --- /dev/null +++ b/Steamodded/lsp_def/classes/font.lua @@ -0,0 +1,35 @@ +---@meta + +---@class SMODS.Font: SMODS.GameObject +---@field obj_table? table Table of objects registered to this class. +---@field super? SMODS.GameObject|table Parent class. +---@field path? string Name of the font file, including the extension. +---@field render_scale? number Set the size of the font. This is generally better as a higher value so it can be scaled down. The default value is `200`. +---@field TEXT_HEIGHT_SCALE? number Determines line spacing. The default value is `0.83`. +---@field TEXT_OFFSET? table|{x: number, y: number} Determines the offset that the font is rendered. You might need to adjust this if the font renders in unexpected places. The default value is `{x=0, y=0}`. +---@field FONTSCALE? number Multiplier to scale down the font to the intended display size. Multiplies `render_scale` so that it renders at a proper size. The default value is `0.1`. +---@field squish? number Determines horizontal width of each character. The default value is `1`. +---@field DESCSCALE? number Determines how big the description text should be in relation to normal text. Keep in mind that mobile UI makes this 1.5x bigger. The default font's value is `1`. +---@field __call? fun(self: SMODS.Font|table, o: SMODS.Font|table): nil|table|SMODS.Font +---@field extend? fun(self: SMODS.Font|table, o: SMODS.Font|table): table Primary method of creating a class. +---@field check_duplicate_register? fun(self: SMODS.Font|table): boolean? Ensures objects already registered will not register. +---@field check_duplicate_key? fun(self: SMODS.Font|table): boolean? Ensures objects with duplicate keys will not register. Checked on `__call` but not `take_ownership`. For take_ownership, the key must exist. +---@field register? fun(self: SMODS.Font|table) Registers the object. +---@field check_dependencies? fun(self: SMODS.Font|table): boolean? Returns `true` if there's no failed dependencies. +---@field process_loc_text? fun(self: SMODS.Font|table) Called during `inject_class`. Handles injecting loc_text. +---@field send_to_subclasses? fun(self: SMODS.Font|table, func: string, ...: any) Starting from this class, recusively searches for functions with the given key on all subordinate classes and run all found functions with the given arguments. +---@field pre_inject_class? fun(self: SMODS.Font|table) Called before `inject_class`. Injects and manages class information before object injection. +---@field post_inject_class? fun(self: SMODS.Font|table) Called after `inject_class`. Injects and manages class information after object injection. +---@field inject_class? fun(self: SMODS.Font|table) Injects all direct instances of class objects by calling `obj:inject` and `obj:process_loc_text`. Also injects anything necessary for the class itself. Only called if class has defined both `obj_table` and `obj_buffer`. +---@field inject? fun(self: SMODS.Font|table, i?: number) Called during `inject_class`. Injects the object into the game. +---@field take_ownership? fun(self: SMODS.Font|table, key: string, obj: SMODS.Font|table, silent?: boolean): nil|table|SMODS.Font Takes control of vanilla objects. Child class must have get_obj for this to function +---@field get_obj? fun(self: SMODS.Font|table, key: string): SMODS.Font|table? Returns an object if one matches the `key`. +---@overload fun(self: SMODS.Font): SMODS.Font +SMODS.Font = setmetatable({}, { + __call = function(self) + return self + end +}) + +---@type table +SMODS.Fonts = {} \ No newline at end of file diff --git a/Steamodded/lsp_def/classes/game_object.lua b/Steamodded/lsp_def/classes/game_object.lua index d0c09a9..63f7605 100644 --- a/Steamodded/lsp_def/classes/game_object.lua +++ b/Steamodded/lsp_def/classes/game_object.lua @@ -15,7 +15,7 @@ ---@field prefix_config? boolean|table Controls how prefixes are applied. By default, class_prefix and mod_prefix are applied to all registered objects. ---@field required_params? string[] Array of parameters required for objects created by this class. ---@field set? string Important for objects wanting to follow vanilla logic that depends on `set`. For classes, this is used for logging purposes. ----@field no_collection? boolean Sets whether the object shows up in collections. +---@field no_collection? boolean Sets whether the object is allowed to show up in collections. ---@field config? table Cards/Objects representing your center will copy default values from `config` into it's `ability` table. Custom values can be stored within `extra`. ---@field __call? fun(self: SMODS.GameObject|table, o: SMODS.GameObject|table): nil|table|SMODS.GameObject ---@field extend? fun(self: SMODS.GameObject|table, o: SMODS.GameObject|table): table Primary method of creating a class. @@ -40,14 +40,14 @@ SMODS.GameObject = setmetatable({ }) ---@param obj SMODS.GameObject|table ----@param prefix boolean|string? ----@param condition boolean? ----@param key string? +---@param prefix? boolean|string +---@param condition? boolean +---@param key? string --- Modifies the object's key. function SMODS.modify_key(obj, prefix, condition, key) end ---@param cls SMODS.GameObject|table The class of this object ---@param obj SMODS.GameObject|table The object ----@param from_take_ownership true? +---@param from_take_ownership? boolean --- Adds prefixes into the object. function SMODS.add_prefixes(cls, obj, from_take_ownership) end diff --git a/Steamodded/lsp_def/classes/gradient.lua b/Steamodded/lsp_def/classes/gradient.lua index e6fd7d9..1ed30ec 100644 --- a/Steamodded/lsp_def/classes/gradient.lua +++ b/Steamodded/lsp_def/classes/gradient.lua @@ -1,7 +1,7 @@ ---@meta ---@class SMODS.Gradient: SMODS.GameObject ----@field interpolation? string Interpolation type of the gradient. Currently supported: `'trig'`, '`linear'`. +---@field interpolation? 'trig'|'linear'|string Interpolation type of the gradient. Currently supported: `'trig'`, `'linear'`. ---@field colours? table> List of colours to interpolate between. ---@field cycle? number Amount of time (in seconds) for the gradient to cycle through all colours. ---@field __call? fun(self: SMODS.Gradient|table, o: SMODS.Gradient|table): nil|table|SMODS.Gradient @@ -18,6 +18,7 @@ ---@field inject? fun(self: SMODS.Gradient|table, i?: number) Called during `inject_class`. Injects the object into the game. ---@field take_ownership? fun(self: SMODS.Gradient|table, key: string, obj: SMODS.Gradient|table, silent?: boolean): nil|table|SMODS.Gradient Takes control of vanilla objects. Child class must have get_obj for this to function ---@field get_obj? fun(self: SMODS.Gradient|table, key: string): SMODS.Gradient|table? Returns an object if one matches the `key`. +---@field update? fun(self: SMODS.Gradient|table, dt: number) Allows finer per-frame control over the implementation. ---@overload fun(self: SMODS.Gradient): SMODS.Gradient SMODS.Gradient = setmetatable({}, { __call = function(self) diff --git a/Steamodded/lsp_def/classes/jimbo_quip.lua b/Steamodded/lsp_def/classes/jimbo_quip.lua new file mode 100644 index 0000000..9a2a668 --- /dev/null +++ b/Steamodded/lsp_def/classes/jimbo_quip.lua @@ -0,0 +1,30 @@ +---@meta + +---@class SMODS.JimboQuip: SMODS.GameObject +---@field type? 'win'|'loss'|string Whether it's a win, loss or another type quip. +---@field loc_txt? string[] Text for the quip. +---@field __call? fun(self: SMODS.JimboQuip|table, o: SMODS.JimboQuip|table): nil|table|SMODS.JimboQuip +---@field extend? fun(self: SMODS.JimboQuip|table, o: SMODS.JimboQuip|table): table Primary method of creating a class. +---@field check_duplicate_register? fun(self: SMODS.JimboQuip|table): boolean? Ensures objects already registered will not register. +---@field check_duplicate_key? fun(self: SMODS.JimboQuip|table): boolean? Ensures objects with duplicate keys will not register. Checked on `__call` but not `take_ownership`. For take_ownership, the key must exist. +---@field register? fun(self: SMODS.JimboQuip|table) Registers the object. +---@field check_dependencies? fun(self: SMODS.JimboQuip|table): boolean? Returns `true` if there's no failed dependencies. +---@field process_loc_text? fun(self: SMODS.JimboQuip|table) Called during `inject_class`. Handles injecting loc_text. +---@field send_to_subclasses? fun(self: SMODS.JimboQuip|table, func: string, ...: any) Starting from this class, recusively searches for functions with the given key on all subordinate classes and run all found functions with the given arguments. +---@field pre_inject_class? fun(self: SMODS.JimboQuip|table) Called before `inject_class`. Injects and manages class information before object injection. +---@field post_inject_class? fun(self: SMODS.JimboQuip|table) Called after `inject_class`. Injects and manages class information after object injection. +---@field inject_class? fun(self: SMODS.JimboQuip|table) Injects all direct instances of class objects by calling `obj:inject` and `obj:process_loc_text`. Also injects anything necessary for the class itself. Only called if class has defined both `obj_table` and `obj_buffer`. +---@field inject? fun(self: SMODS.JimboQuip|table, i?: number) Called during `inject_class`. Injects the object into the game. +---@field take_ownership? fun(self: SMODS.JimboQuip|table, key: string, obj: SMODS.JimboQuip|table, silent?: boolean): nil|table|SMODS.JimboQuip Takes control of vanilla objects. Child class must have get_obj for this to function +---@field get_obj? fun(self: SMODS.JimboQuip|table, key: string): SMODS.JimboQuip|table? Returns an object if one matches the `key`. +---@field extra? table|fun():table? Arguments for Card_Character. +---@field filter? fun(self: SMODS.JimboQuip|table, quip_type: string): boolean?, table? Allows configuring if the quip is allowed to appear. +---@overload fun(self: SMODS.JimboQuip): SMODS.JimboQuip +SMODS.JimboQuip = setmetatable({}, { + __call = function(self) + return self + end +}) + +---@type table +SMODS.JimboQuips = {} diff --git a/Steamodded/lsp_def/classes/joker.lua b/Steamodded/lsp_def/classes/joker.lua index 9eda54c..e936a44 100644 --- a/Steamodded/lsp_def/classes/joker.lua +++ b/Steamodded/lsp_def/classes/joker.lua @@ -17,6 +17,7 @@ ---@field take_ownership? fun(self: SMODS.Joker|table, key: string, obj: SMODS.Joker|table, silent?: boolean): nil|table|SMODS.Joker Takes control of vanilla objects. Child class must have get_obj for this to function ---@field get_obj? fun(self: SMODS.Joker|table, key: string): SMODS.Joker|table? Returns an object if one matches the `key`. ---@field calc_dollar_bonus? fun(self: SMODS.Joker|table, card: Card|table): nil|number Calculates reward money. +---@field calc_scaling? fun(self: SMODS.Joker|table, card: Card|table, other_card: Card|table, scaling_value: number, scalar_value: number, args: table): table? Called by `SMODS.scale_card`. Allows detection and modification of cards when scaling values. The return may include a `scaling_value` or `scalar_value` field to modify those values or any standard calculation return. ---@field new? fun(self, name, slug, config, spritePos, loc_txt, rarity, cost, unlocked, discovered,blueprint_compat, eternal_compat, effect, atlas, soul_pos): any DEPRECATED. DO NOT USE ---@overload fun(self: SMODS.Joker): SMODS.Joker SMODS.Joker = setmetatable({}, { diff --git a/Steamodded/lsp_def/classes/poker_hand.lua b/Steamodded/lsp_def/classes/poker_hand.lua index 539e7af..8034586 100644 --- a/Steamodded/lsp_def/classes/poker_hand.lua +++ b/Steamodded/lsp_def/classes/poker_hand.lua @@ -1,7 +1,8 @@ ---@meta ---@class SMODS.PokerHand: SMODS.GameObject ----@field obj_table? table Table of objects registered to this class. +---@field obj_buffer? PokerHands|string[] Array of keys to all objects registered to this class. +---@field obj_table? table Table of objects registered to this class. ---@field loc_txt? table|{name: string, description: string[]} Contains strings used for displaying text related to this object. ---@field super? SMODS.GameObject|table Parent class. ---@field mult? number Base mult for poker hand. @@ -9,8 +10,8 @@ ---@field l_mult? number Mult gained per hand level. ---@field l_chips? number Chips gained per hand level. ---@field example? table Table of cards used to represent the hand example in the "Run Info" tab. ----@field visisble? boolean Sets hand visibility in the poker hands menu. If `false`, poker hand is shown only after being played once. ----@field above_hand? string Key to a poker hand. Used to order this poker hand above specified poker hand. +---@field visible? boolean|fun(self:SMODS.PokerHand|table): boolean? Sets hand visibility in the poker hands menu. If `false`, poker hand is shown only after being played once. A function allows more precise control over hand visibility in the poker hands menu. +---@field above_hand? PokerHands|string Key to a poker hand. Used to order this poker hand above specified poker hand. ---@field order_offset? number Adds this value to poker hand's mult and chips to offset ordering. ---@field __call? fun(self: SMODS.PokerHand|table, o: SMODS.PokerHand|table): nil|table|SMODS.PokerHand ---@field extend? fun(self: SMODS.PokerHand|table, o: SMODS.PokerHand|table): table Primary method of creating a class. @@ -27,7 +28,7 @@ ---@field take_ownership? fun(self: SMODS.PokerHand|table, key: string, obj: SMODS.PokerHand|table, silent?: boolean): nil|table|SMODS.PokerHand Takes control of vanilla objects. Child class must have get_obj for this to function ---@field get_obj? fun(self: SMODS.PokerHand|table, key: string): SMODS.PokerHand|table? Returns an object if one matches the `key`. ---@field evaluate? fun(parts: table, hand: table): table? Determines if played cards contain this hand, and what cards are a part of it. ----@field modify_display_text? fun(self: SMODS.PokerHand|table, cards: Card[]|table[], scoring_hand: Card[]|table[]): string? Allows modifying the display text when this poker hand's text is meant to display. +---@field modify_display_text? fun(self: SMODS.PokerHand|table, cards: Card[]|table[], scoring_hand: Card[]|table[]): string? Allows modifying the display text when this poker hand's text is meant to display. ---@overload fun(self: SMODS.PokerHand): SMODS.PokerHand SMODS.PokerHand = setmetatable({}, { __call = function(self) @@ -35,7 +36,7 @@ SMODS.PokerHand = setmetatable({}, { end }) ----@type table +---@type table SMODS.PokerHands = {} ---@class SMODS.PokerHandPart: SMODS.GameObject diff --git a/Steamodded/lsp_def/classes/rank.lua b/Steamodded/lsp_def/classes/rank.lua index 3d1f5e9..0ec2adf 100644 --- a/Steamodded/lsp_def/classes/rank.lua +++ b/Steamodded/lsp_def/classes/rank.lua @@ -1,7 +1,8 @@ ---@meta ---@class SMODS.Rank: SMODS.GameObject ----@field obj_table? table Table of objects registered to this class. +---@field obj_buffer? Ranks|string[] Array of keys to all objects registered to this class. +---@field obj_table? table Table of objects registered to this class. ---@field loc_txt? table|{name: string} Contains strings used for displaying text related to this object. ---@field super? SMODS.GameObject|table Parent class. ---@field atlas? string Key to the rank's atlas. @@ -13,8 +14,8 @@ ---@field shorthand? string Short description of this rank in deck preview. ---@field face_nominal? number Determines the displayed order of ranks with the same nominal value. ---@field face? boolean Sets if this rank counts as a "face" card. ----@field next? string[] List of keys to other ranks that come after this card. ----@field prev? string[] List of keys to other ranks that come before this card. Used when evaluating straights. +---@field next? Ranks|string[] List of keys to other ranks that come after this card. +---@field prev? Ranks|string[] List of keys to other ranks that come before this card. Used when evaluating straights. ---@field strength_effect? table|{fixed?: number, random?: boolean, ignore?: boolean} Determines how cards with this rank behave when Strength is used. ---@field straight_edge? boolean Sets if this rank behaves like an Ace for straights. ---@field suit_map? table For any suit keys in this table, use this rank's atlas over the suit's atlas. Provided number is the `y` position of the suit on the rank's atlas. @@ -43,5 +44,5 @@ SMODS.Rank = setmetatable({}, { end }) ----@type table +---@type table SMODS.Ranks = {} diff --git a/Steamodded/lsp_def/classes/rarity.lua b/Steamodded/lsp_def/classes/rarity.lua index 82a3e49..d13286a 100644 --- a/Steamodded/lsp_def/classes/rarity.lua +++ b/Steamodded/lsp_def/classes/rarity.lua @@ -1,7 +1,8 @@ ---@meta ---@class SMODS.Rarity: SMODS.GameObject ----@field obj_table? table Table of objects registered to this class. +---@field obj_buffer? Rarities|string[] Array of keys to all objects registered to this class. +---@field obj_table? table Table of objects registered to this class. ---@field loc_txt? table|{name: string} Contains strings used for displaying text related to this object. ---@field super? SMODS.GameObject|table Parent class. ---@field pools? table Table with a list of ObjectTypes keys this rarity should be added to. @@ -31,12 +32,12 @@ SMODS.Rarity = setmetatable({}, { end }) ----@type table +---@type table SMODS.Rarities = {} ---@param _pool_key string Key to ObjectType ---@param _rand_key? string Used as polling seed ----@return string|number rarity_key +---@return Rarities|string|number rarity_key ---Polls all rarities tied to provided ObjectType. function SMODS.poll_rarity(_pool_key, _rand_key) end diff --git a/Steamodded/lsp_def/classes/scoring_calculation.lua b/Steamodded/lsp_def/classes/scoring_calculation.lua new file mode 100644 index 0000000..e1f5f76 --- /dev/null +++ b/Steamodded/lsp_def/classes/scoring_calculation.lua @@ -0,0 +1,76 @@ +---@meta + +---@class SMODS.Scoring_Calculation: SMODS.GameObject +---@field extend? fun(self: SMODS.Scoring_Calculation|table, o: SMODS.Scoring_Calculation|table): table Primary method of creating a class. +---@field check_duplicate_register? fun(self: SMODS.Scoring_Calculation|table): boolean? Ensures objects already registered will not register. +---@field check_duplicate_key? fun(self: SMODS.Scoring_Calculation|table): boolean? Ensures objects with duplicate keys will not register. Checked on `__call` but not `take_ownership`. For take_ownership, the key must exist. +---@field register? fun(self: SMODS.Scoring_Calculation|table) Registers the object. +---@field check_dependencies? fun(self: SMODS.Scoring_Calculation|table): boolean? Returns `true` if there's no failed dependencies. +---@field process_loc_text? fun(self: SMODS.Scoring_Calculation|table) Called during `inject_class`. Handles injecting loc_text. +---@field send_to_subclasses? fun(self: SMODS.Scoring_Calculation|table, func: string, ...: any) Starting from this class, recusively searches for functions with the given key on all subordinate classes and run all found functions with the given arguments. +---@field pre_inject_class? fun(self: SMODS.Scoring_Calculation|table) Called before `inject_class`. Injects and manages class information before object injection. +---@field post_inject_class? fun(self: SMODS.Scoring_Calculation|table) Called after `inject_class`. Injects and manages class information after object injection. +---@field inject_class? fun(self: SMODS.Scoring_Calculation|table) Injects all direct instances of class objects by calling `obj:inject` and `obj:process_loc_text`. Also injects anything necessary for the class itself. Only called if class has defined both `obj_table` and `obj_buffer`. +---@field inject? fun(self: SMODS.Scoring_Calculation|table, i?: number) Called during `inject_class`. Injects the object into the game. +---@field take_ownership? fun(self: SMODS.Scoring_Calculation|table, key: string, obj: SMODS.Scoring_Calculation|table, silent?: boolean): nil|table|SMODS.Scoring_Calculation Takes control of vanilla objects. Child class must have get_obj for this to function +---@field get_obj? fun(self: SMODS.Scoring_Calculation|table, key: string): SMODS.Scoring_Calculation|table? Returns an object if one matches the `key`. +---@field new? fun(self, config): SMODS.Scoring_Calculation Creates a new instance of this operator. +---@field key string Used to reference your calculation, mod_prefix is applied +---@field func fun(self, chips, mult, flames) Calculate your new score, flames respects animation timings +---@field text? string Replaces the `X` in the UI +---@field colour? table HEX colour of the `text` in the UI +---@field replace_ui? fun(self) Return a UI node to replace the display +---@field update_ui? fun(self: SMODS.Scoring_Calculation, container?: UIElement, chip_display?: UIElement, mult_display?: UIElement, operator?: UIElement) +---@field config? table Values saved to the scoring calculation +---@field parameters? string[] Table of Scoring Parameter keys that are used +---@overload fun(self: SMODS.Scoring_Calculation): SMODS.Scoring_Calculation +SMODS.Scoring_Calculation = setmetatable({}, { + __call = function(self) + return self + end +}) + +---@type table +SMODS.Scoring_Calculations = {} + +--- Sets the current operator used on chips and mult. +---@param key string|SMODS.Scoring_Calculation The key of the scoring calculation you want to use. +---@param config table? The operator's config. +function SMODS.set_scoring_calculation(key) end + +--- Calculates a final round score based on the current scoring calculation. +---@param flames boolean Flag for flame calculation - result respects animations +---@return number +SMODS.calculate_round_score = function(flames) end + + +---@class SMODS.Scoring_Parameter: SMODS.GameObject +---@field extend? fun(self: SMODS.Scoring_Parameter|table, o: SMODS.Scoring_Parameter|table): table Primary method of creating a class. +---@field check_duplicate_register? fun(self: SMODS.Scoring_Parameter|table): boolean? Ensures objects already registered will not register. +---@field check_duplicate_key? fun(self: SMODS.Scoring_Parameter|table): boolean? Ensures objects with duplicate keys will not register. Checked on `__call` but not `take_ownership`. For take_ownership, the key must exist. +---@field register? fun(self: SMODS.Scoring_Parameter|table) Registers the object. +---@field check_dependencies? fun(self: SMODS.Scoring_Parameter|table): boolean? Returns `true` if there's no failed dependencies. +---@field process_loc_text? fun(self: SMODS.Scoring_Parameter|table) Called during `inject_class`. Handles injecting loc_text. +---@field send_to_subclasses? fun(self: SMODS.Scoring_Parameter|table, func: string, ...: any) Starting from this class, recusively searches for functions with the given key on all subordinate classes and run all found functions with the given arguments. +---@field pre_inject_class? fun(self: SMODS.Scoring_Parameter|table) Called before `inject_class`. Injects and manages class information before object injection. +---@field post_inject_class? fun(self: SMODS.Scoring_Parameter|table) Called after `inject_class`. Injects and manages class information after object injection. +---@field inject_class? fun(self: SMODS.Scoring_Parameter|table) Injects all direct instances of class objects by calling `obj:inject` and `obj:process_loc_text`. Also injects anything necessary for the class itself. Only called if class has defined both `obj_table` and `obj_buffer`. +---@field inject? fun(self: SMODS.Scoring_Parameter|table, i?: number) Called during `inject_class`. Injects the object into the game. +---@field take_ownership? fun(self: SMODS.Scoring_Parameter|table, key: string, obj: SMODS.Scoring_Parameter|table, silent?: boolean): nil|table|SMODS.Scoring_Calculation Takes control of vanilla objects. Child class must have get_obj for this to function +---@field get_obj? fun(self: SMODS.Scoring_Parameter|table, key: string): SMODS.Scoring_Parameter|table? Returns an object if one matches the `key`. +---@field key string Used to reference the parameter, mod_prefix is added +---@field default_value number Default value of the parameter +---@field colour? table HEX colour +---@field calculation_keys? string[] Valid return keys from calculate functions +---@field hands? table[] Used to add custom values for different poker hands +---@field modify? fun(self: SMODS.Scoring_Parameter, amount: number) Alters the value of the parameter +---@field calc_effect? fun(self: SMODS.Scoring_Parameter, effect: table, scored_card: Card|table, key: string, amount: number, from_edition: boolean) Handle how this parameter is calculated when return from a calculate functon +---@field level_up_hand? fun(self: SMODS.Scoring_Parameter, amount: number, hand: table) Handle how to level up this parameter + +---@type table +SMODS.Scoring_Parameters = {} + +--- Gets the value of a scoring parameter +---@param key string The key of the parameter +---@param flames boolean Flag for flame calculation - result respects animations +function SMODS.get_scoring_parameter(key, flames) end \ No newline at end of file diff --git a/Steamodded/lsp_def/classes/seal.lua b/Steamodded/lsp_def/classes/seal.lua index 2a0bdce..9225a6a 100644 --- a/Steamodded/lsp_def/classes/seal.lua +++ b/Steamodded/lsp_def/classes/seal.lua @@ -1,8 +1,9 @@ ---@meta ---@class SMODS.Seal: SMODS.GameObject ----@field obj_table? table Table of objects registered to this class. ----@field loc_txt? table|{name: string, text: string[], label: string} Contains strings used for displaying text related to this object. +---@field obj_buffer? Seals|string[] Array of keys to all objects registered to this class. +---@field obj_table? table Table of objects registered to this class. +---@field loc_txt? table|{name: string|string[], text: string[]|string[][], label: string} Contains strings used for displaying text related to this object. ---@field super? SMODS.GameObject|table Parent class. ---@field atlas? string Key to the seal's atlas. ---@field pos? table|{x: integer, y: integer} Position of the seal's sprite. @@ -39,10 +40,10 @@ SMODS.Seal = setmetatable({}, { end }) ----@type table +---@type table SMODS.Seals = {} ---@param args table|{key?: string, mod?: number, guaranteed?: boolean, options?: table, type_key?: string} ----@return string? +---@return Seals|string? --- Polls seals. function SMODS.poll_seal(args) end diff --git a/Steamodded/lsp_def/classes/stake.lua b/Steamodded/lsp_def/classes/stake.lua index adae7ca..3289047 100644 --- a/Steamodded/lsp_def/classes/stake.lua +++ b/Steamodded/lsp_def/classes/stake.lua @@ -27,7 +27,8 @@ ---@field inject? fun(self: SMODS.Stake|table, i?: number) Called during `inject_class`. Injects the object into the game. ---@field take_ownership? fun(self: SMODS.Stake|table, key: string, obj: SMODS.Stake|table, silent?: boolean): nil|table|SMODS.Stake Takes control of vanilla objects. Child class must have get_obj for this to function ---@field get_obj? fun(self: SMODS.Stake|table, key: string): SMODS.Stake|table? Returns an object if one matches the `key`. ----@field modifiers? fun() Applies changes to the game state when this stake is applied at the start of a run. +---@field modifiers? fun() Applies changes to the game state when this stake is applied at the start of a run. +---@field calculate? fun(self: SMODS.Stake|table, context: CalcContext|table): table?, boolean? Calculates effects based on parameters in `context`. See [SMODS calculation](https://github.com/Steamodded/smods/wiki/calculate_functions) docs for details. ---@overload fun(self: SMODS.Stake): SMODS.Stake SMODS.Stake = setmetatable({}, { __call = function(self) @@ -39,7 +40,7 @@ SMODS.Stake = setmetatable({}, { SMODS.Stakes = {} ---@param stake SMODS.Stake|table ----@param applied table? +---@param applied? table ---@return table applied ---Builds the stake chain. function SMODS.build_stake_chain(stake, applied) end diff --git a/Steamodded/lsp_def/classes/sticker.lua b/Steamodded/lsp_def/classes/sticker.lua index 72f43d1..f9a197e 100644 --- a/Steamodded/lsp_def/classes/sticker.lua +++ b/Steamodded/lsp_def/classes/sticker.lua @@ -1,7 +1,8 @@ ---@meta ---@class SMODS.Sticker: SMODS.GameObject ----@field obj_table? table Table of objects registered to this class. +---@field obj_buffer? Stickers|string[] Array of keys to all objects registered to this class. +---@field obj_table? table Table of objects registered to this class. ---@field super? SMODS.GameObject|table Parent class. ---@field atlas? string Key to the center's atlas. ---@field pos? table|{x: integer, y: integer} Position of the center's sprite. @@ -40,17 +41,17 @@ SMODS.Sticker = setmetatable({}, { end }) ----@type table +---@type table SMODS.Stickers = {} ---@param self Card|table ----@param sticker string Key to the sticker to apply. +---@param sticker Stickers|string Key to the sticker to apply. ---@param bypass_check? boolean Whether the sticker's `should_apply` function is called. --- Adds the sticker onto the card. function Card:add_sticker(sticker, bypass_check) end ---@param self Card|table ----@param sticker string Key to the sticker to remove. +---@param sticker Stickers|string Key to the sticker to remove. --- Removes the sticker from the card, if it has the sticker. function Card:remove_sticker(sticker) end diff --git a/Steamodded/lsp_def/classes/suit.lua b/Steamodded/lsp_def/classes/suit.lua index 809e144..185a79a 100644 --- a/Steamodded/lsp_def/classes/suit.lua +++ b/Steamodded/lsp_def/classes/suit.lua @@ -1,7 +1,8 @@ ---@meta ---@class SMODS.Suit: SMODS.GameObject ----@field obj_table? table Table of objects registered to this class. +---@field obj_buffer? Suits|string[] Array of keys to all objects registered to this class. +---@field obj_table? table Table of objects registered to this class. ---@field loc_txt? table|{singular: string, plural: string} Contains strings used for displaying text related to this object. ---@field super? SMODS.GameObject|table Parent class. ---@field atlas? string Key to the suit's atlas. @@ -39,5 +40,5 @@ SMODS.Suit = setmetatable({}, { end }) ----@type table +---@type table SMODS.Suits = {} diff --git a/Steamodded/lsp_def/classes/voucher.lua b/Steamodded/lsp_def/classes/voucher.lua index 270ed06..22e61aa 100644 --- a/Steamodded/lsp_def/classes/voucher.lua +++ b/Steamodded/lsp_def/classes/voucher.lua @@ -17,7 +17,8 @@ ---@field inject? fun(self: SMODS.Voucher|table, i?: number) Called during `inject_class`. Injects the object into the game. ---@field take_ownership? fun(self: SMODS.Voucher|table, key: string, obj: SMODS.Voucher|table, silent?: boolean): nil|table|SMODS.Voucher Takes control of vanilla objects. Child class must have get_obj for this to function ---@field get_obj? fun(self: SMODS.Voucher|table, key: string): SMODS.Voucher|table? Returns an object if one matches the `key`. ----@field redeem? fun(self: SMODS.Voucher|table, voucher?: Card|table) Defines behaviour when this voucher is redeemed. +---@field redeem? fun(self: SMODS.Voucher|table, voucher?: Card|table) Defines behaviour when this voucher is redeemed. +---@field calc_scaling? fun(self: SMODS.Voucher|table, voucher: Card|table, other_card: Card|table, scaling_value: number, scalar_value: number, args: table): table? Called by `SMODS.scale_card`. Allows detection and modification of cards when scaling values. The return may include a `scaling_value` or `scalar_value` field to modify those values or any standard calculation return. ---@field new? fun(self, name, slug, config, pos, loc_txt, cost, unlocked, discovered, available, requires, atlas): any DEPRECATED. DO NOT USE ---@overload fun(self: SMODS.Voucher): SMODS.Voucher SMODS.Voucher = setmetatable({}, { diff --git a/Steamodded/lsp_def/smods_core.lua b/Steamodded/lsp_def/smods_core.lua index a4acf99..473be18 100644 --- a/Steamodded/lsp_def/smods_core.lua +++ b/Steamodded/lsp_def/smods_core.lua @@ -13,39 +13,43 @@ MODDED_VERSION = "" SMODS.path = "" ---@class Mod ----@field id? string Unique ID. ----@field name? string Name of the mod. ----@field display_name? string Display name of the mod. ----@field description? string Mod description. ----@field priority? number Loaded mods are sorted via priority. ----@field badge_colour? table HEX color of the mod badge. ----@field badge_text_colour? table HEX color of the text inside the mod badge. ----@field prefix? string Unique string. All objects created by this mod have this string appended to their key. ----@field version? string Mod version. ----@field dump_loc? true Dumps G.localization table into this mod's directory. ----@field dependencies? string[] All mods in this array must be installed and loaded for this mod to load. ----@field conflicts? table[] No mods in this array can be installed for this mod to load. ----@field provides? table[] If any of the mods in this array are not installed or loaded, this mod will act as a stand in. ----@field main_file? string Path to the main .lua file of this mod. ----@field config_file? string Path to the config file of this mod. Defaults to "config.lua" if not provided. ----@field config? table Config values for this mod. ----@field can_load? boolean? ----@field config_tab? fun(): table Creates this mod's config tab UI. ----@field extra_tabs? fun(): table[] Creates additional tabs within this mod's menu. ----@field custom_collection_tabs? fun(): table[] Creates additional buttons displayed inside the "Other" tab in collections. ----@field description_loc_vars? fun(self: Mod|table): table Allows dynamic display of this mod's description. ----@field custom_ui? fun(mod_nodes: table) Allows manipulating this mod's description tab. ----@field set_ability_reset_keys? fun(): table When a card's `ability` table is changed, values with a key matching inside this table will not persist. ----@field reset_game_globals? fun(run_start: boolean) Allows resetting global values every new run or round. ----@field set_debuff? fun(card: Card|table): boolean|string? Allows controlling when a card is debuffed or not. Return `"prevent_debuff"` to force a card to be undebuffable. ----@field optional_features? SMODS.optional_features|(fun(): SMODS.optional_features) Table of optional SMODS features to enable inserted into `SMODS.optional_features`. If function, returns table. +---@field id? string Unique ID. +---@field name? string Name of the mod. +---@field display_name? string Display name of the mod. +---@field description? string Mod description. +---@field priority? number Loaded mods are sorted via priority. +---@field badge_colour? table HEX color of the mod badge. +---@field badge_text_colour? table HEX color of the text inside the mod badge. +---@field prefix? string Unique string. All objects created by this mod have this string appended to their key. +---@field version? string Mod version. +---@field dump_loc? true Dumps G.localization table into this mod's directory. +---@field dependencies? string[] All mods in this array must be installed and loaded for this mod to load. +---@field conflicts? table[] No mods in this array can be installed for this mod to load. +---@field provides? table[] If any of the mods in this array are not installed or loaded, this mod will act as a stand in. +---@field main_file? string Path to the main .lua file of this mod. +---@field config_file? string Path to the config file of this mod. Defaults to "config.lua" if not provided. +---@field config? table Config values for this mod. +---@field can_load? boolean `true` if the mod is able to load. +---@field calculate? fun(self: Mod|table, context: CalcContext|table): table?, boolean? Calculates effects based on parameters in `context`. See [SMODS calculation](https://github.com/Steamodded/smods/wiki/calculate_functions) docs for details. +---@field config_tab? fun(): table Creates this mod's config tab UI. +---@field extra_tabs? fun(): table[] Creates additional tabs within this mod's menu. +---@field custom_collection_tabs? fun(): table[] Creates additional buttons displayed inside the "Other" tab in collections. +---@field description_loc_vars? fun(self: Mod|table): table Allows dynamic display of this mod's description. +---@field custom_ui? fun(mod_nodes: table) Allows manipulating this mod's description tab. +---@field ui_config? table Allows specifying custom values for this mod's menu UI elements. +---@field set_ability_reset_keys? fun(): string[] When a card's `ability` table is changed, values with a key matching a string inside the returned table . +---@field reset_game_globals? fun(run_start: boolean) Allows resetting global values every new run or round. +---@field set_debuff? fun(card: Card|table): boolean|string? Allows controlling when a card is debuffed or not. Return `"prevent_debuff"` to force a card to be undebuffable. +---@field quip_filter? fun(quip: SMODS.JimboQuip|table, quip_type: string): boolean?, table? Allows configuring a quip is allowed to appear. +---@field optional_features? SMODS.optional_features|(fun(): SMODS.optional_features) Table of optional SMODS features to enable inserted into `SMODS.optional_features`. If function, returns table. +---@field save_mod_config? fun(mod: Mod) If defined, this funciton will be called over `SMODS.save_mod_config` when SMODS goes to save this mod's config. ---@field meta_mod? boolean Marked as a "meta mod" by SMODS. Only "Steamodded", "Lovely", and "Balatro" are provided by default. ---@type table SMODS.Mods = {} ---@type Mod|table? ---- The current mod being loaded. +--- The current mod being loaded. SMODS.current_mod = {} SMODS.Mods["Steamodded"] = SMODS @@ -61,15 +65,15 @@ SMODS.Mods["Balatro"] = { } ---@param modsDirectory string ---- Loads mods. +--- Loads mods. function loadMods(modsDirectory) end ---- Initializes Steamodded. +--- Initializes Steamodded. function initSteamodded() end ---- Injects all classes and items. +--- Injects all classes and items. function SMODS.injectItems() end ---@param class SMODS.GameObject|table --- Inject all SMODS Objects that are part of this class or a subclass. -function SMODS.injectObjects(class) end \ No newline at end of file +function SMODS.injectObjects(class) end diff --git a/Steamodded/lsp_def/ui.lua b/Steamodded/lsp_def/ui.lua index 44c85f4..f30e438 100644 --- a/Steamodded/lsp_def/ui.lua +++ b/Steamodded/lsp_def/ui.lua @@ -62,7 +62,7 @@ G.UIT = { -- UI Functions ---@param str string ----@return any? +---@return any --- Unpacks provided string. function STR_UNPACK(str) end @@ -81,7 +81,7 @@ function buildModDescTab(mod) end --- Creates UIBox for Mod's "Additions" tab. function buildAdditionsTab(mod) end ----@param e table? +---@param e? table --- Button function for "Other" collections menu G.FUNCS.your_collection_other_gameobjects = function(e) end @@ -89,7 +89,7 @@ G.FUNCS.your_collection_other_gameobjects = function(e) end --- Creates UIBox for "Other" collections menu function create_UIBox_Other_GameObjects() end ----@param e table? +---@param e? table --- Button function for "Consumables" collections menu UIBox G.FUNCS.your_collection_consumables = function(e) end @@ -97,7 +97,7 @@ G.FUNCS.your_collection_consumables = function(e) end --- Creates UIBox for "Consumables" collections menu function create_UIBox_your_collection_consumables() end ----@param args table? +---@param args? table --- Pages button function for "Consumables" collection menu G.FUNCS.your_collection_consumables_page = function(args) end @@ -107,17 +107,17 @@ G.FUNCS.your_collection_consumables_page = function(args) end G.UIDEF.consumable_collection_page = function(page) end ---@param mod Mod ----@param current_page number? +---@param current_page? number ---@return UINode --- Creates UIBox for Mod's "Achievements" tab. function buildAchievementsTab(mod, current_page) end ----@param args table? +---@param args? table --- Pages button function for "Achievements" tab G.FUNCS.achievments_tab_page = function(args) end ---@param pool table[] ----@param set string? Only objects with matching set will be tallied. +---@param set? string Only objects with matching set will be tallied. ---@return {tally: 0|number, of: 0|number} --- Tallies all objects within `pool` that are discovered. function modsCollectionTally(pool, set) end @@ -127,7 +127,7 @@ function modsCollectionTally(pool, set) end --- Creates Mod tag UI for Mods list menu. function buildModtag(mod) end ----@param options table? +---@param options? table --- Opens "Mods" directory. function G.FUNCS.openModsDirectory(options) end @@ -144,7 +144,7 @@ function SMODS.save_mod_config(mod) end --- Saves all mod configs. function SMODS.save_all_config() end ----@param e table? +---@param e? table --- Exits mods tab. function G.FUNCS.exit_mods(e) end @@ -152,15 +152,15 @@ function G.FUNCS.exit_mods(e) end --- Creates UIBox for SMODS Menu. function create_UIBox_mods_button() end ----@param e table? +---@param e? table --- Updates achievements settings. function G.FUNCS.update_achievement_settings(e) end ----@param e table? +---@param e? table --- Button function for Steamodded Github link. function G.FUNCS.steamodded_github(e) end ----@param e table? +---@param e? table --- Updates UI to display SMODS menu. function G.FUNCS.mods_button(e) end @@ -189,7 +189,7 @@ function SMODS.GUI.DynamicUIManager.updateDynamicAreas(uiDefinitions) end --- EX: in this pane the 'modsList' node will contain the dynamic content which is defined in the function below function SMODS.GUI.staticModListContent() end ----@param page number? +---@param page? number ---@return UINode --- Creates mod list. function SMODS.GUI.dynamicModListContent(page) end @@ -243,10 +243,23 @@ function create_UIBox_your_collection_editions() end --- Creates UIBox for "Seals" collection menu function create_UIBox_your_collection_seals() end ----@param e table? +---@param e? table --- Button function for "Stickers" collection menu G.FUNCS.your_collection_stickers = function(e) end ---@return UINode --- Creates UIBox for "Stickers" collection menu function create_UIBox_your_collection_stickers() end + + +---@return UINode +---@param table +---@field scale? number Set scale of text +---@field colour? table HEX colour of the container +---@field type? string Type of scoring component - defaults to `'mult'` +---@field align? string Must be two letters, first indicates vertical alignment, second indicates horizontal alignment +---@field func? string Reference to function in `G.FUNCS` that controls changing the text - defaults to `'hand_'..type..'_UI_set'` +---@field text? string Key of value in `G.GAME.current_round.current_hand` - defaults to `type..'_text'` +---@field w? number Minimum width +---@field h? number Minimum height +function SMODS.GUI.score_container(args) end \ No newline at end of file diff --git a/Steamodded/lsp_def/utils.lua b/Steamodded/lsp_def/utils.lua index b147df1..6e8c716 100644 --- a/Steamodded/lsp_def/utils.lua +++ b/Steamodded/lsp_def/utils.lua @@ -2,87 +2,122 @@ --- Util Classes ---- Internal class referring args passed as `context` in a SMODS object's `calculate` function. ---- Not all arguments typed here are present in all contexts, see [Calculate Function](https://github.com/Steamodded/smods/wiki/calculate_functions#contexts) for details. ----@class CalcContext: table ----@field cardarea? CardArea|"unscored" The CardArea currently being checked. ----@field full_hand? Card[]|table[] All played or selected cards. ----@field scoring_hand? Card[]|table[] All scoring cards in played hand. ----@field scoring_name? string Key to the scoring poker hand. ----@field poker_hands? table All poker hand parts the played hand can form. ----@field other_card? Card|table The individual card being checked during scoring. ----@field other_joker? Card|table The individual Joker being checked during scoring. ----@field card_effects? table Table of effects that have been calculated. ----@field destroy_card? Card|table The individual card being checked for destruction. ----@field destroying_card? Card|table The individual card being checked for destruction. Only present when calculating G.play. ----@field removed? Card[]|table[] Table of destroyed playing cards. ----@field game_over? boolean Whether the run is lost or not. ----@field blind? Blind|table Current blind being selected. ----@field hook? boolean `true` when "The Hook" discards cards. ----@field card? Card|table The individual card being checked outside of scoring. ----@field cards? table[]|Card[] Table of cards representing how many cards were created. ----@field consumeable? Card|table The Consumable being used. Only a value when `context.using_consumeable` is `true`. ----@field blueprint_card? Card|table The card currently copying the eval effects. ----@field no_blueprint? true Effects akin to Blueprint or Brainstorm should not trigger in this context. ----@field other_context? CalcContext|table The context the last eval happened on. ----@field other_ret? table The return table from the last eval. ----@field before? true Check if `true` for effects that happen before hand scoring. ----@field after? true Check if `true` for effects that happen after hand scoring. ----@field main_scoring? true Check if `true` for effects that happen during scoring. ----@field individual? true Check if `true` for effects on individual playing cards during scoring. ----@field repetition? true Check if `true` for adding repetitions to playing cards. ----@field edition? true `true` for any Edition-specific context (e.x. context.pre_joker and context.post_joker). ----@field pre_joker? true Check if `true` for triggering editions on jokers before they score. ----@field post_joker? true Check if `true` for triggering editions on jokers after they score. ----@field joker_main? true Check if `true` for triggering normal scoring effects on Jokers. ----@field final_scoring_step? true Check if `true` for effects after cards are scored and before the score is totalled. ----@field remove_playing_cards? true Check if `true` for effects on removed cards. ----@field debuffed_hand? true Check if `true` for effects when playing a hand debuffed by a blind. ----@field end_of_round? true Check if `true` for effects at the end of the round. ----@field setting_blind? true Check if `true` for effects when the blind is selected. ----@field pre_discard? true Check if `true` for effects before cards are discarded. ----@field discard? true Check if `true` for effects on each individual card discarded. ----@field open_booster? true Check if `true` for effects when opening a Booster Pack. ----@field skipping_booster? true Check if `true` for effects after a Booster Pack is skipped. ----@field buying_card? true Check if `true` for effects after buying a card. ----@field selling_card? true Check if `true` for effects after selling a card. ----@field reroll_shop? true Check if `true` for effects after rerolling the shop. ----@field ending_shop? true Check if `true` for effects after leaving the shop. ----@field first_hand_drawn? true Check if `true` for effects after drawing the first hand. ----@field hand_drawn? true Check if `true` for effects after drawing a hand. ----@field using_consumeable? true Check if `true` for effects after using a Consumable. ----@field skip_blind? true Check if `true` for effects after skipping a blind. ----@field playing_card_added? true Check if `true` for effects after a playing card was added into the deck. ----@field check_enhancement? true Check if `true` for applying quantum enhancements. ----@field post_trigger? true Check if `true` for effects after another Joker is triggered. ----@field modify_scoring_hand? true Check if `true` for modifying the scoring hand. ----@field ending_booster? true Check if `true` for effects after a Booster Pack ends. ----@field starting_shop? true Check if `true` for effects when the shop is first opened. ----@field blind_disabled? true Check if `true` for effects when the blind is disabled. ----@field blind_defeated? true Check if `true` for effects when the blind is disabled. +--- Internal class referring args passed as `context` in a SMODS object's `calculate` function. +--- Not all arguments typed here are present in all contexts, see [Calculate Function](https://github.com/Steamodded/smods/wiki/calculate_functions#contexts) for details. +---@class CalcContext: table +---@field cardarea? CardArea|"unscored" The CardArea currently being checked. +---@field full_hand? Card[]|table[] All played or selected cards. +---@field scoring_hand? Card[]|table[] All scoring cards in played hand. +---@field scoring_name? PokerHands|string Key to the scoring poker hand. +---@field poker_hands? table All poker hand parts the played hand can form. +---@field main_eval? true `true` when no secondary card is evaluated. +---@field other_card? Card|table The individual card being checked during scoring. +---@field other_joker? Card|table The individual Joker being checked during scoring. +---@field card_effects? table Table of effects that have been calculated. +---@field destroy_card? Card|table The individual card being checked for destruction. +---@field destroying_card? Card|table The individual card being checked for destruction. Only present when calculating G.play. +---@field removed? Card[]|table[] Table of destroyed playing cards. +---@field game_over? boolean Whether the run is lost or not. +---@field beat_boss? boolean Whether a boss was defeated. +---@field blind? Blind|table Current blind being selected. +---@field hook? boolean `true` when "The Hook" discards cards. +---@field card? Card|table The individual card being checked outside of scoring. +---@field cards? table[]|Card[] Table of cards representing how many cards were created. +---@field consumeable? Card|table The Consumable being used. Only a value when `context.using_consumeable` is `true`. +---@field blueprint_card? Card|table The card currently copying the eval effects. +---@field no_blueprint? true Effects akin to Blueprint or Brainstorm should not trigger in this context. +---@field other_context? CalcContext|table The context the last eval happened on. +---@field other_ret? table The return table from the last eval. +---@field before? true Check if `true` for effects that happen before hand scoring. +---@field after? true Check if `true` for effects that happen after hand scoring. +---@field main_scoring? true Check if `true` for effects that happen during scoring. +---@field individual? true Check if `true` for effects on individual playing cards during scoring. +---@field repetition? true Check if `true` for adding repetitions to playing cards. +---@field edition? true `true` for any Edition-specific context (e.x. context.pre_joker and context.post_joker). +---@field pre_joker? true Check if `true` for triggering editions on jokers before they score. +---@field post_joker? true Check if `true` for triggering editions on jokers after they score. +---@field joker_main? true Check if `true` for triggering normal scoring effects on Jokers. +---@field final_scoring_step? true Check if `true` for effects after cards are scored and before the score is totalled. +---@field remove_playing_cards? true Check if `true` for effects on removed cards. +---@field debuffed_hand? true Check if `true` for effects when playing a hand debuffed by a blind. +---@field end_of_round? true Check if `true` for effects at the end of the round. +---@field setting_blind? true Check if `true` for effects when the blind is selected. +---@field pre_discard? true Check if `true` for effects before cards are discarded. +---@field discard? true Check if `true` for effects on each individual card discarded. +---@field open_booster? true Check if `true` for effects when opening a Booster Pack. +---@field skipping_booster? true Check if `true` for effects after a Booster Pack is skipped. +---@field buying_card? true Check if `true` for effects after buying a card. +---@field selling_card? true Check if `true` for effects after selling a card. +---@field reroll_shop? true Check if `true` for effects after rerolling the shop. +---@field ending_shop? true Check if `true` for effects after leaving the shop. +---@field first_hand_drawn? true Check if `true` for effects after drawing the first hand. +---@field hand_drawn? true Check if `true` for effects after drawing a hand. +---@field using_consumeable? true Check if `true` for effects after using a Consumable. +---@field skip_blind? true Check if `true` for effects after skipping a blind. +---@field playing_card_added? true Check if `true` for effects after a playing card was added into the deck. +---@field card_added? true Check if `true` for effects after a non-playing card was added into the deck. +---@field check_enhancement? true Check if `true` for applying quantum enhancements. +---@field post_trigger? true Check if `true` for effects after another Joker is triggered. +---@field modify_scoring_hand? true Check if `true` for modifying the scoring hand. +---@field ending_booster? true Check if `true` for effects after a Booster Pack ends. +---@field starting_shop? true Check if `true` for effects when the shop is first opened. +---@field blind_disabled? true Check if `true` for effects when the blind is disabled. +---@field blind_defeated? true Check if `true` for effects when the blind is disabled. ---@field press_play? true Check if `true` for effects when the Play button is pressed. ----@field debuff_card? Card|table The card being checked for if it should be debuffed. ----@field ignore_debuff? true Sets if `self.debuff` checks are ignored. ----@field debuff_hand? true Check if `true` for calculating if the played hand should be debuffed. ----@field check? true `true` when the blind is being checked for if it debuffs the played hand. ----@field stay_flipped? true Check if `true` for effects when a card is being drawn. ----@field to_area? CardArea|table CardArea the card is being drawn to. ----@field from_area? CardArea|table CardArea the card is being drawn from. ----@field modify_hand? true Check if `true` for modifying the chips and mult of the played hand. +---@field debuff_card? Card|table The card being checked for if it should be debuffed. +---@field ignore_debuff? true Sets if `self.debuff` checks are ignored. +---@field debuff_hand? true Check if `true` for calculating if the played hand should be debuffed. +---@field check? true `true` when the blind is being checked for if it debuffs the played hand. +---@field stay_flipped? true Check if `true` for effects when a card is being drawn. +---@field to_area? CardArea|table CardArea the card is being drawn to. +---@field from_area? CardArea|table CardArea the card is being drawn from. +---@field modify_hand? true Check if `true` for modifying the chips and mult of the played hand. +---@field drawing_cards? true `true` when cards are being drawn +---@field amount? number Used for in some contexts to specify a numerical amount. +---@field evaluate_poker_hand? integer Check if `true` for modifying the name, display name or contained poker hands when evaluating a hand. +---@field display_name? PokerHands|'Royal Flush'|string Display name of the scoring poker hand. +---@field mod_probability? true Check if `true` for effects that make additive or multiplicative modifications to probabilities. +---@field fix_probability? true Check if `true` for effects that set probabilities. +---@field pseudorandom_result? true Check if `true` for effects when a probability is rolled. +---@field numerator? number Current numerator for probabilty. +---@field denominator? number Current denominator for probabilty. +---@field trigger_obj? table Current object for probability. Not guaranteed to be a Card object. +---@field identifier? string Identifies the source of the probability roll. +---@field from_roll? true `true` when a roll is made (as opposed to getting the values to display). +---@field result? boolean Result of the probability roll. +---@field initial_scoring_step? true Check if `true` for scoring effects before cards are scored. +---@field joker_type_destroyed? true Check if `true` for effects when a non-playing card is destroyed. +---@field check_eternal? true Check if `true` for applying the eternal effect without the sticker being applied. +---@field trigger? table Source for the check. Not guaranteed to be a Card object. +---@field tag_added? Tag|table Check for effects when a Tag is added. +---@field tag_triggered? Tag|table Check for effects when a Tag is triggered. +---@field prevent_tag_trigger? Tag|table Check to prevent a Tag for being triggered. +---@field change_rank? true Check for effects when a card's rank changes. +---@field change_suit? true Check for effects when a card's suit changes. +---@field new_rank? number ID of the new rank the card changed to. +---@field old_rank? number ID of the old rank the card changed from. +---@field rank_increase? boolean `true` if rank increased. +---@field new_suit? Suits|string New suit the card changed to. +---@field old_suit? Suits|string Old suit the card changed from. +---@field round_eval? true Check if `true` for effects during round evaluation (cashout screen). +---@field money_altered? true Check if `true` for effects when the amount of money the player has changes. +---@field from_shop? true Check if `true` if money changed during the shop. +---@field from_consumeable? true Check if `true` if money changed by a consumable. +---@field from_scoring? true Check if `true` if money changed during scoring. --- Util Functions ---@param ... table ---@return table ----Flattens given arrays into one, then adds elements from each table to a new one. Skips duplicates. +---Flattens given arrays into one, then adds elements from each table to a new one. Skips duplicates. function SMODS.merge_lists(...) end ---- A table of SMODS feature that mods can choose to enable. +--- A table of SMODS feature that mods can choose to enable. ---@class SMODS.optional_features: table ----@field quantum_enhancements? boolean Enables "Quantum Enhancement" contexts. Cards can count as having multiple enhancements at once. ----@field retrigger_joker? boolean Enables "Joker Retrigger" contexts. Jokers can be retriggered by other jokers or effects. ----@field post_trigger? boolean Enables "Post Trigger" contexts. Allows calculating effects after a Joker has been calculated. ----@field cardareas? SMODS.optional_features.cardareas Enables additional CardArea calculation. +---@field quantum_enhancements? boolean Enables "Quantum Enhancement" contexts. Cards can count as having multiple enhancements at once. +---@field retrigger_joker? boolean Enables "Joker Retrigger" contexts. Jokers can be retriggered by other jokers or effects. +---@field post_trigger? boolean Enables "Post Trigger" contexts. Allows calculating effects after a Joker has been calculated. +---@field cardareas? SMODS.optional_features.cardareas Enables additional CardArea calculation. ---@class SMODS.optional_features.cardareas: table ---@field deck? boolean Enables "Deck Calculation". Decks are included in calculation. @@ -91,40 +126,53 @@ function SMODS.merge_lists(...) end ---@type SMODS.optional_features SMODS.optional_features = { cardareas = {} } ---- Inserts all SMODS features enabled by loaded mods into `SMODS.optional_features`. +--- Inserts all SMODS features enabled by loaded mods into `SMODS.optional_features`. function SMODS.get_optional_features() end ----@param context CalcContext|table ----@param return_table? table ----@return table +---@param context CalcContext|table +---@param return_table? table +---@return table? # Will use `return_table` over returning if provided. --- Used to calculate contexts across `G.jokers`, `scoring_hand` (if present), `G.play` and `G.GAME.selected_back`. --- Hook this function to add different areas to MOST calculations function SMODS.calculate_context(context, return_table) end +---@alias CardAreaTypes +---| 'joker' +---| 'playing_cards' +---| 'individual' + +---@param _type CardAreaTypes|string Type of CardAreas to check +---@param context CalcContext +---@param return_table? table +---@param args? table +---@return table +--- Calculates effects on cards across multiple cardareas based on provided `_type`. +function SMODS.calculate_card_areas(_type, context, return_table, args) end + ---@param card Card|table ---@param context CalcContext|table ---- Scores the provided `card`. +--- Scores the provided `card`. function SMODS.score_card(card, context) end ---@param context CalcContext|table ----@param scoring_hand Card[]|table[]? +---@param scoring_hand? Card[]|table[] --- Handles calculating the scoring hand. Defaults to `context.cardarea.cards` if `scoring_hand` is not provided. function SMODS.calculate_main_scoring(context, scoring_hand) end ---@param context CalcContext|table ---- Handles calculating end of round effects. +--- Handles calculating end of round effects. function SMODS.calculate_end_of_round_effects(context) end ---@param context CalcContext|table ---@param cards_destroyed Card[]|table[] ---@param scoring_hand Card[]|table[] ---- Handles calculating destroyed cards. +--- Handles calculating whether to destroy cards. Adds the destroyed cards to `cards_destroyed`. function SMODS.calculate_destroying_cards(context, cards_destroyed, scoring_hand) end ---@param effect table ---@param scored_card Card|table ---@param key string ----@param amount number|boolean +---@param amount number|boolean ---@param from_edition? boolean ---@return boolean|table? --- This function handles the calculation of each effect returned to evaluate play. @@ -133,11 +181,19 @@ function SMODS.calculate_individual_effect(effect, scored_card, key, amount, fro ---@param effect table ---@param scored_card Card|table ----@param from_edition? boolean +---@param from_edition? boolean ---@return table ---- Handles calculating effects on provided `scored_card`. +--- Handles calculating effects on provided `scored_card`. function SMODS.calculate_effect(effect, scored_card, from_edition, pre_jokers) end +---@param effect_table table +---@param key string +---@param card Card|table +---@param ret table +--- Internal helper for SMODS.calculate_effect. +--- Calculate one key of an effect table returned from eval_card. +function SMODS.calculate_effect_table_key(effect_table, key, card, ret) end + ---@param effects table ---@param card Card|table --- Used to calculate a table of effects generated in evaluate_play @@ -147,7 +203,7 @@ function SMODS.trigger_effects(effects, card) end ---@param context CalcContext|table ---@param _ret table ---@return number[] ---- Calculate retriggers on provided `card`. +--- Calculate retriggers on provided `card`. function SMODS.calculate_retriggers(card, context, _ret) end ---@param card Card|table @@ -157,122 +213,141 @@ function SMODS.calculate_retriggers(card, context, _ret) end function SMODS.calculate_repetitions(card, context, reps) end ---@param copier Card|table ----@param copied_card Card|table +---@param copied_card? Card|table ---@param context CalcContext|table ---@return table? --- Helper function to copy the ability of another joker. Useful for implementing Blueprint-like jokers. function SMODS.blueprint_effect(copier, copied_card, context) end ----@param _type string +---@type string? +--- Internal global variable for smart_level_up_hand +--- Holds the currently displayed hand type, +--- if it hasn't had mult/chips added +SMODS.displayed_hand = nil + +---@type boolean? +--- Internal global variable for smart_level_up_hand +--- True if scoring is ongoing (chips/mult/etc. are being displayed on the left) +SMODS.displaying_scoring = nil + +---@param card? Card|table +---@param hand PokerHands|string +---@param instant boolean +---@param amount? number +-- Like level_up_hand(), but takes care of calling update_hand_text(). +-- Tries to avoid calling update_hand_text() if unnecessary. +function SMODS.smart_level_up_hand(card, hand, instant, amount) end + +---@param _type CardAreaTypes|string ---@param _context string ---@return CardArea[]|table[] ---- Returns table of CardAreas. +--- Returns table of CardAreas. function SMODS.get_card_areas(_type, _context) end ---@param card Card|table ----@param extra_only boolean? Return table will not have the card's actual enhancement. ----@return table enhancements ---- Returns table of enhancements the provided `card` has. +---@param extra_only? boolean Return table will not have the card's actual enhancement. +---@return table enhancements +--- Returns table of enhancements the provided `card` has. function SMODS.get_enhancements(card, extra_only) end ---@param card Card|table ----@param key string ----@return boolean ---- Checks if this card a specific enhancement. +---@param key Enhancements|string +---@return boolean +--- Checks if this card a specific enhancement. function SMODS.has_enhancement(card, key) end ---@param card Card|table ---@param effects table ---@param context CalcContext|table ---- Calculates quantum Enhancements. Require `SMODS.optional_features.quantum_enhancements` to be `true`. +--- Calculates quantum Enhancements. Require `SMODS.optional_features.quantum_enhancements` to be `true`. function SMODS.calculate_quantum_enhancements(card, effects, context) end ---@param card Card|table ---@return boolean? ---- Check if the card shoud shatter. +--- Check if the card should shatter. function SMODS.shatters(card) end ---@param card Card|table ---@return boolean? ---- Checks if the card counts as having no suit. +--- Checks if the card counts as having no suit. function SMODS.has_no_suit(card) end ---@param card Card|table ---@return boolean? ---- Checks if the card counts as having all suits. +--- Checks if the card counts as having all suits. function SMODS.has_any_suit(card) end ---@param card Card|table ---@return boolean? ---- Checks if the card counts as having no rank. +--- Checks if the card counts as having no rank. function SMODS.has_no_rank(card) end ---@param card Card|table ---@return boolean? ---- Checks if the card should score. +--- Checks if the card should score. function SMODS.always_scores(card) end ---@param card Card|table ---- Checks if the card should not score. +--- Checks if the card should not score. function SMODS.never_scores(card) end ---@param card Card|table ---@param scoring_hand Card[]|table[] ---@return true? ---- Returns `true` if provided card is inside the scoring hand. +--- Returns `true` if provided card is inside the scoring hand. function SMODS.in_scoring(card, scoring_hand) end ---@nodiscard ---@param path string Path to the file (excluding `mod.path`) ----@param id string? Key to Mod ID. Default to `SMODS.current_mod` if not provided. ----@return function|nil +---@param id? string Key to Mod ID. Default to `SMODS.current_mod` if not provided. +---@return function|nil ---@return nil|string err ---- Loads the file from provided path. +--- Loads the file from provided path. function SMODS.load_file(path, id) end ----@param table table +---@param table table ---@return string ---- Shallow inspect a table. +--- Shallow inspect a table. function inspect(table) end ---@param table table ----@param indent number? ----@param depth number? Cap depth of 5 +---@param indent? number +---@param depth? number Cap depth of 5 ---@return string ---- Deep inspect a table. +--- Deep inspect a table. function inspectDepth(table, indent, depth) end ---@param func function ---@return string ---- Inspect a function. +--- Inspect a function. function inspectFunction(func) end ---- Handles saving discovery and unlocks. +--- Handles saving discovery and unlocks. function SMODS.SAVE_UNLOCKS() end ---@param ref_table table ---@param ref_value string ---@param loc_txt table|string ----@param key string? Key to the value within `loc_txt`. ---- Injects `loc_txt` into `G.localization`. +---@param key? string Key to the value within `loc_txt`. +--- Injects `loc_txt` into `G.localization`. function SMODS.process_loc_text(ref_table, ref_value, loc_txt, key) end ---@param path string ---- Handles injecting localization files. +--- Handles injecting localization files. function SMODS.handle_loc_file(path) end ---@param pool table[] ---@param center metatable ---@param replace boolean? ---- Injects an object into provided pool. +--- Injects an object into provided pool. function SMODS.insert_pool(pool, center, replace) end ---@param pool table ---@param key string ---- Removes an object from the provided pool. +--- Removes an object from the provided pool. function SMODS.remove_pool(pool, key) end ---- Juices up blind. +--- Juices up blind. function SMODS.juice_up_blind() end --- Change a card's suit, rank, or both. @@ -280,10 +355,10 @@ function SMODS.juice_up_blind() end --- It is recommended to wrap this function in `assert` to prevent unnoticed errors. ---@nodiscard ---@param card Card|table ----@param suit? string Key to the suit. ----@param rank? string Key to the rank. +---@param suit? Suits|string Key to the suit. +---@param rank? Ranks|string Key to the rank. ---@return Card|table? cardOrErr If successful the card. If it failed `nil`. ----@return string? msg If it failed, a message describing what went wrong. +---@return string? msg If it failed, a message describing what went wrong. function SMODS.change_base(card, suit, rank) end --- Modify a card's rank by the specified amount. @@ -293,65 +368,83 @@ function SMODS.change_base(card, suit, rank) end ---@param card Card|table ---@param amount number ---@return Card|table? cardOrErr If successful the card. If it failed `nil`. ----@return string? msg If it failed, a message describing what went wrong. +---@return string? msg If it failed, a message describing what went wrong. function SMODS.modify_rank(card, amount) end ---@param key string ----@param count_debuffed true? +---@param count_debuffed? true ---@return Card[]|table[] ---- Returns all cards matching provided `key`. +--- Returns all cards matching provided `key`. function SMODS.find_card(key, count_debuffed) end +---@alias CreateCardSets +---| 'Base' # Playing Cards without enhancements. +---| 'Enhanced' # Playing Cards with enhancements. +---| 'Playing Card' # Playing Cards with a random chance for enhancements. +---| 'Joker' +---| 'Tarot' +---| 'Planet' +---| 'Tarot_Planet' # Random pick between Tarot and Planet. +---| 'Spectral' +---| 'Consumeables' # Random pick between any consumable type. +---| 'Booster' +---| 'Voucher' + ---@class CreateCard ----@field set? string Set of the card. ----@field area? CardArea|table CardArea to emplace this card to. ----@field legendary? boolean Pools legendary cards, if applicable. ----@field rarity? number|string Only spawns cards with provided rarity, if applicable. ----@field skip_materialize? boolean Skips materialization animations. ----@field soulable? boolean Card could be replace by a legendary version, if applicable. ----@field key? string Created card is forced to have a center matching this key. ----@field key_append? string Appends this string to seeds. +---@field set? CreateCardSets|string Set of the card. +---@field area? CardArea|table CardArea to emplace this card to. +---@field legendary? boolean Pools legendary cards, if applicable. +---@field rarity? Rarities|number|string Only spawns cards with provided rarity, if applicable. +---@field skip_materialize? boolean Skips materialization animations. +---@field soulable? boolean Card could be replace by a legendary version, if applicable. +---@field key? string Created card is forced to have a center matching this key. +---@field key_append? string Appends this string to seeds. ---@field discover? boolean Discovers the card when created. ---@field bypass_discovery_center? boolean Creates the card's proper sprites and UI even if it hasn't been discovered. ----@field no_edition? boolean Ignore natural edition application. ----@field edition? string Apply this edition. ----@field enhancement? string Apply this enhancement. ----@field seal? string Apply this seal. ----@field stickers? string[] Apply all stickers in this array. +---@field no_edition? boolean Ignore natural edition application. +---@field edition? Editions|string Apply this edition. +---@field enhancement? Enhancements|string Apply this enhancement. +---@field seal? Seals|string Apply this seal. +---@field stickers? Stickers[]|string[] Apply all stickers in this array. +---@field allow_duplicates? boolean Allows duplicated cards to be created, even without Showman. +---@field rank? Ranks|string|integer Rank of the playing card. +---@field suit? Suits|string Suit of the playing card. +---@field front? string Front of the playing card. Ignores rank and suit. +---@field enhanced_poll? number Chance to pick 'Base' over 'Enhanced' with set 'Playing Card'. ---@param t CreateCard|table ---@return Card|table ---- Creates a card. +--- Creates a card. function SMODS.create_card(t) end ---@param t CreateCard|table ---@return Card|table ---- Adds + creates a card into provided `area`. +--- Adds + creates a card into provided `area`. function SMODS.add_card(t) end ---@param card Card|table ----@param debuff boolean|"reset"? +---@param debuff boolean|"reset"|'prevent_debuff'? ---@param source string? ---- Debuffs provided `card`. +--- Debuffs provided `card`. function SMODS.debuff_card(card, debuff, source) end ---@param card Card|table ---- Recalculate card debuffs. +--- Recalculate card debuffs. function SMODS.recalc_debuff(card) end ---- Restarts the game. +--- Restarts the game. function SMODS.restart_game() end ---@param obj SMODS.GameObject|table ---@param badges table[] ---- Adds the mod badge into the `badges` of the provided `obj` description UIBox. +--- Adds the mod badge into the `badges` of the provided `obj` description UIBox. function SMODS.create_mod_badges(obj, badges) end ---- Creates a localization dump. +--- Creates a localization dump. function SMODS.create_loc_dump() end ---@param t table ----@param indent string? +---@param indent? string ---@return string --- Serializes an input table in valid Lua syntax --- Keys must be of type number or string @@ -360,11 +453,16 @@ function serialize(t, indent) end ---@param s string ---@return string ---- Serializes provided string. -function serialize_strings(s) end +--- Serializes provided string. +function serialize_string(s) end ----@param t false|table? ----@param defaults false|table? +---@param t table +---@return table +--- Return a shallow copy of table `t`. +function SMODS.shallow_copy(t) end + +---@param t? false|table +---@param defaults? false|table ---@return false|table? --- Starting with `t`, insert any key-value pairs from `defaults` that don't already --- exist in `t` into `t`. Modifies `t`. @@ -380,7 +478,7 @@ function SMODS.merge_defaults(t, defaults) end ---@param num number ---@param precision number ---@return number ---- Rounds provided `num`. +--- Rounds provided `num`. function round_number(num, precision) end ---@param value number|string @@ -390,65 +488,75 @@ function format_ui_value(value) end ---@param ante number ---@return number ---- Returns the blind amount. +--- Returns the blind amount. function SMODS.get_blind_amount(ante) end ---- Converts save data for vanilla objects. +--- Converts save data for vanilla objects. function convert_save_data() end ---@param id string ---@return Mod[]|table[] ---- Returns table representing mods either matching provided `id` or can provide that mod. +--- Returns table representing mods either matching provided `id` or can provide that mod. function SMODS.find_mod(id) end ---@param tbl table ---@param val any ----@param mode ("index"|"i")|("value"|"v")? Sets if the value is compared with the indexes or values of the table. ----@param immediate boolean? ----Seatch for val anywhere deep in tbl. Return a table of finds, or the first found if args.immediate is provided. +---@param mode? ("index"|"i")|("value"|"v") Sets if the value is compared with the indexes or values of the table. +---@param immediate? boolean +---@return table +--- Searches for `val` anywhere deep in `tbl`. Return a table of finds, or the first found if args.immediate is provided. function SMODS.deepfind(tbl, val, mode, immediate) end ---- Enables debugging Joker calculations. +--- Enables debugging Joker calculations. function SMODS.debug_calculation() end ---@param card Card|table ---@param pack SMODS.Booster|table ---@return boolean ---- Controls if the card should be selectable from a Booster Pack. +--- Controls if the card should be selectable from a Booster Pack. function Card.selectable_from_pack(card, pack) end ---@param pool (string|"UNAVAILABLE")[] ---@return number ---- Returns size of the provided pool (excluding `"UNAVAILABLE"`). +--- Returns size of the provided pool (excluding `"UNAVAILABLE"`). function SMODS.size_of_pool(pool) end ---@param vouchers {[number]: table, spawn: table}? ---@return {[number]: table, spawn: table} vouchers ---- Returns next vouchers to spawn. +--- Returns the next vouchers to spawn. function SMODS.get_next_vouchers(vouchers) end ---@param key string ---@return Card|table voucher ---- Adds a Voucher with matching `key` to the shop. -function SMODS.add_voucher_to_shop(key) end +--- Adds a Voucher with matching `key` to the shop. +--- If dont_save is true the Voucher will not return in the next shop +function SMODS.add_voucher_to_shop(key, dont_save) end ---@param mod number ---- Modifies the Voucher shop limit by `mod`. +--- Modifies the Voucher shop limit by `mod`. function SMODS.change_voucher_limit(mod) end ----@param key string +---@param key string ---@return Card|table booster ---- Adds a Booster Pack with matching `key` to the shop. +--- Adds a Booster Pack with matching `key` to the shop. function SMODS.add_booster_to_shop(key) end ---@param mod number ---- Modifies the Booster Pack shop limit by `mod`. +--- Modifies the Booster Pack shop limit by `mod`. function SMODS.change_booster_limit(mod) end ---@param mod number ---- Modifies the current amount of free shop rerolls by `mod`. +--- Modifies the current amount of free shop rerolls by `mod`. function SMODS.change_free_rerolls(mod) end +---@param mod number +--- Modifies the amount of cards you are allowed to play by `mod`. +function SMODS.change_play_limit(mod) end + +---@param mod number +--- Modifies the amount of cards you are allowed to discard by `mod`. +function SMODS.change_discard_limit(mod) end + ---@param message string ---@param logger? string --- Prints to the console at "DEBUG" level @@ -474,24 +582,137 @@ function sendErrorMessage(message, logger) end --- Prints to the console at "FATAL" level function sendFatalMessage(message, logger) end ----@param level string ----@param logger string ----@param message string ---- Sends the provided `message` to debug console. +---@param level string +---@param logger string +---@param message string +--- Sends the provided `message` to debug console. function sendMessageToConsole(level, logger, message) end ---@param val number ---@return string ---- Returns a signed `val`. +--- Returns a signed `val` by +--- prefixing with "+" if positive function SMODS.signed(val) end ---@param val number ---@return string ---- Returns a signed `val` with "$". +--- Returns string representing "$"`val`. +--- If `val` is negative, correctly adds "-" before "$". function SMODS.signed_dollars(val) end ---@param base number ---@param perma number ----@return number|0 # Returns 0 ---- Returns result of multiplying `base` and `perma`. +---@return number +--- Returns result of multiplying `base` and `perma + 1`. +--- Reproduces weird vanilla behavior of using 0 for no/negative x_mult. function SMODS.multiplicative_stacking(base, perma) end + +---@param card Card|table +---@param suit Suits|string +---@return boolean +--- Checks if the suit can be smeared (e.x. Smeared Joker). +function SMODS.smeared_check(card, suit) end + +---@param hand Card[]|table[] +---@param suit Suits|string +---@return boolean +--- Checks if the provided `hand` meets the conditions to trigger Seeing Double. +function SMODS.seeing_double_check(hand, suit) end + +---@param lines table +---@param args table +--- Handles localization description boxes. +function SMODS.localize_box(lines, args) end + +---@param multi_box table +---@return table multi_boxes +--- Returns all description boxes within `multi_box`. +function SMODS.get_multi_boxes(multi_box) end + +---@param cards Card|Card[] +---@param bypass_eternal boolean? +---@param immediate boolean? +--- Destroys the cards passed to the function, handling calculation events that need to happen +function SMODS.destroy_cards(cards, bypass_eternal, immediate) end + +---@param hand_space number +--- Used to draw cards to hand outside of the normal card draw +--- Allows context.drawing_cards to function +function SMODS.draw_cards(hand_space) end + +---@param ... table +---@return table +---Flattens given calculation returns into one, utilising `extra` tables. +function SMODS.merge_effects(...) end + +---@param trigger_obj? Card|table +---@param base_numerator number +---@param base_denominator number +---@param identifier? string optional seed key for associating results in loc_vars with in-game probability rolls +---@param from_roll? boolean +---@return number numerator +---@return number denominator +---@param no_mod boolean|nil optional boolean to bypass other probability modifying effects +--- Returns a *`numerator` in `denominator`* listed probability opportunely modified by in-game effects +--- starting from a *`base_numerator` in `base_denominator`* probability. +--- +--- Can be hooked for more complex probability behaviour. `trigger_obj` is optionally the object that queues the probability. +function SMODS.get_probability_vars(trigger_obj, base_numerator, base_denominator, identifier, from_roll, no_mod) end + +---@param trigger_obj? Card|table +---@param seed string|number +---@param base_numerator number +---@param base_denominator number +---@param identifier? string +---@param no_mod boolean|nil optional boolean to bypass other probability modifying effects +---@return boolean +--- Sets the seed to `seed` and runs a *`base_numerator` in `base_denominator`* listed probability check. +--- Returns `true` if the probability succeeds. You do not need to multiply `base_numerator` by `G.GAME.probabilities.normal`. +--- +--- Can be hooked to run code when a listed probability succeeds and/or fails. `trigger_obj` is optionally the object that queues the probability. +function SMODS.pseudorandom_probability(trigger_obj, seed, base_numerator, base_denominator, identifier, no_mod) end + +---@param handname PokerHands|string +---@return boolean +---Checks if handname is visible in the poker hands menu. +function SMODS.is_poker_hand_visible(handname) end + +---@param card Card|table +---@param trigger? Card|table +---@return boolean +--- Checks whether the card is eternal. +--- `trigger` is the card or effect that runs the check +function SMODS.is_eternal(card, trigger) end + +---@param card Card|table +---@param args? table|{ref_table: table, ref_value: string, scalar_value: string, scalar_table: table?, operation: string?} +---@return table? results +--- Tells Jokers that this card is scaling allowing for scaling detection +--- Can return scaling_value and scalar_value in results to change the scaling cards values +--- Args must contain `ref_table`, `ref_value`, and `scalar_value`. It may optionally contain `scalar_table`, used in place of `ref_table` for the `scalar_value`, and `operation` to designate the scaling operation, which defaults to `"+"` +function SMODS.scale_card(card, args) end + + +---@param prototype_obj SMODS.GameObject|table +---@param args table? +---@return boolean?, table? +--- Checks whether an object should be added to the pool. +--- i.e. the in_pool method doesn't exist or it returns `true` +function SMODS.add_to_pool(prototype_obj, args) end + + +---@param context CalcContext|table The context being pushed +---@param func string|nil The function/file from which the call originates +--- Pushes a context to the SMODS.context_stack. (Form: {context=context, count=[number of consecutive pushes]}) +function SMODS.push_to_context_stack(context, func) end + +---@param context CalcContext|table The context being popped +---@param func string|nil The function/file from which the call originates +--- Pop a context from the SMODS.context_stack. (Removes 1 from .count) +function SMODS.pop_from_context_stack(context, func) end + +---@return CalcContext|table|nil +--- Returns the second to last context from the SMODS.context_stack. +--- Useful for Seals/Enhancements determining whether a playing card was being individually evaluated, +--- when a Joker called (e.g.) SMODS.pseudorandom_probability(). +function SMODS.get_previous_context() end diff --git a/Steamodded/lsp_def/vanilla.lua b/Steamodded/lsp_def/vanilla.lua index ee37946..21418a1 100644 --- a/Steamodded/lsp_def/vanilla.lua +++ b/Steamodded/lsp_def/vanilla.lua @@ -250,4 +250,75 @@ function tally_sprite(pos, value, tooltip, suit) end ---@return table ---@return string key --- Sets the seed to `seed` and randomly selects a table within `_t`. -function pseudorandom_element(_t, seed, args) end \ No newline at end of file +function pseudorandom_element(_t, seed, args) end + +--- Vanilla Pools + +---@alias Enhancements +---| 'm_bonus' +---| 'm_mult' +---| 'm_wild' +---| 'm_glass' +---| 'm_steel' +---| 'm_stone' +---| 'm_gold' +---| 'm_lucky' + +---@alias Editions +---| 'e_foil' +---| 'e_holo' +---| 'e_polychrome' +---| 'e_negative' + +---@alias Seals +---| 'Red' +---| 'Blue' +---| 'Gold' +---| 'Purple' + +---@alias Stickers +---| 'perishable' +---| 'eternal' +---| 'rental' +---| 'pinned' + +---@alias PokerHands +---| 'Flush Five' +---| 'Flush House' +---| 'Five of a Kind' +---| 'Straight Flush' +---| 'Four of a Kind' +---| 'Full House' +---| 'Flush' +---| 'Straight' +---| 'Three of a Kind' +---| 'Two Pair' +---| 'Pair' +---| 'High Card' + +---@alias Ranks +---| '2' +---| '3' +---| '4' +---| '5' +---| '6' +---| '7' +---| '8' +---| '9' +---| '10' +---| 'Jack' +---| 'Queen' +---| 'King' +---| 'Ace' + +---@alias Suits +---| 'Hearts' +---| 'Diamonds' +---| 'Clubs' +---| 'Spades' + +---@alias Rarities +---| 'Legendary' +---| 'Rare' +---| 'Uncommon' +---| 'Common' \ No newline at end of file diff --git a/Steamodded/release.lua b/Steamodded/release.lua new file mode 100644 index 0000000..238bf80 --- /dev/null +++ b/Steamodded/release.lua @@ -0,0 +1 @@ +return "1.0.0~BETA-0827c-STEAMODDED" \ No newline at end of file diff --git a/Steamodded/src/card_draw.lua b/Steamodded/src/card_draw.lua index 089e421..ba6b54b 100644 --- a/Steamodded/src/card_draw.lua +++ b/Steamodded/src/card_draw.lua @@ -28,6 +28,7 @@ SMODS.DrawStep = SMODS.GameObject:extend { check_individual_condition = function(self, card, layer, k, v) if k == 'vortex' then return not not card.vortex == v end if k == 'facing' then return card.sprite_facing == v end + if k == 'front_hidden' then return not not card.front_hidden == v end return true end, check_conditions = function(self, card, layer) @@ -147,7 +148,7 @@ SMODS.DrawStep { order = -10, func = function(self, layer) --Draw the main part of the card - if (self.edition and self.edition.negative and not self.delay_edition) or (self.ability.name == 'Antimatter' and (self.config.center.discovered or self.bypass_discovery_center)) then + if (self.edition and self.edition.negative and (not self.delay_edition or self.delay_edition.negative)) or (self.ability.name == 'Antimatter' and (self.config.center.discovered or self.bypass_discovery_center)) then self.children.center:draw_shader('negative', nil, self.ARGS.send_to_shader) elseif not self:should_draw_base_shader() then -- Don't render base dissolve shader. @@ -190,14 +191,14 @@ SMODS.DrawStep { order = 0, func = function(self, layer) --Draw the main part of the card - if (self.edition and self.edition.negative and not self.delay_edition) or (self.ability.name == 'Antimatter' and (self.config.center.discovered or self.bypass_discovery_center)) then - if self.children.front and (self.ability.delayed or (self.ability.effect ~= 'Stone Card' and not self.config.center.replace_base_card)) then + if (self.edition and self.edition.negative and (not self.delay_edition or self.delay_edition.negative)) or (self.ability.name == 'Antimatter' and (self.config.center.discovered or self.bypass_discovery_center)) then + if self.children.front and (self.ability.delayed or not self:should_hide_front()) then self.children.front:draw_shader('negative', nil, self.ARGS.send_to_shader) end elseif not self:should_draw_base_shader() then -- Don't render base dissolve shader. elseif not self.greyed then - if self.children.front and (self.ability.delayed or (self.ability.effect ~= 'Stone Card' and not self.config.center.replace_base_card)) then + if self.children.front and (self.ability.delayed or not self:should_hide_front()) then self.children.front:draw_shader('dissolve') end end @@ -218,7 +219,7 @@ SMODS.DrawStep { end end end, - conditions = { vortex = false, facing = 'front' }, + conditions = { vortex = false, facing = 'front', front_hidden = false }, } SMODS.DrawStep { key = 'card_type_shader', @@ -240,21 +241,22 @@ SMODS.DrawStep { key = 'edition', order = 20, func = function(self, layer) - if self.edition and not self.delay_edition then + local edition = self.delay_edition or self.edition + if edition then for k, v in pairs(G.P_CENTER_POOLS.Edition) do - if self.edition[v.key:sub(3)] and v.shader then + if edition[v.key:sub(3)] and v.shader then if type(v.draw) == 'function' then v:draw(self, layer) else self.children.center:draw_shader(v.shader, nil, self.ARGS.send_to_shader) - if self.children.front and self.ability.effect ~= 'Stone Card' and not self.config.center.replace_base_card then + if self.children.front and not self:should_hide_front() then self.children.front:draw_shader(v.shader, nil, self.ARGS.send_to_shader) end end end end end - if (self.edition and self.edition.negative) or (self.ability.name == 'Antimatter' and (self.config.center.discovered or self.bypass_discovery_center)) then + if (edition and edition.negative) or (self.ability.name == 'Antimatter' and (self.config.center.discovered or self.bypass_discovery_center)) then self.children.center:draw_shader('negative_shine', nil, self.ARGS.send_to_shader) end end, @@ -266,6 +268,7 @@ SMODS.DrawStep { order = 30, func = function(self, layer) local seal = G.P_SEALS[self.seal] or {} + if self.ability.delay_seal then return end if type(seal.draw) == 'function' then seal:draw(self, layer) elseif self.seal then @@ -332,21 +335,20 @@ SMODS.DrawStep { if type(self.config.center.soul_pos.draw) == 'function' then self.config.center.soul_pos.draw(self, scale_mod, rotate_mod) - elseif self.ability.name == 'Hologram' then - self.hover_tilt = self.hover_tilt*1.5 - self.children.floating_sprite:draw_shader('hologram', nil, self.ARGS.send_to_shader, nil, self.children.center, 2*scale_mod, 2*rotate_mod) - self.hover_tilt = self.hover_tilt/1.5 - else - self.children.floating_sprite:draw_shader('dissolve',0, nil, nil, self.children.center,scale_mod, rotate_mod,nil, 0.1 + 0.03*math.sin(1.8*G.TIMERS.REAL),nil, 0.6) - self.children.floating_sprite:draw_shader('dissolve', nil, nil, nil, self.children.center, scale_mod, rotate_mod) + elseif self.children.floating_sprite then + if self.ability.name == 'Hologram' then + self.hover_tilt = self.hover_tilt*1.5 + self.children.floating_sprite:draw_shader('hologram', nil, self.ARGS.send_to_shader, nil, self.children.center, 2*scale_mod, 2*rotate_mod) + self.hover_tilt = self.hover_tilt/1.5 + else + self.children.floating_sprite:draw_shader('dissolve',0, nil, nil, self.children.center,scale_mod, rotate_mod,nil, 0.1 + 0.03*math.sin(1.8*G.TIMERS.REAL),nil, 0.6) + self.children.floating_sprite:draw_shader('dissolve', nil, nil, nil, self.children.center, scale_mod, rotate_mod) + end end if self.edition then - for k, v in pairs(G.P_CENTER_POOLS.Edition) do - if v.apply_to_float then - if self.edition[v.key:sub(3)] then - self.children.floating_sprite:draw_shader(v.shader, nil, nil, nil, self.children.center, scale_mod, rotate_mod) - end - end + local edition = G.P_CENTERS[self.edition.key] + if edition.apply_to_float and self.children.floating_sprite then + self.children.floating_sprite:draw_shader(edition.shader, nil, nil, nil, self.children.center, scale_mod, rotate_mod) end end end @@ -360,7 +362,7 @@ SMODS.DrawStep { func = function(self) if self.debuff then self.children.center:draw_shader('debuff', nil, self.ARGS.send_to_shader) - if self.children.front and (self.ability.delayed or (self.ability.effect ~= 'Stone Card' and not self.config.center.replace_base_card)) then + if self.children.front and (self.ability.delayed or not self:should_hide_front()) then self.children.front:draw_shader('debuff', nil, self.ARGS.send_to_shader) end end @@ -374,7 +376,7 @@ SMODS.DrawStep { func = function(self) if self.greyed then self.children.center:draw_shader('played', nil, self.ARGS.send_to_shader) - if self.children.front and (self.ability.delayed or (self.ability.effect ~= 'Stone Card' and not self.config.center.replace_base_card)) then + if self.children.front and (self.ability.delayed or not self:should_hide_front()) then self.children.front:draw_shader('played', nil, self.ARGS.send_to_shader) end end @@ -414,7 +416,7 @@ SMODS.DrawStep { local sticker_offset = self.sticker_offset or {} G.shared_stickers[self.sticker]:draw_shader('dissolve', nil, nil, true, self.children.center, nil, self.sticker_rotation, sticker_offset.x, sticker_offset.y) local stake = G.P_STAKES['stake_'..string.lower(self.sticker)] or {} - if stake.shiny then G.shared_stickers[self.sticker]:draw_shader('voucher', nil, self.ARGS.send_to_shader, true, self.children.center) end + if stake.shiny then G.shared_stickers[self.sticker]:draw_shader('voucher', nil, self.ARGS.send_to_shader, true, self.children.center, nil, self.sticker_rotation, sticker_offset.x, sticker_offset.y) end end end, conditions = { vortex = false, facing = 'back' }, @@ -460,4 +462,4 @@ function Card:draw(layer) for _, k in ipairs(SMODS.DrawStep.obj_buffer) do if SMODS.DrawSteps[k]:check_conditions(self, layer) then SMODS.DrawSteps[k].func(self, layer) end end -end \ No newline at end of file +end diff --git a/Steamodded/src/core.lua b/Steamodded/src/core.lua index 3ae1296..8fe2f0b 100644 --- a/Steamodded/src/core.lua +++ b/Steamodded/src/core.lua @@ -3,6 +3,7 @@ SMODS = {} MODDED_VERSION = require'SMODS.version' +RELEASE_VERSION = require'SMODS.release' SMODS.id = 'Steamodded' SMODS.version = MODDED_VERSION:gsub('%-STEAMODDED', '') SMODS.can_load = true diff --git a/Steamodded/src/crash_handler.lua b/Steamodded/src/crash_handler.lua index 989889e..2db6e3c 100644 --- a/Steamodded/src/crash_handler.lua +++ b/Steamodded/src/crash_handler.lua @@ -30,7 +30,7 @@ function loadStackTracePlus() local pcall, type, pairs, ipairs = pcall, type, pairs, ipairs local error = error - assert(debug, "debug table must be available at this point") + assert(debug, "Internal: Debug table must be available at this point") local io_open = io.open local string_gmatch = string.gmatch @@ -100,7 +100,7 @@ function loadStackTracePlus() -- Parses a line, looking for possible function definitions (in a very naïve way) -- Returns '(anonymous)' if no function name was found in the line local function ParseLine(line) - assert(type(line) == "string") + assert(type(line) == "string", ("Internal: line \"%s\" is type \"%s\", should be a string"):format(tostring(line), type(line))) -- print(line) local match = line:match("^%s*function%s+(%w+)") if match then @@ -673,6 +673,18 @@ function injectStackTrace() table.insert(err, "Invalid UTF-8 string in error message.") end + if V and SMODS and SMODS.save_game and V(SMODS.save_game or '0.0.0') ~= V(SMODS.version or '0.0.0') then + table.insert(err, 'This crash may be caused by continuing a run that was started on a previous version of Steamodded. Try creating a new run.') + end + + if V and V(MODDED_VERSION or '0.0.0') ~= V(RELEASE_VERSION or '0.0.0') then + table.insert(err, '\n\nDevelopment version of Steamodded detected! If you are not actively developing a mod, please try using the latest release instead.\n\n') + end + + if not V then + table.insert(err, '\nA bad lovely patch has resulted in this crash.\n') + end + local success, msg = pcall(getDebugInfoForCrash) if success and msg then table.insert(err, '\n' .. msg) diff --git a/Steamodded/src/game_object.lua b/Steamodded/src/game_object.lua index df60641..0354e0a 100644 --- a/Steamodded/src/game_object.lua +++ b/Steamodded/src/game_object.lua @@ -21,7 +21,7 @@ function loadAPIs() function SMODS.GameObject:__call(o) o = o or {} - assert(o.mod == nil) + assert(o.mod == nil, "Created object should not have \"mod\" field defined.") o.mod = SMODS.current_mod o.original_mod = o.mod setmetatable(o, self) @@ -172,7 +172,7 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. o.atlas = o.atlas or o.set if o._discovered_unlocked_overwritten then - assert(o._saved_d_u) + assert(o._saved_d_u, ("Internal: original discovery/unlocked state for object \"%s\" should have been saved at this point."):format(o and o.key or "UNKNOWN")) o.discovered, o.unlocked = o._d, o._u o._discovered_unlocked_overwritten = false else @@ -273,6 +273,50 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. return res end + ------------------------------------------------------------------------------------------------- + ----- API CODE GameObject.Font + ------------------------------------------------------------------------------------------------- + + SMODS.Fonts = {} + SMODS.Font = SMODS.GameObject:extend { + obj_table = SMODS.Fonts, + set = 'Fonts', + obj_buffer = {}, + disable_mipmap = false, + required_params = { + 'key', + 'path', + }, + render_scale = 200, + TEXT_HEIGHT_SCALE = 0.83, + TEXT_OFFSET = {x = 0, y = 0}, + FONTSCALE = 0.1, + squish = 1, + DESCSCALE = 1, + register = function(self) + if self.registered then + sendWarnMessage(('Detected duplicate register call on object %s'):format(self.key), self.set) + return + end + self.name = self.key + SMODS.Font.super.register(self) + end, + inject = function(self) + local file_path = self.path + if file_path == 'DEFAULT' then return end + + self.full_path = (self.mod and self.mod.path or SMODS.path) .. + 'assets/fonts/' .. file_path + local file_data = assert(NFS.newFileData(self.full_path), + ('Failed to collect file data for Font %s'):format(self.key)) + self.FONT = assert(love.graphics.newFont(file_data, self.render_scale or G.TILESIZE), + ('Failed to initialize font data for Font %s'):format(self.key)) + + end, + process_loc_text = function() end, + } + + ------------------------------------------------------------------------------------------------- ----- API CODE GameObject.Language ------------------------------------------------------------------------------------------------- @@ -294,7 +338,7 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. local data = assert(NFS.newFileData(self.mod.path .. 'assets/fonts/' .. self.font.file), ('Failed to collect file data for font of language %s'):format(self.key)) self.font.FONT = love.graphics.newFont(data, self.font.render_scale) elseif type(self.font) ~= 'table' then - self.font = G.FONTS[type(self.font) == 'number' and self.font or 1] or G.FONTS[1] + self.font = SMODS.Fonts[self.font] or G.FONTS[type(self.font) == 'number' and self.font or 1] or G.FONTS[1] end G.LANGUAGES[self.key] = self if self.key == (G.SETTINGS.real_language or G.SETTINGS.language) then G.LANG = self end @@ -425,7 +469,7 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. self.replace_sounds[replace] = { key = self.key, times = times, args = args } end -- TODO detect music state based on if select_music_track exists - assert(not self.select_music_track or self.key:find('music')) + assert(not self.select_music_track or self.key:find('music'), ("Object \"%s\" has a defined \"select_music_track\" but is not a music track."):format(self.key)) SMODS.Sound.super.register(self) end, inject = function(self) @@ -633,11 +677,14 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. function SMODS.setup_stake(i) local applied_stakes = SMODS.build_stake_chain(G.P_CENTER_POOLS.Stake[i]) + G.GAME.applied_stakes = {} for stake, _ in pairs(applied_stakes) do if G.P_CENTER_POOLS['Stake'][stake].modifiers then G.P_CENTER_POOLS['Stake'][stake].modifiers() end + table.insert(G.GAME.applied_stakes, stake) end + table.sort(G.GAME.applied_stakes) end --Register vanilla stakes @@ -883,9 +930,16 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. for _, v in pairs(SMODS.Rarities) do if v.pools and v.pools[self.key] and not injected_rarities[v.key] then SMODS.inject_rarity(self, v) end end + if self.cards then + for k, v in pairs(G.P_CENTERS) do + if self.cards[k] then self:inject_card(v) end + end + end end, inject_card = function(self, center) if center.set ~= self.key then SMODS.insert_pool(G.P_CENTER_POOLS[self.key], center) end + if not center.pools then center.pools = {} end + center.pools[self.key] = true local default_rarity_check = {["Common"] = 1, ["Uncommon"] = 2, ["Rare"] = 3, ["Legendary"] = 4} if self.rarities and center.rarity and self.rarity_pools[default_rarity_check[center.rarity] or center.rarity] then SMODS.insert_pool(self.rarity_pools[default_rarity_check[center.rarity] or center.rarity], center) @@ -893,6 +947,7 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. end, delete_card = function(self, center) if center.set ~= self.key then SMODS.remove_pool(G.P_CENTER_POOLS[self.key], center.key) end + if center.pools then center.pools[self.key] = nil end local default_rarity_check = {["Common"] = 1, ["Uncommon"] = 2, ["Rare"] = 3, ["Legendary"] = 4} if self.rarities and center.rarity and self.rarity_pools[default_rarity_check[center.rarity] or center.rarity] then SMODS.remove_pool(self.rarity_pools[default_rarity_check[center.rarity] or center.rarity], center.key) @@ -916,6 +971,7 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. SMODS.ConsumableTypes = {} SMODS.ConsumableType = SMODS.ObjectType:extend { ctype_buffer = {}, + visible_buffer = {}, set = 'ConsumableType', required_params = { 'key', @@ -926,7 +982,7 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. collection_rows = { 6, 6 }, create_UIBox_your_collection = function(self) local type_buf = {} - for _, v in ipairs(SMODS.ConsumableType.ctype_buffer) do + for _, v in ipairs(SMODS.ConsumableType.visible_buffer) do if not v.no_collection and (not G.ACTIVE_MOD_UI or modsCollectionTally(G.P_CENTER_POOLS[v]).of > 0) then type_buf[#type_buf + 1] = v end end return SMODS.card_collection_UIBox(G.P_CENTER_POOLS[self.key], self.collection_rows, { back_func = #type_buf>3 and 'your_collection_consumables' or nil }) @@ -935,6 +991,7 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. SMODS.ConsumableType.super.register(self) if self:check_dependencies() then SMODS.ConsumableType.ctype_buffer[#SMODS.ConsumableType.ctype_buffer+1] = self.key + if not self.no_collection then SMODS.ConsumableType.visible_buffer[#SMODS.ConsumableType.visible_buffer + 1] = self.key end end end, inject = function(self) @@ -943,6 +1000,7 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. G.localization.descriptions[self.key] = G.localization.descriptions[self.key] or {} G.C.SET[self.key] = self.primary_colour G.C.SECONDARY_SET[self.key] = self.secondary_colour + G.C.UI[self.key] = self.text_colour or G.C.UI.TEXT_LIGHT G.FUNCS['your_collection_' .. string.lower(self.key) .. 's'] = function(e) G.SETTINGS.paused = true G.FUNCS.overlay_menu { @@ -1062,9 +1120,11 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. key = self.key, set = self.set, nodes = desc_nodes, + AUT = full_UI_table, vars = specific_vars or {} } + if target.vars.is_info_queue then target.is_info_queue = true; target.vars.is_info_queue = nil end local res = {} if self.loc_vars and type(self.loc_vars) == 'function' then res = self:loc_vars(info_queue, card) or {} @@ -1074,6 +1134,7 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. target.scale = res.scale target.text_colour = res.text_colour end + if desc_nodes == full_UI_table.main and not full_UI_table.name then full_UI_table.name = self.set == 'Enhanced' and 'temp_value' or localize { type = 'name', set = target.set, key = res.name_key or target.key, nodes = full_UI_table.name, vars = res.name_vars or target.vars or {} } elseif desc_nodes ~= full_UI_table.main and not desc_nodes.name and self.set ~= 'Enhanced' then @@ -1081,12 +1142,14 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. end if specific_vars and specific_vars.debuffed and not res.replace_debuff then target = { type = 'other', key = 'debuffed_' .. - (specific_vars.playing_card and 'playing_card' or 'default'), nodes = desc_nodes } + (specific_vars.playing_card and 'playing_card' or 'default'), nodes = desc_nodes, AUT = full_UI_table, } end if res.main_start then desc_nodes[#desc_nodes + 1] = res.main_start end + localize(target) + if res.main_end then desc_nodes[#desc_nodes + 1] = res.main_end end @@ -1289,7 +1352,7 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. SMODS.process_loc_text(G.localization.misc.dictionary, 'k_booster_group_'..self.key, self.loc_txt, 'group_name') end, loc_vars = function(self, info_queue, card) - return { vars = {card.ability.choose, card.ability.extra} } + return { vars = {math.min(card.ability.choose + (G.GAME.modifiers.booster_choice_mod or 0), math.max(1, card.ability.extra + (G.GAME.modifiers.booster_size_mod or 0))), math.max(1, card.ability.extra + (G.GAME.modifiers.booster_size_mod or 0))} } end, generate_ui = function(self, info_queue, card, desc_nodes, specific_vars, full_UI_table) if not card then @@ -1299,8 +1362,10 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. type = 'other', key = self.key, nodes = desc_nodes, + AUT = full_UI_table, vars = {} } + if target.vars.is_info_queue then target.is_info_queue = true; target.vars.is_info_queue = nil end local res = {} if self.loc_vars and type(self.loc_vars) == 'function' then res = self:loc_vars(info_queue, card) or {} @@ -1366,12 +1431,12 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. ease_background_colour{new_colour = G.C.FILTER, special_colour = G.C.BLACK, contrast = 2} end, create_UIBox = function(self) - local _size = SMODS.OPENED_BOOSTER.ability.extra + local _size = math.max(1, SMODS.OPENED_BOOSTER.ability.extra + (G.GAME.modifiers.booster_size_mod or 0)) G.pack_cards = CardArea( G.ROOM.T.x + 9 + G.hand.T.x, G.hand.T.y, math.max(1,math.min(_size,5))*G.CARD_W*1.1, 1.05*G.CARD_H, - {card_limit = _size, type = 'consumeable', highlight_limit = 1}) + {card_limit = _size, type = 'consumeable', highlight_limit = 1, negative_info = true}) local t = {n=G.UIT.ROOT, config = {align = 'tm', r = 0.15, colour = G.C.CLEAR, padding = 0.15}, nodes={ {n=G.UIT.R, config={align = "cl", colour = G.C.CLEAR,r=0.15, padding = 0.1, minh = 2, shadow = true}, nodes={ @@ -1409,7 +1474,7 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. local pack_loc_vars = function(self, info_queue, card) local cfg = (card and card.ability) or self.config return { - vars = { cfg.choose, cfg.extra }, + vars = { math.min(cfg.choose + (G.GAME.modifiers.booster_choice_mod or 0), math.max(1, cfg.extra + (G.GAME.modifiers.booster_size_mod or 0))), math.max(1, cfg.extra + (G.GAME.modifiers.booster_size_mod or 0)) }, key = self.key:sub(1, -3), } end @@ -1478,7 +1543,7 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. if G.GAME.used_vouchers.v_telescope and i == 1 then local _planet, _hand, _tally = nil, nil, 0 for k, v in ipairs(G.handlist) do - if G.GAME.hands[v].visible and G.GAME.hands[v].played > _tally then + if SMODS.is_poker_hand_visible(v) and G.GAME.hands[v].played > _tally then _hand = v _tally = G.GAME.hands[v].played end @@ -1608,6 +1673,7 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. class_prefix = 'bl', debuff = {}, vars = {}, + config = {}, dollars = 5, mult = 2, atlas = 'blind_chips', @@ -1642,16 +1708,18 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. }) SMODS.Blind:take_ownership('wheel', { loc_vars = function(self) - return { vars = { G.GAME.probabilities.normal } } + return { vars = { SMODS.get_probability_vars(self, 1, 7, 'wheel') } } end, collection_loc_vars = function(self) - return { vars = { '1' }} + return { vars = { '1', '7' }} end, process_loc_text = function(self) local text = G.localization.descriptions.Blind[self.key].text[1] if string.sub(text, 1, 3) ~= '#1#' then G.localization.descriptions.Blind[self.key].text[1] = "#1#"..text end + -- Is this too much hacky? + G.localization.descriptions.Blind[self.key].text[1] = string.gsub(G.localization.descriptions.Blind[self.key].text[1], "7", "#2#") SMODS.Blind.process_loc_text(self) end, get_loc_debuff_text = function() return G.GAME.blind.loc_debuff_text end, @@ -1696,8 +1764,10 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. set = 'Other', key = self.key:lower()..'_seal', nodes = desc_nodes, + AUT = full_UI_table, vars = specific_vars or {}, } + if target.vars.is_info_queue then target.is_info_queue = true; target.vars.is_info_queue = nil end local res = {} if self.loc_vars and type(self.loc_vars) == 'function' then res = self:loc_vars(info_queue, card) or {} @@ -1813,7 +1883,8 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. ranks = {'Ace', 'King', 'Queen', 'Jack', '10', '9', '8', '7', '6', '5', '4', '3', '2'}, display_ranks = {'King', 'Queen', 'Jack'}, atlas = self.hc_atlas, - pos_style = 'deck' + pos_style = 'deck', + hc_default = true } or nil, } } @@ -2178,7 +2249,7 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. func = function() for i = #destroyed_cards, 1, -1 do local card = destroyed_cards[i] - if card.ability.name == 'Glass Card' then + if SMODS.shatters(card) then card:shatter() else card:start_dissolve(nil, i ~= #destroyed_cards) @@ -2445,6 +2516,19 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. end } + -- weird hook to artificially initialize G.collab_credits early + -- this previously used a local recursive function, which broke modded languages + SMODS.init_collab_credits = true + local ps_ref = Game.prep_stage + function Game:prep_stage(new_stage, new_state, new_game_obj) + ps_ref(self, new_stage, new_state, new_game_obj) + if not G.collab_credits then + G.FUNCS.show_credits() + SMODS.init_collab_credits = nil + G.FUNCS:exit_overlay_menu() + end + end + for suitName, options in pairs(G.COLLABS.options) do SMODS.DeckSkin{ key = options[1]..'_'..suitName, @@ -2488,6 +2572,21 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. hc_default = true, }, }, + generate_ds_card_ui = function(card, deckskin, palette, info_queue, desc_nodes, specific_vars, full_UI_table) + for k, v in pairs(G.collab_credits) do + if v.artist and deckskin.key == v.art and (card.base.value == "Jack" or card.base.value == "Queen" or card.base.value == "King") then + localize{type = 'other', key = 'artist', nodes = desc_nodes, vars = {}} + localize{type = 'other', key = 'artist_credit', nodes = desc_nodes, vars = { v.artist }} + end + end + end, + has_ds_card_ui = function(card, deckskin, palette) + for k, v in pairs(G.collab_credits) do + if v.artist and deckskin.key == v.art and (card.base.value == "Jack" or card.base.value == "Queen" or card.base.value == "King") then + return true + end + end + end } end end @@ -2503,6 +2602,50 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. G:save_settings() end + ------------------------------------------------------------------------------------------------- + ----- API CODE GameObject.JimboQuip + ------------------------------------------------------------------------------------------------- + + SMODS.JimboQuips = {} + SMODS.JimboQuip = SMODS.GameObject:extend { + obj_table = SMODS.JimboQuips, + obj_buffer = {}, + required_params = { + 'key' + }, + set = 'JimboQuip', + process_loc_text = function(self) + SMODS.process_loc_text(G.localization.misc.quips, self.key:lower(), self.loc_txt) + end, + register = function(self) + if self.registered then + sendWarnMessage(('Detected duplicate register call on JimboQuip %s'):format(self.key:lower()), self.set) + return + end + if self:check_dependencies() then + self.obj_buffer[#self.obj_buffer + 1] = self.key:lower() + self.obj_table[self.key:lower()] = self + self.registered = true + end + end, + inject = function(self) + self.extra = self.extra or {center = 'j_joker'} + end + } + + for i=1,10 do + SMODS.JimboQuip{ + key = "lq_"..tostring(i), + type = 'loss', + } + end + for i=1,7 do + SMODS.JimboQuip{ + key = "wq_"..tostring(i), + type = 'win', + } + end + ------------------------------------------------------------------------------------------------- ----- API CODE GameObject.PokerHand ------------------------------------------------------------------------------------------------- @@ -2575,7 +2718,7 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. } SMODS.PokerHandPart { key = '_straight', - func = function(hand) return get_straight(hand, next(SMODS.find_card('j_four_fingers')) and 4 or 5, not not next(SMODS.find_card('j_shortcut'))) end + func = function(hand) return get_straight(hand, SMODS.four_fingers('straight'), SMODS.shortcut(), SMODS.wrap_around_straight()) end } SMODS.PokerHandPart { key = '_flush', @@ -2657,6 +2800,7 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. vouchers = {}, restrictions = { banned_cards = {}, banned_tags = {}, banned_other = {} }, unlocked = function(self) return true end, + calculate = function (self, context) end, class_prefix = 'c', process_loc_text = function(self) SMODS.process_loc_text(G.localization.misc.challenge_names, self.key, self.loc_txt, 'name') @@ -2738,8 +2882,10 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. key = self.key, set = self.set, nodes = desc_nodes, + AUT = full_UI_table, vars = specific_vars } + if target.vars.is_info_queue then target.is_info_queue = true; target.vars.is_info_queue = nil end local res = {} if self.loc_vars and type(self.loc_vars) == 'function' then -- card is actually a `Tag` here @@ -2825,6 +2971,16 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. end, apply = function(self, card, val) card.ability[self.key] = val + if val and self.config and next(self.config) then + card.ability[self.key] = {} + for k, v in pairs(self.config) do + if type(v) == 'table' then + card.ability[self.key][k] = copy_table(v) + else + card.ability[self.key][k] = v + end + end + end end } @@ -2937,13 +3093,10 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. -- if true, enhanced card is any suit -- always_scores -- if true, card always scores - -- loc_subtract_extra_chips - -- During tooltip generation, number of chips to subtract from displayed extra chips. - -- Use if enhancement already displays its own chips. -- Future work: use ranks() and suits() for better control register = function(self) self.config = self.config or {} - assert(not (self.no_suit and self.any_suit)) + assert(not (self.no_suit and self.any_suit), "Cannot have both \"no_suit\" and \"any_suit\" defined in a SMODS.Enhancement object.") if self.no_rank then self.overrides_base_rank = true end SMODS.Enhancement.super.register(self) end, @@ -2963,33 +3116,7 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. localize { type = 'other', key = 'card_extra_chips', nodes = desc_nodes, vars = { SMODS.signed(remaining_bonus_chips) } } end end - if specific_vars and specific_vars.bonus_x_chips then - localize{type = 'other', key = 'card_x_chips', nodes = desc_nodes, vars = {specific_vars.bonus_x_chips}} - end - if specific_vars and specific_vars.bonus_mult then - localize{type = 'other', key = 'card_extra_mult', nodes = desc_nodes, vars = {SMODS.signed(specific_vars.bonus_mult)}} - end - if specific_vars and specific_vars.bonus_x_mult then - localize{type = 'other', key = 'card_x_mult', nodes = desc_nodes, vars = {specific_vars.bonus_x_mult}} - end - if specific_vars and specific_vars.bonus_h_chips then - localize{type = 'other', key = 'card_extra_h_chips', nodes = desc_nodes, vars = {SMODS.signed(specific_vars.bonus_h_chips)}} - end - if specific_vars and specific_vars.bonus_x_chips then - localize{type = 'other', key = 'card_h_x_chips', nodes = desc_nodes, vars = {specific_vars.bonus_h_x_chips}} - end - if specific_vars and specific_vars.bonus_h_mult then - localize{type = 'other', key = 'card_extra_h_mult', nodes = desc_nodes, vars = {SMODS.signed(specific_vars.bonus_h_mult)}} - end - if specific_vars and specific_vars.bonus_h_x_mult then - localize{type = 'other', key = 'card_h_x_mult', nodes = desc_nodes, vars = {specific_vars.bonus_h_x_mult}} - end - if specific_vars and specific_vars.bonus_p_dollars then - localize{type = 'other', key = 'card_extra_p_dollars', nodes = desc_nodes, vars = {SMODS.signed_dollars(specific_vars.bonus_p_dollars)}} - end - if specific_vars and specific_vars.bonus_h_dollars then - localize{type = 'other', key = 'card_extra_h_dollars', nodes = desc_nodes, vars = {SMODS.signed_dollars(specific_vars.bonus_h_dollars)}} - end + SMODS.localize_perma_bonuses(specific_vars, desc_nodes) end, -- other methods: -- calculate(self, context, effect) @@ -3028,12 +3155,21 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. SMODS.Enhancement:take_ownership('glass', { calculate = function(self, card, context) - if context.destroy_card and context.cardarea == G.play and context.destroy_card == card and pseudorandom('glass') < G.GAME.probabilities.normal/card.ability.extra then + if context.destroy_card and context.cardarea == G.play and context.destroy_card == card and SMODS.pseudorandom_probability(card, 'glass', 1, card.ability.extra) then + card.glass_trigger = true return { remove = true } end end, }) + SMODS.Enhancement:take_ownership('lucky', { + loc_vars = function (self, info_queue, card) + local numerator_mult, denominator_mult = SMODS.get_probability_vars(card, 1, 5, 'lucky_mult') + local numerator_dollars, denominator_dollars = SMODS.get_probability_vars(card, 1, 15, 'lucky_money') + return {vars = {numerator_mult, card.ability.mult, denominator_mult, card.ability.p_dollars, denominator_dollars, numerator_dollars}} + end, + }) + ------------------------------------------------------------------------------------------------- ----- API CODE GameObject.Shader ------------------------------------------------------------------------------------------------- @@ -3093,6 +3229,14 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. on_load = nil, -- function (card) - modify card when it is loaded from the save file register = function(self) self.config = self.config or {} + if self.config.card_limit then + self.card_limit_keys = self.card_limit_keys or { + joker = string.sub(self.key, 3) .. '_SMODS_INTERNAL', + consumable = string.sub(self.key, 3) .. '_consumable' .. '_SMODS_INTERNAL', + playing_card = string.sub(self.key, 3) .. '_playing_card' .. '_SMODS_INTERNAL', + generic = string.sub(self.key, 3) .. '_generic' .. '_SMODS_INTERNAL' + } + end SMODS.Edition.super.register(self) end, process_loc_text = function(self) @@ -3106,8 +3250,28 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. create_fake_card = function(self) return { edition = copy_table(self.config), fake_card = true } end, + card_limit_key = function(self, card) + local area = (card.area or {}).config or {} + if area.negative_info then + if type(area.negative_info) == 'string' then + return self.card_limit_keys[area.negative_info] + end + if card.ability.set == 'Joker' then + return self.card_limit_keys['joker'] + elseif card.ability.consumeable then + return self.card_limit_keys['consumable'] + elseif card.ability.set == 'Default' or card.ability.set == 'Enhanced' then + return self.card_limit_keys['playing_card'] + end + end + return self.card_limit_keys['generic'] + end } + function SMODS.Edition:get_card_limit_key() + return G.P_CENTERS[self.edition.key]:card_limit_key(self) + end + -- TODO also, this should probably be a utility method in core -- card_area = pass the card area -- edition = boolean value @@ -3138,6 +3302,8 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. sound = { sound = "foil1", per = 1.2, vol = 0.4 }, weight = 20, extra_cost = 2, + in_shop = true, + vanilla = true, get_weight = function(self) return G.GAME.edition_rate * self.weight end, @@ -3169,6 +3335,8 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. sound = { sound = "holo1", per = 1.2 * 1.58, vol = 0.4 }, weight = 14, extra_cost = 3, + in_shop = true, + vanilla = true, get_weight = function(self) return G.GAME.edition_rate * self.weight end, @@ -3200,6 +3368,8 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. sound = { sound = "polychrome1", per = 1.2, vol = 0.7 }, weight = 3, extra_cost = 5, + in_shop = true, + vanilla = true, get_weight = function(self) return (G.GAME.edition_rate - 1) * G.P_CENTERS["e_negative"].weight + G.GAME.edition_rate * self.weight end, @@ -3231,6 +3401,8 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. sound = { sound = "negative", per = 1.5, vol = 0.4 }, weight = 3, extra_cost = 5, + in_shop = true, + vanilla = true, get_weight = function(self) return self.weight end, @@ -3320,6 +3492,8 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. process_loc_text = function(self) SMODS.process_loc_text(G.localization.misc.achievement_names, self.key, self.loc_txt, "name") SMODS.process_loc_text(G.localization.misc.achievement_descriptions, self.key, self.loc_txt, "description") + SMODS.process_loc_text(G.localization.misc.achievement_names, self.key.."_hidden", self.loc_txt, "hidden_name") + SMODS.process_loc_text(G.localization.misc.achievement_descriptions, self.key.."_hidden", self.loc_txt, "hidden_description") end, } @@ -3364,6 +3538,243 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. cycle = 1, } + ------------------------------------------------------------------------------------------------- + ------- API CODE GameObject.Scoring_Calculation + ------------------------------------------------------------------------------------------------- + + SMODS.Scoring_Parameters = {} + SMODS.Scoring_Parameter_Calculation = {} + SMODS.Scoring_Parameter = SMODS.GameObject:extend{ + set = 'Scoring_Parameters', + obj_table = SMODS.Scoring_Parameters, + obj_buffer = {}, + required_parameters = { + 'key', + 'default_value', + }, + inject = function(self) + self.colour = self.colour or G.C.UI_MULT + self.lick = {1, 1, 1, 1} + self.current = self.default_value + if self.calculation_keys then + SMODS.scoring_parameter_keys = SMODS.merge_lists({SMODS.scoring_parameter_keys, self.calculation_keys}) + SMODS.calculation_keys = SMODS.merge_lists({SMODS.scoring_parameter_keys, SMODS.other_calculation_keys}) + for _, calc_key in ipairs(self.calculation_keys) do + SMODS.Scoring_Parameter_Calculation[calc_key] = self.key + end + end + SMODS.Calculation_Controls[self.key] = false + end, + flame_handler = function(self) + return { + id = 'flame_'..self.key, + arg_tab = self.key..'_flames', + colour = self.colour, + accent = self.lick + } + end, + modify = function(self, amount) + self.current = self.current + amount + update_hand_text({delay = 0}, {[self.key] = self.current}) + end, + level_up_hand = function(self, amount, hand) + hand[self.key] = math.max(hand['s_'..self.key] + hand['l_'..self.key]*(hand.level - 1), 0) + end, + calc_effect = function(self, effect, scored_card, key, amount, from_edition) + if not SMODS.Calculation_Controls[self.key] then return end + if 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 + end + } + + SMODS.Scoring_Parameter({ + key = 'chips', + default_value = 0, + colour = G.C.UI_CHIPS, + calculation_keys = {'chips', 'h_chips', 'chip_mod', 'x_chips', 'xchips', 'Xchip_mod',}, + calc_effect = function(self, effect, scored_card, key, amount, from_edition) + if not SMODS.Calculation_Controls.chips then return end + if (key == 'chips' or key == 'h_chips' or key == 'chip_mod') and amount then + if effect.card and effect.card ~= scored_card then juice_card(effect.card) end + self:modify(amount) + if not effect.remove_default_message then + if from_edition then + card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = localize{type = 'variable', key = amount > 0 and 'a_chips' or 'a_chips_minus', vars = {amount}}, chip_mod = amount, colour = G.C.EDITION, edition = true}) + else + if key ~= 'chip_mod' then + if effect.chip_message then + card_eval_status_text(effect.message_card or effect.juice_card or scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.chip_message) + else + card_eval_status_text(effect.message_card or effect.juice_card or scored_card or effect.card or effect.focus, 'chips', amount, percent) + end + end + end + end + return true + end + if (key == 'x_chips' or key == 'xchips' or key == 'Xchip_mod') and amount ~= 1 then + if effect.card and effect.card ~= scored_card then juice_card(effect.card) end + self:modify(hand_chips * (amount - 1)) + if not effect.remove_default_message then + if from_edition then + card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = localize{type='variable',key= amount > 0 and 'a_xchips' or 'a_xchips_minus',vars={amount}}, Xchips_mod = amount, colour = G.C.EDITION, edition = true}) + else + if key ~= 'Xchip_mod' then + if effect.xchip_message then + card_eval_status_text(effect.message_card or effect.juice_card or scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.xchip_message) + else + card_eval_status_text(effect.message_card or effect.juice_card or scored_card or effect.card or effect.focus, 'x_chips', amount, percent) + end + end + end + end + return true + end + end, + modify = function(self, amount, skip) + if not skip then hand_chips = mod_chips(self.current + amount) end + self.current = (hand_chips or 0) + (skip or 0) + update_hand_text({delay = 0}, {chips = self.current}) + end + }) + + SMODS.Scoring_Parameter({ + key = 'mult', + default_value = 0, + colour = G.C.UI_MULT, + calculation_keys = {'mult', 'h_mult', 'mult_mod','x_mult', 'Xmult', 'xmult', 'x_mult_mod', 'Xmult_mod'}, + calc_effect = function(self, effect, scored_card, key, amount, from_edition) + if not SMODS.Calculation_Controls.mult then return end + if (key == 'mult' or key == 'h_mult' or key == 'mult_mod') and amount then + if effect.card and effect.card ~= scored_card then juice_card(effect.card) end + self:modify(amount) + if not effect.remove_default_message then + if from_edition then + card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = localize{type = 'variable', key = amount > 0 and 'a_mult' or 'a_mult_minus', vars = {amount}}, mult_mod = amount, colour = G.C.DARK_EDITION, edition = true}) + else + if key ~= 'mult_mod' then + if effect.mult_message then + card_eval_status_text(effect.message_card or effect.juice_card or scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.mult_message) + else + card_eval_status_text(effect.message_card or effect.juice_card or scored_card or effect.card or effect.focus, 'mult', amount, percent) + end + end + end + end + return true + end + if (key == 'x_mult' or key == 'xmult' or key == 'Xmult' or key == 'x_mult_mod' or key == 'Xmult_mod') and amount ~= 1 then + if effect.card and effect.card ~= scored_card then juice_card(effect.card) end + self:modify(mult * (amount - 1)) + if not effect.remove_default_message then + if from_edition then + card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = localize{type='variable',key= amount > 0 and 'a_xmult' or 'a_xmult_minus',vars={amount}}, Xmult_mod = amount, colour = G.C.EDITION, edition = true}) + else + if key ~= 'Xmult_mod' then + if effect.xmult_message then + card_eval_status_text(effect.message_card or effect.juice_card or scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.xmult_message) + else + card_eval_status_text(effect.message_card or effect.juice_card or scored_card or effect.card or effect.focus, 'x_mult', amount, percent) + end + end + end + end + return true + end + end, + modify = function(self, amount, skip) + if not skip then mult = mod_mult(self.current + amount) end + self.current = (mult or 0) + (skip or 0) + update_hand_text({delay = 0}, {mult = self.current}) + end + }) + + SMODS.Calculation_Controls = { + chips = true, + mult = true + } + SMODS.Scoring_Calculations = {} + SMODS.Scoring_Calculation = SMODS.GameObject:extend { + set = 'Scoring_Calculations', + obj_table = SMODS.Scoring_Calculations, + obj_buffer = {}, + required_params = { + 'key', + 'func', + }, + parameters = {'chips', 'mult'}, + inject = function() end, + new = function(self, def) + def = def or {} + if self.init then def.config = def.config or self.init(def) end + for key, _ in pairs(SMODS.Calculation_Controls) do + SMODS.Calculation_Controls[key] = false + end + for _, key in ipairs(self.parameters) do + SMODS.Calculation_Controls[key] = true + G.GAME.current_round.current_hand[key] = SMODS.Scoring_Parameters[key].default_value + end + return setmetatable(def, {__index = self}) + end, + load = function(self, def) + def = def or {} + def.config = def.config or {} + for key, _ in pairs(SMODS.Calculation_Controls) do + SMODS.Calculation_Controls[key] = false + end + for _, key in ipairs(self.parameters) do + SMODS.Calculation_Controls[key] = true + end + return setmetatable(def, {__index = self}) + end, + save = function(self) + local backTable = { + config = self.config, + key = self.key or 'multiply' + } + + return backTable + end + } + + local init_game_object_ref = Game.init_game_object + function Game:init_game_object() + local ret = init_game_object_ref(self) + for _, parameter in pairs(SMODS.Scoring_Parameters) do + if parameter.hands then + for hand, values in pairs(parameter.hands) do + for k, v in pairs(values) do + ret.hands[hand][k] = v + end + end + end + end + return ret + end + + SMODS.Scoring_Calculation { + key = "multiply", + func = function(self, chips, mult, flames) return chips * mult end, + text = 'X' + } + + SMODS.Scoring_Calculation { + key = "add", + func = function(self, chips, mult, flames) return chips + mult end, + text = '+' + } + + SMODS.Scoring_Calculation { + key = "exponent", + func = function(self, chips, mult, flames) return chips ^ mult end, + text = '^' + } + ------------------------------------------------------------------------------------------------- ----- API IMPORT GameObject.DrawStep @@ -3383,7 +3794,7 @@ Set `prefix_config.key = false` on your object instead.]]):format(obj.key), obj. register = function() error('INTERNAL CLASS, DO NOT CALL') end, pre_inject_class = function() for _, mod in ipairs(SMODS.mod_list) do - if mod.can_load then + if mod.can_load and not mod.lovely_only then SMODS.handle_loc_file(mod.path, mod.id) end end diff --git a/Steamodded/src/loader.lua b/Steamodded/src/loader.lua index 8c2da95..3339ac8 100644 --- a/Steamodded/src/loader.lua +++ b/Steamodded/src/loader.lua @@ -621,7 +621,7 @@ function SMODS.injectItems() G.P_SEALS, } do for k, v in pairs(t) do - assert(v._discovered_unlocked_overwritten) + assert(v._discovered_unlocked_overwritten, ("Internal: discovery/unlocked of object \"%s\" failed to override."):format(v and v.key or "UNKNOWN")) end end end @@ -630,6 +630,9 @@ local function initializeModUIFunctions() for id, modInfo in pairs(SMODS.mod_list) do G.FUNCS["openModUI_" .. modInfo.id] = function(e) G.ACTIVE_MOD_UI = modInfo + if e and e.config and e.config.page then + SMODS.LAST_SELECTED_MOD_TAB = e.config.page + end G.FUNCS.overlay_menu({ definition = create_UIBox_mods(e) }) diff --git a/Steamodded/src/overrides.lua b/Steamodded/src/overrides.lua index 2d5cd4d..86400fc 100644 --- a/Steamodded/src/overrides.lua +++ b/Steamodded/src/overrides.lua @@ -195,7 +195,13 @@ function create_UIBox_your_collection_blinds(exit) end local extras = nil - local t = create_UIBox_generic_options({ + local t = create_UIBox_generic_options({ + colour = G.ACTIVE_MOD_UI and ((G.ACTIVE_MOD_UI.ui_config or {}).collection_colour or + (G.ACTIVE_MOD_UI.ui_config or {}).colour) or nil, + bg_colour = G.ACTIVE_MOD_UI and ((G.ACTIVE_MOD_UI.ui_config or {}).collection_bg_colour or + (G.ACTIVE_MOD_UI.ui_config or {}).bg_colour) or nil, + back_colour = G.ACTIVE_MOD_UI and ((G.ACTIVE_MOD_UI.ui_config or {}).collection_back_colour or + (G.ACTIVE_MOD_UI.ui_config or {}).back_colour) or nil, back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or exit or 'your_collection', contents = { { @@ -263,7 +269,7 @@ function create_UIBox_your_collection_blinds(exit) opt_callback = 'your_collection_blinds_page', focus_args = {snap_to = true, nav = 'wide'}, current_option = page, - colour = G.C.RED, + colour = G.ACTIVE_MOD_UI and (G.ACTIVE_MOD_UI.ui_config or {}).collection_option_cycle_colour or G.C.RED, no_pips = true }) }, @@ -446,7 +452,13 @@ function create_UIBox_your_collection_tags_content(page) for i = 1, math.ceil(#tag_tab/(rows*cols)) do table.insert(page_options, localize('k_page')..' '..tostring(i)..'/'..tostring(math.ceil(#tag_tab/(rows*cols)))) end - local t = create_UIBox_generic_options({ + local t = create_UIBox_generic_options({ + colour = G.ACTIVE_MOD_UI and ((G.ACTIVE_MOD_UI.ui_config or {}).collection_colour or + (G.ACTIVE_MOD_UI.ui_config or {}).colour) or nil, + bg_colour = G.ACTIVE_MOD_UI and ((G.ACTIVE_MOD_UI.ui_config or {}).collection_bg_colour or + (G.ACTIVE_MOD_UI.ui_config or {}).bg_colour) or nil, + back_colour = G.ACTIVE_MOD_UI and ((G.ACTIVE_MOD_UI.ui_config or {}).collection_back_colour or + (G.ACTIVE_MOD_UI.ui_config or {}).back_colour) or nil, back_func = G.ACTIVE_MOD_UI and "openModUI_" .. G.ACTIVE_MOD_UI.id or 'your_collection', contents = { { @@ -473,7 +485,7 @@ function create_UIBox_your_collection_tags_content(page) opt_callback = 'your_collection_tags_page', focus_args = { snap_to = true, nav = 'wide' }, current_option = page, - colour = G.C.RED, + colour = G.ACTIVE_MOD_UI and (G.ACTIVE_MOD_UI.ui_config or {}).collection_option_cycle_colour or G.C.RED, no_pips = true }) } @@ -530,11 +542,11 @@ end function G.UIDEF.deck_stake_column(_deck_key) local deck_usage = G.PROFILES[G.SETTINGS.profile].deck_usage[_deck_key] local stake_col = {} - local valid_option = nil local num_stakes = #G.P_CENTER_POOLS['Stake'] for i = #G.P_CENTER_POOLS['Stake'], 1, -1 do local _wins = deck_usage and deck_usage.wins[i] or 0 - if (deck_usage and deck_usage.wins[i - 1]) or i == 1 or G.PROFILES[G.SETTINGS.profile].all_unlocked then valid_option = true end + local valid_option = nil + if (deck_usage and deck_usage.wins[i - 1]) or (not next(G.P_CENTER_POOLS.Stake[i].applied_stakes or {})) or G.PROFILES[G.SETTINGS.profile].all_unlocked then valid_option = true end stake_col[#stake_col + 1] = {n = G.UIT.R, config = {id = i, align = "cm", colour = _wins > 0 and G.C.GREY or G.C.CLEAR, outline = 0, outline_colour = G.C.WHITE, r = 0.1, minh = 2 / num_stakes, minw = valid_option and 0.45 or 0.25, func = 'RUN_SETUP_check_back_stake_highlight'}, nodes = { {n = G.UIT.R, config = {align = "cm", minh = valid_option and 1.36 / num_stakes or 1.04 / num_stakes, minw = valid_option and 0.37 or 0.13, colour = _wins > 0 and get_stake_col(i) or G.C.UI.TRANSPARENT_LIGHT, r = 0.1}, nodes = {}}}} if i > 1 then stake_col[#stake_col + 1] = {n = G.UIT.R, config = {align = "cm", minh = 0.8 / num_stakes, minw = 0.04 }, nodes = {} } end @@ -542,6 +554,44 @@ function G.UIDEF.deck_stake_column(_deck_key) return {n = G.UIT.ROOT, config = {align = 'cm', colour = G.C.CLEAR}, nodes = stake_col} end +function SMODS.check_applied_stakes(stake, deck) + if next(stake.applied_stakes) then + for _, applied_stake in ipairs(stake.applied_stakes) do + if not deck.wins_by_key[applied_stake] then return false end + end + end + return true +end + +function G.UIDEF.stake_option(_type) + G.viewed_stake = G.viewed_stake or 1 + + local middle = {n=G.UIT.R, config={align = "cm", minh = 1.7, minw = 7.3}, nodes={ + {n=G.UIT.O, config={id = nil, func = 'RUN_SETUP_check_stake2', object = Moveable()}}, + }} + + local stake_options = {} + local curr_options = {} + local deck_usage = G.PROFILES[G.SETTINGS.profile].deck_usage[G.GAME.viewed_back.effect.center.key] + for i=1, #G.P_CENTER_POOLS.Stake do + if G.PROFILES[G.SETTINGS.profile].all_unlocked or SMODS.check_applied_stakes(G.P_CENTER_POOLS.Stake[i], deck_usage or {wins_by_key = {}}) then + stake_options[#stake_options + 1] = i + curr_options[i] = #stake_options + end + end + + return {n=G.UIT.ROOT, config={align = "tm", colour = G.C.CLEAR, minh = 2.03, minw = 8.3}, nodes={ + _type == 'Continue' and middle + or create_option_cycle({options = stake_options, opt_callback = 'change_stake', current_option = curr_options[G.viewed_stake] or 1, + colour = G.C.RED, w = 6, mid = middle}) + }} +end + +G.FUNCS.change_stake = function(args) + G.viewed_stake = args.to_val + G.PROFILES[G.SETTINGS.profile].MEMORY.stake = args.to_val +end + --#endregion --#region straights and view deck UI @@ -651,14 +701,16 @@ function G.UIDEF.deck_preview(args) if v.ability.wheel_flipped and not (v.area and v.area == G.deck) then wheel_flipped = wheel_flipped + 1 end if v.ability.effect == 'Stone Card' then stones = stones + 1 - else - for kk, vv in pairs(suit_counts) do - if v.base.suit == kk then suit_counts[kk] = suit_counts[kk] + 1 end - if v:is_suit(kk) then mod_suit_counts[kk] = mod_suit_counts[kk] + 1 end - end - if SUITS[v.base.suit][v.base.value] then - table.insert(SUITS[v.base.suit][v.base.value], v) - end + end + local v_nr, v_ns = SMODS.has_no_rank(v), SMODS.has_no_suit(v) + for kk, vv in pairs(suit_counts) do + if v.base.suit == kk and not v_ns then suit_counts[kk] = suit_counts[kk] + 1 end + if v:is_suit(kk) then mod_suit_counts[kk] = mod_suit_counts[kk] + 1 end + end + if SUITS[v.base.suit][v.base.value] and not v_nr and not v_ns then + table.insert(SUITS[v.base.suit][v.base.value], v) + end + if not v_nr then rank_counts[v.base.value] = (rank_counts[v.base.value] or 0) + 1 end end @@ -680,13 +732,13 @@ function G.UIDEF.deck_preview(args) for _, suit in ipairs(suit_map) do count = count + #SUITS[suit][rank] end - if count == 0 and SMODS.Ranks[rank].in_pool and not SMODS.Ranks[rank]:in_pool({suit=''}) then + if count == 0 and SMODS.Ranks[rank].in_pool and not SMODS.add_to_pool(SMODS.Ranks[rank], {suit=''}) then hidden_ranks[rank] = true end end local hidden_suits = {} for _, suit in ipairs(suit_map) do - if suit_counts[suit] == 0 and SMODS.Suits[suit].in_pool and not SMODS.Suits[suit]:in_pool({rank=''}) then + if suit_counts[suit] == 0 and SMODS.Suits[suit].in_pool and not SMODS.add_to_pool(SMODS.Suits[suit],{rank=''}) then hidden_suits[suit] = true end end @@ -739,7 +791,8 @@ function G.UIDEF.deck_preview(args) G.ASSET_ATLAS[SMODS.Suits[v][G.SETTINGS.colour_palettes[v] == 'hc' and "hc_ui_atlas" or G.SETTINGS.colour_palettes[v] == 'lc' and "lc_ui_atlas"]] or G.ASSET_ATLAS[("ui_" .. (G.SETTINGS.colourblind_option and "2" or "1"))], SMODS.Suits[v].ui_pos) else - t_s = Sprite(0, 0, 0.3, 0.3, G.ASSET_ATLAS[("ui_" .. (G.SETTINGS.colourblind_option and "2" or "1"))], SMODS.Suits[v].ui_pos) + local atlas = G.SETTINGS.colour_palettes[v] == "hc" and SMODS.Suits[v].hc_ui_atlas or SMODS.Suits[v].lc_ui_atlas + t_s = Sprite(0, 0, 0.3, 0.3, G.ASSET_ATLAS[atlas and atlas or ("ui_" .. (G.SETTINGS.colourblind_option and "2" or "1"))], SMODS.Suits[v].ui_pos) end t_s.states.drag.can = false @@ -815,10 +868,12 @@ function tally_sprite(pos, value, tooltip, suit) }} end +local view_deck_unplayed_only = nil function G.UIDEF.view_deck(unplayed_only) local deck_tables = {} remove_nils(G.playing_cards) G.VIEWING_DECK = true + view_deck_unplayed_only = unplayed_only table.sort(G.playing_cards, function(a, b) return a:get_nominal('suit') > b:get_nominal('suit') end) local SUITS = {} local suit_map = {} @@ -833,51 +888,60 @@ function G.UIDEF.view_deck(unplayed_only) for j = 1, #suit_map do if SUITS[suit_map[j]][1] then num_suits = num_suits + 1 end end + + local visible_suit = {} for j = 1, #suit_map do if SUITS[suit_map[j]][1] then - local view_deck = CardArea( - G.ROOM.T.x + 0.2 * G.ROOM.T.w / 2, G.ROOM.T.h, - 6.5 * G.CARD_W, - ((num_suits > 8) and 0.2 or (num_suits > 4) and (1 - 0.1 * num_suits) or 0.6) * G.CARD_H, - { - card_limit = #SUITS[suit_map[j]], - type = 'title', - view_deck = true, - highlight_limit = 0, - card_w = G - .CARD_W * 0.7, - draw_layers = { 'card' } - }) - table.insert(deck_tables, - {n = G.UIT.R, config = {align = "cm", padding = 0}, nodes = { - {n = G.UIT.O, config = {object = view_deck}}}} - ) + table.insert(visible_suit, suit_map[j]) + end + end - for i = 1, #SUITS[suit_map[j]] do - if SUITS[suit_map[j]][i] then - local greyed, _scale = nil, 0.7 - if unplayed_only and not ((SUITS[suit_map[j]][i].area and SUITS[suit_map[j]][i].area == G.deck) or SUITS[suit_map[j]][i].ability.wheel_flipped) then - greyed = true + for j = 1, #visible_suit do + if (j >= 1 and j <= 4) or num_suits <= 4 then + if SUITS[visible_suit[j]][1] then + local view_deck = CardArea( + G.ROOM.T.x + 0.2 * G.ROOM.T.w / 2, G.ROOM.T.h, + 6.5 * G.CARD_W, + (0.6) * G.CARD_H, + { + card_limit = #SUITS[visible_suit[j]], + type = 'title', + view_deck = true, + highlight_limit = 0, + card_w = G + .CARD_W * 0.7, + draw_layers = { 'card' }, + negative_info = 'playing_card' + }) + table.insert(deck_tables, + {n = G.UIT.R, config = {align = "cm", padding = 0}, nodes = { + {n = G.UIT.O, config = {object = view_deck}}}} + ) + for i = 1, #SUITS[visible_suit[j]] do + if SUITS[visible_suit[j]][i] then + local greyed, _scale = nil, 0.7 + if unplayed_only and not ((SUITS[visible_suit[j]][i].area and SUITS[visible_suit[j]][i].area == G.deck) or SUITS[visible_suit[j]][i].ability.wheel_flipped) then + greyed = true + end + local copy = copy_card(SUITS[visible_suit[j]][i], nil, _scale) + copy.greyed = greyed + copy.T.x = view_deck.T.x + view_deck.T.w / 2 + copy.T.y = view_deck.T.y + + copy:hard_set_T() + view_deck:emplace(copy) end - local copy = copy_card(SUITS[suit_map[j]][i], nil, _scale) - copy.greyed = greyed - copy.T.x = view_deck.T.x + view_deck.T.w / 2 - copy.T.y = view_deck.T.y - - copy:hard_set_T() - view_deck:emplace(copy) end end end end - -- Add empty card area if there's none, to fix a visual issue with no cards left if not next(deck_tables) then local view_deck = CardArea( G.ROOM.T.x + 0.2*G.ROOM.T.w/2,G.ROOM.T.h, 6.5*G.CARD_W, 0.6*G.CARD_H, - {card_limit = 1, type = 'title', view_deck = true, highlight_limit = 0, card_w = G.CARD_W*0.7, draw_layers = {'card'}}) + {card_limit = 1, type = 'title', view_deck = true, highlight_limit = 0, card_w = G.CARD_W*0.7, draw_layers = {'card'}, negative_info = 'playing_card'}) table.insert( deck_tables, {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ @@ -912,17 +976,18 @@ function G.UIDEF.view_deck(unplayed_only) for k, v in ipairs(G.playing_cards) do if v.ability.name ~= 'Stone Card' and (not unplayed_only or ((v.area and v.area == G.deck) or v.ability.wheel_flipped)) then if v.ability.wheel_flipped and not (v.area and v.area == G.deck) and unplayed_only then wheel_flipped = wheel_flipped + 1 end + local v_nr, v_ns = SMODS.has_no_rank(v), SMODS.has_no_suit(v) --For the suits - if v.base.suit then suit_tallies[v.base.suit] = (suit_tallies[v.base.suit] or 0) + 1 end + if v.base.suit and not v_ns then suit_tallies[v.base.suit] = (suit_tallies[v.base.suit] or 0) + 1 end for kk, vv in pairs(mod_suit_tallies) do mod_suit_tallies[kk] = (vv or 0) + (v:is_suit(kk) and 1 or 0) end --for face cards/numbered cards/aces local card_id = v:get_id() - if v.base.value then face_tally = face_tally + ((SMODS.Ranks[v.base.value].face) and 1 or 0) end + if v.base.value and not v_nr then face_tally = face_tally + ((SMODS.Ranks[v.base.value].face) and 1 or 0) end mod_face_tally = mod_face_tally + (v:is_face() and 1 or 0) - if v.base.value and not SMODS.Ranks[v.base.value].face and card_id ~= 14 then + if v.base.value and not v_nr and not SMODS.Ranks[v.base.value].face and card_id ~= 14 then num_tally = num_tally + 1 if not v.debuff then mod_num_tally = mod_num_tally + 1 end end @@ -932,8 +997,8 @@ function G.UIDEF.view_deck(unplayed_only) end --ranks - if v.base.value then rank_tallies[v.base.value] = rank_tallies[v.base.value] + 1 end - if v.base.value and not v.debuff then mod_rank_tallies[v.base.value] = mod_rank_tallies[v.base.value] + 1 end + if v.base.value and not v_nr then rank_tallies[v.base.value] = rank_tallies[v.base.value] + 1 end + if v.base.value and not v_nr and not v.debuff then mod_rank_tallies[v.base.value] = mod_rank_tallies[v.base.value] + 1 end end end local modded = face_tally ~= mod_face_tally @@ -946,7 +1011,7 @@ function G.UIDEF.view_deck(unplayed_only) local rank_cols = {} for i = #rank_name_mapping, 1, -1 do - if rank_tallies[rank_name_mapping[i]] ~= 0 or not SMODS.Ranks[rank_name_mapping[i]].in_pool or SMODS.Ranks[rank_name_mapping[i]]:in_pool({suit=''}) then + if rank_tallies[rank_name_mapping[i]] ~= 0 or SMODS.add_to_pool(SMODS.Ranks[rank_name_mapping[i]], {suit=''}) then local mod_delta = mod_rank_tallies[rank_name_mapping[i]] ~= rank_tallies[rank_name_mapping[i]] rank_cols[#rank_cols + 1] = {n = G.UIT.R, config = {align = "cm", padding = 0.07}, nodes = { {n = G.UIT.C, config = {align = "cm", r = 0.1, padding = 0.04, emboss = 0.04, minw = 0.5, colour = G.C.L_BLACK}, nodes = { @@ -995,7 +1060,7 @@ function G.UIDEF.view_deck(unplayed_only) -- add suit tallies local hidden_suits = {} for _, suit in ipairs(suit_map) do - if suit_tallies[suit] == 0 and SMODS.Suits[suit].in_pool and not SMODS.Suits[suit]:in_pool({rank=''}) then + if suit_tallies[suit] == 0 and SMODS.Suits[suit].in_pool and not SMODS.add_to_pool(SMODS.Suits[suit], {rank=''}) then hidden_suits[suit] = true end end @@ -1006,34 +1071,356 @@ function G.UIDEF.view_deck(unplayed_only) num_suits_shown = num_suits_shown+1 end end - local suits_per_row = num_suits_shown > 6 and 4 or num_suits_shown > 4 and 3 or 2 + local suits_per_row = 2 local n_nodes = {} - while i <= #suit_map do - while #n_nodes < suits_per_row and i <= #suit_map do - if not hidden_suits[suit_map[i]] then - table.insert(n_nodes, tally_sprite( - SMODS.Suits[suit_map[i]].ui_pos, - { - { string = '' .. suit_tallies[suit_map[i]], colour = flip_col }, - { string = '' .. mod_suit_tallies[suit_map[i]], colour = G.C.BLUE } - }, - { localize(suit_map[i], 'suits_plural') }, - suit_map[i] - )) - end - i = i + 1 + local visible_suits = {} + local temp_list = {} + while i <= math.min(4, #visible_suit) do + if not hidden_suits[visible_suit[i]] then + table.insert(n_nodes, tally_sprite( + SMODS.Suits[visible_suit[i]].ui_pos, + { + { string = '' .. suit_tallies[visible_suit[i]], colour = flip_col }, + { string = '' .. mod_suit_tallies[visible_suit[i]], colour = G.C.BLUE } + }, + { localize(visible_suit[i], 'suits_plural') }, + visible_suit[i] + )) + table.insert(visible_suits, i) end - if #n_nodes > 0 then - local n = {n = G.UIT.R, config = {align = "cm", minh = 0.05, padding = 0.1}, nodes = n_nodes} - table.insert(tally_ui, n) + if #n_nodes == suits_per_row then + table.insert(temp_list, n_nodes) n_nodes = {} end + i = i + 1 end - local t = {n = G.UIT.ROOT, config = {align = "cm", colour = G.C.CLEAR}, nodes = { + if #n_nodes > 0 then + table.insert(temp_list, n_nodes) + end + + local index = 0 + local second_temp_list = {} + for _, v in ipairs(temp_list) do + local n = {n = G.UIT.R, config = {align = "cm", minh = 0.05, padding = 0.05}, nodes = v} + table.insert(tally_ui, n) + end + + local suit_options = {} + for i = 1, math.ceil(#visible_suit / 4) do + table.insert(suit_options, + localize('k_page') .. ' ' .. tostring(i) .. '/' .. tostring(math.ceil(#visible_suit / 4))) + end + + local object = {n = G.UIT.ROOT, config = {align = "cm", colour = G.C.CLEAR}, nodes = { {n = G.UIT.R, config = {align = "cm", padding = 0.05}, nodes = {}}, {n = G.UIT.R, config = {align = "cm"}, nodes = { {n = G.UIT.C, config = {align = "cm", minw = 1.5, minh = 2, r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes = { - {n = G.UIT.C, config = {align = "cm", padding = 0.1}, nodes = { + {n = G.UIT.C, config = {align = "tm", padding = 0.1}, nodes = { + {n = G.UIT.R, config = {align = "cm", r = 0.1, colour = G.C.L_BLACK, emboss = 0.05, padding = 0.15}, nodes = { + {n = G.UIT.R, config = {align = "cm"}, nodes = { + {n = G.UIT.O, config = { + object = DynaText({ string = G.GAME.selected_back.loc_name, colours = {G.C.WHITE}, bump = true, rotate = true, shadow = true, scale = 0.6 - string.len(G.GAME.selected_back.loc_name) * 0.01 }) + }}, + }}, + {n = G.UIT.R, config = {align = "cm", r = 0.1, padding = 0.1, minw = 2.5, minh = 1.3, colour = G.C.WHITE, emboss = 0.05}, nodes = { + {n = G.UIT.O, config = { + object = UIBox { + definition = G.GAME.selected_back:generate_UI(nil, 0.7, 0.5, G.GAME.challenge), config = {offset = { x = 0, y = 0 } } + } + }} + }} + }}, + {n = G.UIT.R, config = {align = "cm", r = 0.1, outline_colour = G.C.L_BLACK, line_emboss = 0.05, outline = 1.5}, nodes = tally_ui} + }}, + {n = G.UIT.C, config = {align = "cm"}, nodes = rank_cols}, + {n = G.UIT.B, config = {w = 0.1, h = 0.1}}, + }}, + {n = G.UIT.B, config = {w = 0.2, h = 0.1}}, + {n = G.UIT.C, config = {align = "cm", padding = 0.1, r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes = deck_tables} + }}, + #visible_suit > 4 and {n = G.UIT.R, config = {align = "cm", padding = 0 }, nodes = { + create_option_cycle({ + options = suit_options, + w = 4.5, + cycle_shoulders = true, + opt_callback = + 'your_suits_page', + focus_args = { snap_to = true, nav = 'wide' }, + current_option = 1, + colour = G.C.RED, + no_pips = true, + }) + }} or nil, + {n = G.UIT.R, config = {align = "cm", padding = 0}, nodes = { + modded and {n = G.UIT.R, config = {align = "cm"}, nodes = { + {n = G.UIT.C, config = {padding = 0.3, r = 0.1, colour = mix_colours(G.C.BLUE, G.C.WHITE, 0.7)}, nodes = {}}, + {n = G.UIT.T, config = {text = ' ' .. localize('ph_deck_preview_effective'), colour = G.C.WHITE, scale = 0.3}},}} + or nil, + wheel_flipped > 0 and {n = G.UIT.R, config = {align = "cm"}, nodes = { + {n = G.UIT.C, config = {padding = 0.3, r = 0.1, colour = flip_col}, nodes = {}}, + {n = G.UIT.T, config = { + text = ' ' .. (wheel_flipped > 1 and + localize { type = 'variable', key = 'deck_preview_wheel_plural', vars = { wheel_flipped } } or + localize { type = 'variable', key = 'deck_preview_wheel_singular', vars = { wheel_flipped } }), + colour = G.C.WHITE, scale = 0.3 + }},}} + or nil,}}}} + local t = {n = G.UIT.ROOT, config = {align = "cm", minw = 3, padding = 0.1, r = 0.1, colour = G.C.CLEAR}, nodes = { + {n = G.UIT.O, config = { + id = 'suit_list', + object = UIBox { + definition = object, config = {offset = { x = 0, y = 0 }, align = 'cm'} + } + }}}} + return t +end + +G.FUNCS.your_suits_page = function(args) + if not args or not args.cycle_config then return end + local deck_tables = {} + remove_nils(G.playing_cards) + G.VIEWING_DECK = true + table.sort(G.playing_cards, function(a, b) return a:get_nominal('suit') > b:get_nominal('suit') end) + local SUITS = {} + local suit_map = {} + for i = #SMODS.Suit.obj_buffer, 1, -1 do + SUITS[SMODS.Suit.obj_buffer[i]] = {} + suit_map[#suit_map + 1] = SMODS.Suit.obj_buffer[i] + end + for k, v in ipairs(G.playing_cards) do + if v.base.suit then table.insert(SUITS[v.base.suit], v) end + end + local num_suits = 0 + for j = 1, #suit_map do + if SUITS[suit_map[j]][1] then num_suits = num_suits + 1 end + end + + local visible_suit = {} + for j = 1, #suit_map do + if SUITS[suit_map[j]][1] then + table.insert(visible_suit, suit_map[j]) + end + end + + local deck_start_index = (args.cycle_config.current_option - 1) * 4 + 1 + local deck_end_index = math.min(deck_start_index + 4 - 1, #visible_suit) + for j = 1, #visible_suit do + if SUITS[visible_suit[j]][1] and (j >= deck_start_index and j <= deck_end_index) then + local view_deck = CardArea( + G.ROOM.T.x + 0.2 * G.ROOM.T.w / 2, G.ROOM.T.h, + 6.5 * G.CARD_W, + (0.6) * G.CARD_H, + { + card_limit = #SUITS[visible_suit[j]], + type = 'title', + view_deck = true, + highlight_limit = 0, + card_w = G + .CARD_W * 0.7, + draw_layers = { 'card' }, + negative_info = 'playing_card' + }) + table.insert(deck_tables, + {n = G.UIT.R, config = {align = "cm", padding = 0}, nodes = { + {n = G.UIT.O, config = {object = view_deck}}}} + ) + for i = 1, #SUITS[visible_suit[j]] do + if SUITS[visible_suit[j]][i] then + local greyed, _scale = nil, 0.7 + if view_deck_unplayed_only and not ((SUITS[visible_suit[j]][i].area and SUITS[visible_suit[j]][i].area == G.deck) or SUITS[visible_suit[j]][i].ability.wheel_flipped) then + greyed = true + end + local copy = copy_card(SUITS[visible_suit[j]][i], nil, _scale) + copy.greyed = greyed + copy.T.x = view_deck.T.x + view_deck.T.w / 2 + copy.T.y = view_deck.T.y + + copy:hard_set_T() + view_deck:emplace(copy) + end + end + end + end + + if not next(deck_tables) then + local view_deck = CardArea( + G.ROOM.T.x + 0.2*G.ROOM.T.w/2,G.ROOM.T.h, + 6.5*G.CARD_W, + 0.6*G.CARD_H, + {card_limit = 1, type = 'title', view_deck = true, highlight_limit = 0, card_w = G.CARD_W*0.7, draw_layers = {'card'}, negative_info = 'playing_card'}) + table.insert( + deck_tables, + {n=G.UIT.R, config={align = "cm", padding = 0}, nodes={ + {n=G.UIT.O, config={object = view_deck}} + }} + ) + end + + local flip_col = G.C.WHITE + + local suit_tallies = {} + local mod_suit_tallies = {} + for _, v in ipairs(suit_map) do + suit_tallies[v] = 0 + mod_suit_tallies[v] = 0 + end + local rank_tallies = {} + local mod_rank_tallies = {} + local rank_name_mapping = SMODS.Rank.obj_buffer + for _, v in ipairs(rank_name_mapping) do + rank_tallies[v] = 0 + mod_rank_tallies[v] = 0 + end + local face_tally = 0 + local mod_face_tally = 0 + local num_tally = 0 + local mod_num_tally = 0 + local ace_tally = 0 + local mod_ace_tally = 0 + local wheel_flipped = 0 + + for k, v in ipairs(G.playing_cards) do + if v.ability.name ~= 'Stone Card' and (not view_deck_unplayed_only or ((v.area and v.area == G.deck) or v.ability.wheel_flipped)) then + if v.ability.wheel_flipped and not (v.area and v.area == G.deck) and view_deck_unplayed_only then wheel_flipped = wheel_flipped + 1 end + --For the suits + if v.base.suit then suit_tallies[v.base.suit] = (suit_tallies[v.base.suit] or 0) + 1 end + for kk, vv in pairs(mod_suit_tallies) do + mod_suit_tallies[kk] = (vv or 0) + (v:is_suit(kk) and 1 or 0) + end + + --for face cards/numbered cards/aces + local card_id = v:get_id() + if v.base.value then face_tally = face_tally + ((SMODS.Ranks[v.base.value].face) and 1 or 0) end + mod_face_tally = mod_face_tally + (v:is_face() and 1 or 0) + if v.base.value and not SMODS.Ranks[v.base.value].face and card_id ~= 14 then + num_tally = num_tally + 1 + if not v.debuff then mod_num_tally = mod_num_tally + 1 end + end + if card_id == 14 then + ace_tally = ace_tally + 1 + if not v.debuff then mod_ace_tally = mod_ace_tally + 1 end + end + + --ranks + if v.base.value then rank_tallies[v.base.value] = rank_tallies[v.base.value] + 1 end + if v.base.value and not v.debuff then mod_rank_tallies[v.base.value] = mod_rank_tallies[v.base.value] + 1 end + end + end + local modded = face_tally ~= mod_face_tally + for kk, vv in pairs(mod_suit_tallies) do + modded = modded or (vv ~= suit_tallies[kk]) + if modded then break end + end + + if wheel_flipped > 0 then flip_col = mix_colours(G.C.FILTER, G.C.WHITE, 0.7) end + + local rank_cols = {} + for i = #rank_name_mapping, 1, -1 do + if rank_tallies[rank_name_mapping[i]] ~= 0 or SMODS.add_to_pool(SMODS.Ranks[rank_name_mapping[i]], {suit=''}) then + local mod_delta = mod_rank_tallies[rank_name_mapping[i]] ~= rank_tallies[rank_name_mapping[i]] + rank_cols[#rank_cols + 1] = {n = G.UIT.R, config = {align = "cm", padding = 0.07}, nodes = { + {n = G.UIT.C, config = {align = "cm", r = 0.1, padding = 0.04, emboss = 0.04, minw = 0.5, colour = G.C.L_BLACK}, nodes = { + {n = G.UIT.T, config = {text = SMODS.Ranks[rank_name_mapping[i]].shorthand, colour = G.C.JOKER_GREY, scale = 0.35, shadow = true}},}}, + {n = G.UIT.C, config = {align = "cr", minw = 0.4}, nodes = { + mod_delta and {n = G.UIT.O, config = { + object = DynaText({ + string = { { string = '' .. rank_tallies[rank_name_mapping[i]], colour = flip_col }, { string = '' .. mod_rank_tallies[rank_name_mapping[i]], colour = G.C.BLUE } }, + colours = { G.C.RED }, scale = 0.4, y_offset = -2, silent = true, shadow = true, pop_in_rate = 10, pop_delay = 4 + })}} + or {n = G.UIT.T, config = {text = rank_tallies[rank_name_mapping[i]], colour = flip_col, scale = 0.45, shadow = true } },}}}} + end + end + + local tally_ui = { + -- base cards + {n = G.UIT.R, config = {align = "cm", minh = 0.05, padding = 0.07}, nodes = { + {n = G.UIT.O, config = { + object = DynaText({ + string = { + { string = localize('k_base_cards'), colour = G.C.RED }, + modded and { string = localize('k_effective'), colour = G.C.BLUE } or nil + }, + colours = { G.C.RED }, silent = true, scale = 0.4, pop_in_rate = 10, pop_delay = 4 + }) + }}}}, + -- aces, faces and numbered cards + {n = G.UIT.R, config = {align = "cm", minh = 0.05, padding = 0.1}, nodes = { + tally_sprite( + { x = 1, y = 0 }, + { { string = '' .. ace_tally, colour = flip_col }, { string = '' .. mod_ace_tally, colour = G.C.BLUE } }, + { localize('k_aces') } + ), --Aces + tally_sprite( + { x = 2, y = 0 }, + { { string = '' .. face_tally, colour = flip_col }, { string = '' .. mod_face_tally, colour = G.C.BLUE } }, + { localize('k_face_cards') } + ), --Face + tally_sprite( + { x = 3, y = 0 }, + { { string = '' .. num_tally, colour = flip_col }, { string = '' .. mod_num_tally, colour = G.C.BLUE } }, + { localize('k_numbered_cards') } + ), --Numbers + }}, + } + -- add suit tallies + local hidden_suits = {} + for _, suit in ipairs(suit_map) do + if suit_tallies[suit] == 0 and SMODS.Suits[suit].in_pool and not SMODS.add_to_pool(SMODS.Suits[suit], {rank=''}) then + hidden_suits[suit] = true + end + end + local i = deck_start_index + local num_suits_shown = 0 + for i = 1, #visible_suit do + if not hidden_suits[visible_suit[i]] then + num_suits_shown = num_suits_shown+1 + end + end + local suits_per_row = 2 + local n_nodes = {} + local visible_suits = {} + local temp_list = {} + while i <= deck_end_index do + if not hidden_suits[visible_suit[i]] then + table.insert(n_nodes, tally_sprite( + SMODS.Suits[visible_suit[i]].ui_pos, + { + { string = '' .. suit_tallies[visible_suit[i]], colour = flip_col }, + { string = '' .. mod_suit_tallies[visible_suit[i]], colour = G.C.BLUE } + }, + { localize(visible_suit[i], 'suits_plural') }, + visible_suit[i] + )) + table.insert(visible_suits, i) + end + if #n_nodes == suits_per_row then + table.insert(temp_list, n_nodes) + n_nodes = {} + end + i = i + 1 + end + if #n_nodes > 0 then + table.insert(temp_list, n_nodes) + end + + local index = 0 + local second_temp_list = {} + for _, v in ipairs(temp_list) do + local n = {n = G.UIT.R, config = {align = "cm", minh = 0.05, padding = 0.05}, nodes = v} + table.insert(tally_ui, n) + end + + local suit_options = {} + for i = 1, math.ceil(#visible_suit / 4) do + table.insert(suit_options, + localize('k_page') .. ' ' .. tostring(i) .. '/' .. tostring(math.ceil(#visible_suit / 4))) + end + + local object = {n = G.UIT.ROOT, config = {align = "cm", colour = G.C.CLEAR}, nodes = { + {n = G.UIT.R, config = {align = "cm", padding = 0.05}, nodes = {}}, + {n = G.UIT.R, config = {align = "cm"}, nodes = { + {n = G.UIT.C, config = {align = "cm", minw = 1.5, minh = 2, r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes = { + {n = G.UIT.C, config = {align = "tm", padding = 0.1}, nodes = { {n = G.UIT.R, config = {align = "cm", r = 0.1, colour = G.C.L_BLACK, emboss = 0.05, padding = 0.15}, nodes = { {n = G.UIT.R, config = {align = "cm"}, nodes = { {n = G.UIT.O, config = { @@ -1052,7 +1439,21 @@ function G.UIDEF.view_deck(unplayed_only) {n = G.UIT.B, config = {w = 0.2, h = 0.1}}, {n = G.UIT.C, config = {align = "cm", padding = 0.1, r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes = deck_tables}}}, - {n = G.UIT.R, config = {align = "cm", minh = 0.8, padding = 0.05}, nodes = { + {n = G.UIT.R, config = {align = "cm", padding = 0 }, nodes = { + create_option_cycle({ + options = suit_options, + w = 4.5, + cycle_shoulders = true, + opt_callback = + 'your_suits_page', + focus_args = { snap_to = true, nav = 'wide' }, + current_option = args.cycle_config.current_option, + colour = G.C.RED, + no_pips = true, + }) + } + }, + {n = G.UIT.R, config = {align = "cm", padding = 0.05}, nodes = { modded and {n = G.UIT.R, config = {align = "cm"}, nodes = { {n = G.UIT.C, config = {padding = 0.3, r = 0.1, colour = mix_colours(G.C.BLUE, G.C.WHITE, 0.7)}, nodes = {}}, {n = G.UIT.T, config = {text = ' ' .. localize('ph_deck_preview_effective'), colour = G.C.WHITE, scale = 0.3}},}} @@ -1066,7 +1467,16 @@ function G.UIDEF.view_deck(unplayed_only) colour = G.C.WHITE, scale = 0.3 }},}} or nil,}}}} - return t + + local suit_list = G.OVERLAY_MENU:get_UIE_by_ID('suit_list') + if suit_list then + if suit_list.config.object then + suit_list.config.object:remove() + end + suit_list.config.object = UIBox { + definition = object, config = {offset = { x = 0, y = 0 }, align = 'cm', parent = suit_list } + } + end end --#endregion @@ -1104,19 +1514,25 @@ function G.FUNCS.get_poker_hand_info(_cards) end disp_text = text local _hand = SMODS.PokerHands[text] - if text == 'Straight Flush' then - local royal = true - for j = 1, #scoring_hand do - local rank = SMODS.Ranks[scoring_hand[j].base.value] - royal = royal and (rank.key == 'Ace' or rank.key == '10' or rank.face) - end - if royal then - disp_text = 'Royal Flush' - end - elseif _hand and _hand.modify_display_text and type(_hand.modify_display_text) == 'function' then - disp_text = _hand:modify_display_text(_cards, scoring_hand) or disp_text - end + if text == 'Straight Flush' then + local royal = true + for j = 1, #scoring_hand do + local rank = SMODS.Ranks[scoring_hand[j].base.value] + royal = royal and (rank.key == 'Ace' or rank.key == '10' or rank.face) + end + if royal then + disp_text = 'Royal Flush' + end + elseif _hand and _hand.modify_display_text and type(_hand.modify_display_text) == 'function' then + disp_text = _hand:modify_display_text(_cards, scoring_hand) or disp_text + end + local flags = SMODS.calculate_context({ evaluate_poker_hand = true, full_hand = _cards, scoring_hand = scoring_hand, scoring_name = + text, poker_hands = poker_hands, display_name = disp_text }) + text = flags.replace_scoring_name or text + disp_text = flags.replace_display_name or flags.replace_scoring_name or disp_text + poker_hands = flags.replace_poker_hands or poker_hands loc_disp_text = localize(disp_text, 'poker_hands') + loc_disp_text = loc_disp_text == 'ERROR' and disp_text or loc_disp_text return text, loc_disp_text, poker_hands, scoring_hand, disp_text end @@ -1136,7 +1552,7 @@ function create_UIBox_current_hands(simple) local visible_hands = {} for _, v in ipairs(G.handlist) do - if G.GAME.hands[v].visible then + if SMODS.is_poker_hand_visible(v) then table.insert(visible_hands, v) end end @@ -1195,7 +1611,7 @@ G.FUNCS.your_hands_page = function(args) local visible_hands = {} for _, v in ipairs(G.handlist) do - if G.GAME.hands[v].visible then + if SMODS.is_poker_hand_visible(v) then table.insert(visible_hands, v) end end @@ -1387,26 +1803,19 @@ end -- silent = boolean value function Card:set_edition(edition, immediate, silent, delay) SMODS.enh_cache:write(self, nil) - -- Check to see if negative is being removed and reduce card_limit accordingly - if (self.added_to_deck or self.joker_added_to_deck_but_debuffed or (self.area == G.hand and not self.debuff)) and self.edition and self.edition.card_limit then - if self.ability.consumeable and self.area == G.consumeables then - G.consumeables.config.card_limit = G.consumeables.config.card_limit - self.edition.card_limit - elseif self.ability.set == 'Joker' and self.area == G.jokers then - G.jokers.config.card_limit = G.jokers.config.card_limit - self.edition.card_limit - elseif self.area == G.hand then - if G.hand.config.real_card_limit then - G.hand.config.real_card_limit = G.hand.config.real_card_limit - self.edition.card_limit - end - G.hand.config.card_limit = G.hand.config.card_limit - self.edition.card_limit - end + + if self.edition then + self.ability.card_limit = self.ability.card_limit - (self.edition.card_limit or 0) + self.ability.extra_slots_used = self.ability.extra_slots_used - (self.edition.extra_slots_used or 0) + if self.area then self.area:handle_card_limit(-1 * (self.edition.card_limit or 0), -1 * (self.edition.extra_slots_used or 0)) end end - local old_edition = self.edition and self.edition.key - if old_edition then - self.ignore_base_shader[old_edition] = nil - self.ignore_shadow[old_edition] = nil + local old_edition = self.edition + if old_edition and old_edition.key then + self.ignore_base_shader[old_edition.key] = nil + self.ignore_shadow[old_edition.key] = nil - local on_old_edition_removed = G.P_CENTERS[old_edition] and G.P_CENTERS[old_edition].on_remove + local on_old_edition_removed = G.P_CENTERS[old_edition.key] and G.P_CENTERS[old_edition.key].on_remove if type(on_old_edition_removed) == "function" then on_old_edition_removed(self) end @@ -1414,7 +1823,7 @@ function Card:set_edition(edition, immediate, silent, delay) local edition_type = nil if type(edition) == 'string' then - assert(string.sub(edition, 1, 2) == 'e_') + assert(string.sub(edition, 1, 2) == 'e_', ("Edition \"%s\" is missing \"e_\" prefix."):format(edition)) edition_type = string.sub(edition, 3) elseif type(edition) == 'table' then if edition.type then @@ -1422,7 +1831,7 @@ function Card:set_edition(edition, immediate, silent, delay) else for k, v in pairs(edition) do if v then - assert(not edition_type) + assert(not edition_type, "Tried to apply more than one edition.") edition_type = k end end @@ -1447,6 +1856,16 @@ function Card:set_edition(edition, immediate, silent, delay) end })) end + if delay then + self.delay_edition = old_edition + G.E_MANAGER:add_event(Event({ + trigger = 'immediate', + func = function() + self.delay_edition = nil + return true + end + })) + end return end @@ -1464,39 +1883,17 @@ function Card:set_edition(edition, immediate, silent, delay) self.ignore_shadow[self.edition.key] = true end - local on_edition_applied = p_edition.on_apply - if type(on_edition_applied) == "function" then - on_edition_applied(self) - end - for k, v in pairs(p_edition.config) do if type(v) == 'table' then self.edition[k] = copy_table(v) else self.edition[k] = v end - if k == 'card_limit' and (self.added_to_deck or self.joker_added_to_deck_but_debuffed or (self.area == G.hand and not self.debuff)) and G.jokers and G.consumeables then - if self.ability.consumeable then - G.consumeables.config.card_limit = G.consumeables.config.card_limit + v - elseif self.ability.set == 'Joker' then - G.jokers.config.card_limit = G.jokers.config.card_limit + v - elseif self.area == G.hand then - local is_in_pack = (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK or (G.STATE == G.STATES.SMODS_BOOSTER_OPENED and SMODS.OPENED_BOOSTER.config.center.draw_hand)) - G.E_MANAGER:add_event(Event({ - trigger = 'immediate', - func = function() - if G.hand.config.real_card_limit then - G.hand.config.real_card_limit = G.hand.config.real_card_limit + v - end - G.hand.config.card_limit = G.hand.config.card_limit + v - if not is_in_pack and G.GAME.blind.in_blind then - G.FUNCS.draw_from_deck_to_hand(v) - end - return true - end - })) - end - end + end + + local on_edition_applied = p_edition.on_apply + if type(on_edition_applied) == "function" then + on_edition_applied(self) end if self.area and self.area == G.jokers then @@ -1537,7 +1934,7 @@ function Card:set_edition(edition, immediate, silent, delay) end if delay then - self.delay_edition = true + self.delay_edition = old_edition or {base = true} G.E_MANAGER:add_event(Event({ trigger = 'immediate', func = function() @@ -1547,6 +1944,11 @@ function Card:set_edition(edition, immediate, silent, delay) })) end + self.ability.card_limit = self.ability.card_limit + (self.edition.card_limit or 0) + self.ability.extra_slots_used = self.ability.extra_slots_used + (self.edition.extra_slots_used or 0) + if self.area then self.area:handle_card_limit(self.edition.card_limit, self.edition.extra_slots_used) end + + if G.jokers and self.area == G.jokers then check_for_unlock({ type = 'modify_jokers' }) end @@ -1566,28 +1968,34 @@ function poll_edition(_key, _mod, _no_neg, _guaranteed, _options) local available_editions = {} -- Table containing a list of editions and their weights if not _options then - _options = { 'e_negative', 'e_polychrome', 'e_holo', 'e_foil' } if _key == "wheel_of_fortune" or _key == "aura" then -- set base game edition polling + _options = { 'e_negative', 'e_polychrome', 'e_holo', 'e_foil' } else - for _, v in ipairs(G.P_CENTER_POOLS.Edition) do - local in_pool = (v.in_pool and type(v.in_pool) == "function") and v:in_pool({source = _key}) - if in_pool or v.in_shop then - table.insert(_options, v.key) + local unordered_options = get_current_pool("Edition", nil, nil, _key or 'edition_generic') + _options = {} + for _, edition in ipairs(unordered_options) do -- Flip the order of vanilla editions + if G.P_CENTERS[edition] and G.P_CENTERS[edition].vanilla then + table.insert(_options, 1, edition) + else + table.insert(_options, edition) end end end end - for _, v in ipairs(_options) do - local edition_option = {} - if type(v) == 'string' then - assert(string.sub(v, 1, 2) == 'e_') - edition_option = { name = v, weight = G.P_CENTERS[v].weight } - elseif type(v) == 'table' then - assert(string.sub(v.name, 1, 2) == 'e_') - edition_option = { name = v.name, weight = v.weight } - end - table.insert(available_editions, edition_option) - end + for _, v in ipairs(_options) do + local edition_option = {} + if type(v) == 'string' then + if v ~= 'UNAVAILABLE' then + assert(string.sub(v, 1, 2) == 'e_', ("Edition \"%s\" is missing \"e_\" prefix."):format(v)) + edition_option = { name = v, weight = G.P_CENTERS[v].weight } + table.insert(available_editions, edition_option) + end + elseif type(v) == 'table' then + assert(string.sub(v.name, 1, 2) == 'e_', ("Edition \"%s\" is missing \"e_\" prefix."):format(v.name)) + edition_option = { name = v.name, weight = v.weight } + table.insert(available_editions, edition_option) + end + end -- Calculate total weight of editions local total_weight = 0 @@ -1643,7 +2051,7 @@ function get_joker_win_sticker(_center, index) local applied = {} local _count = 0 local _stake = nil - for k, v in pairs(joker_usage.wins_by_key) do + for k, v in pairs(joker_usage.wins_by_key or {}) do SMODS.build_stake_chain(G.P_STAKES[k], applied) end for i, v in ipairs(G.P_CENTER_POOLS.Stake) do @@ -1777,7 +2185,7 @@ function get_pack(_key, _type) v.current_weight = v.get_weight and v:get_weight() or v.weight or 1 if (not _type or _type == v.kind) then add = true end if v.in_pool and type(v.in_pool) == 'function' then - local res, pool_opts = v:in_pool() + local res, pool_opts = SMODS.add_to_pool(v) pool_opts = pool_opts or {} add = res and (add or pool_opts.override_base_checks) end @@ -1793,25 +2201,6 @@ function get_pack(_key, _type) if not center then center = G.P_CENTERS['p_buffoon_normal_1'] end return center end ---#region quantum enhancements API --- prevent base chips from applying with extra enhancements -local gcb = Card.get_chip_bonus -function Card:get_chip_bonus() - if not self.ability.extra_enhancement then - return gcb(self) - end - if self.debuff then return 0 end - return self.ability.bonus + (self.ability.perma_bonus or 0) -end - --- prevent quantum enhacements from applying seal effects -local ccs = Card.calculate_seal -function Card:calculate_seal(context) - if self.ability.extra_enhancement then return end - return ccs(self, context) -end ---#endregion - function playing_card_joker_effects(cards) SMODS.calculate_context({playing_card_added = true, cards = cards}) end @@ -1943,3 +2332,80 @@ function Blind:modify_hand(cards, poker_hands, text, mult, hand_chips, scoring_h local flags = SMODS.calculate_context({ modify_hand = true, poker_hands = poker_hands, scoring_name = text, scoring_hand = scoring_hand, full_hand = cards }) return _G.mult, _G.hand_chips, modded or flags.calculated end + +local card_set_base = Card.set_base +function Card:set_base(card, initial, manual_sprites) + if self.playing_card and self.base then + local new_rank = card and card.value and SMODS.Ranks[card.value] and SMODS.Ranks[card.value].id + local contexts = {} + if new_rank then + if self.base.id and self.base.id ~= new_rank then + SMODS.merge_defaults(contexts, {change_rank = true, other_card = self, new_rank = new_rank, old_rank = self.base.id, rank_increase = ((self.base.id < new_rank) and true) or false}) + end + end + if card and card.suit and self.base.suit ~= card.suit then + SMODS.merge_defaults(contexts, {change_suit = true, other_card = self, new_suit = card.suit, old_suit = self.base.suit}) + end + if next(contexts) then + contexts.ignore_other_debuff = true + SMODS.calculate_context(contexts) + end + end + + card_set_base(self, card, initial, manual_sprites) +end + +local use_consumeable = Card.use_consumeable +function Card:use_consumeable(area, copier) + local ret = use_consumeable(self, area, copier) + if SMODS.post_prob and next(SMODS.post_prob) then + local prob_tables = SMODS.post_prob + SMODS.post_prob = {} + for i, v in ipairs(prob_tables) do + v.pseudorandom_result = true + SMODS.calculate_context(v) + end + end + return ret +end + +local ease_ante_ref = ease_ante +function ease_ante(mod, ante_end) + local flags = SMODS.calculate_context({modify_ante = mod, ante_end = ante_end}) + if flags.modify then mod = mod + flags.modify end + ease_ante_ref(mod) + SMODS.calculate_context({ante_change = mod, ante_end = ante_end}) +end + +local eval_card_ref = eval_card +function eval_card(card, context) + SMODS.push_to_context_stack(context, "overrides.lua : eval_card") + local eff, post = eval_card_ref(card, context) + SMODS.pop_from_context_stack(context, "overrides.lua : eval_card") + return eff, post +end + +local calculate_seal_ref = Card.calculate_seal +function Card:calculate_seal(context, ...) + SMODS.push_to_context_stack(context, "overrides.lua : Card.calculate_seal") + local eff, post = calculate_seal_ref(self, context, ...) + SMODS.pop_from_context_stack(context, "overrides.lua : Card.calculate_seal") + return eff, post +end + +local calculate_joker_ref = Card.calculate_joker +function Card:calculate_joker(context, ...) + SMODS.push_to_context_stack(context, "overrides.lua : Card.calculate_joker") + local eff, post = calculate_joker_ref(self, context, ...) + SMODS.pop_from_context_stack(context, "overrides.lua : Card.calculate_joker") + return eff, post +end + +local set_ability = Card.set_ability +function Card:set_ability(center, initial, delay_sprites) + local old_center = self.config.center + set_ability(self, center, initial, delay_sprites) + if not initial and G.STATE ~= G.STATES.SMODS_BOOSTER_OPENED and G.STATE ~= G.STATES.SHOP and not G.SETTINGS.paused or G.TAROT_INTERRUPT then + SMODS.calculate_context({setting_ability = true, old = old_center.key, new = self.config.center_key, other_card = self, unchanged = old_center.key == self.config.center.key}) + end +end \ No newline at end of file diff --git a/Steamodded/src/ui.lua b/Steamodded/src/ui.lua index 1695f33..36be30e 100644 --- a/Steamodded/src/ui.lua +++ b/Steamodded/src/ui.lua @@ -18,6 +18,46 @@ function STR_UNPACK(str) end end +-- used for icons for correct scaling +SMODS.pixels_to_unit = function(value) return value/(G.TILESCALE*G.TILESIZE) end +SMODS.trim_string = function (s) + local l = 1 + while string.sub(s,l,l) == ' ' do + l = l+1 + end + local r = string.len(s) + while string.sub(s,r,r) == ' ' do + r = r-1 + end + return string.sub(s,l,r) +end +SMODS.smart_line_splitter = function(phrase, length, always_new_line) + local words = {} + local current_line = "" + for word in phrase:gmatch("%S+") do + -- concat string if it is not at the limit + if string.len(current_line .. word) <= length then + current_line = current_line .. word .. " " + -- this will only happen if word is longer than specified length + else + -- if it's longer than half length then put it in new line + if string.len(current_line) >= length/2 or always_new_line then + SMODS.trim_string(current_line) + table.insert(words,current_line) + current_line = word .. " " + + else + current_line = current_line .. word + table.insert(words,current_line) + current_line = "" + end + end + end + if current_line ~= "" and current_line ~= " " then + table.insert(words,current_line) + end + return words +end local gameMainMenuRef = Game.main_menu function Game:main_menu(change_context) @@ -176,6 +216,10 @@ function create_UIBox_mods(args) end return (create_UIBox_generic_options({ + colour = (mod.ui_config or {}).colour, + bg_colour = (mod.ui_config or {}).bg_colour, + back_colour = (mod.ui_config or {}).back_colour, + outline_colour = (mod.ui_config or {}).outline_colour, back_func = "mods_button", contents = { { @@ -187,7 +231,7 @@ function create_UIBox_mods(args) nodes = { create_tabs({ snap_to_nav = true, - colour = G.C.BOOSTER, + colour = (mod.ui_config or {}).tab_button_colour or G.C.BOOSTER, tabs = mod_tabs }) } @@ -220,7 +264,7 @@ function buildModDescTab(mod) local authors = localize('b_author' .. (#mod.author > 1 and 's' or '')) .. ': ' .. concatAuthors(mod.author) - -- Authors names in blue + -- Authors names table.insert(modNodes, { n = G.UIT.R, config = { @@ -228,7 +272,9 @@ function buildModDescTab(mod) r = 0.1, emboss = 0.1, outline = 1, - padding = 0.07 + padding = 0.07, + outline_colour = (mod.ui_config or {}).author_outline_colour, + colour = (mod.ui_config or {}).author_bg_colour, }, nodes = { { @@ -237,7 +283,7 @@ function buildModDescTab(mod) text = authors, shadow = true, scale = scale * 0.65, - colour = G.C.BLUE, + colour = (mod.ui_config or {}).author_colour or G.C.BLUE, } } } @@ -328,11 +374,11 @@ end function buildAdditionsTab(mod) local consumable_nodes = {} - for _, key in ipairs(SMODS.ConsumableType.ctype_buffer) do + for _, key in ipairs(SMODS.ConsumableType.visible_buffer) do local id = 'your_collection_'..key:lower()..'s' local tally = modsCollectionTally(G.P_CENTER_POOLS[key]) if tally.of > 0 then - consumable_nodes[#consumable_nodes+1] = UIBox_button({button = id, label = {localize('b_'..key:lower()..'_cards')}, count = tally, minw = 4, id = id, colour = G.C.SECONDARY_SET[key]}) + consumable_nodes[#consumable_nodes+1] = UIBox_button({button = id, label = {localize('b_'..key:lower()..'_cards')}, count = tally, minw = 4, id = id, colour = G.C.SECONDARY_SET[key], text_colour = G.C.UI[key]}) end end if #consumable_nodes > 3 then @@ -480,7 +526,17 @@ function create_UIBox_Other_GameObjects() {n=G.UIT.R, config={align = "cm", padding = 0.15}, nodes = custom_gameobject_rows} }} - return create_UIBox_generic_options({ back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or 'your_collection', contents = {t}}) + return create_UIBox_generic_options({ + colour = G.ACTIVE_MOD_UI and ((G.ACTIVE_MOD_UI.ui_config or {}).collection_colour or + (G.ACTIVE_MOD_UI.ui_config or {}).colour), + bg_colour = G.ACTIVE_MOD_UI and ((G.ACTIVE_MOD_UI.ui_config or {}).collection_bg_colour or + (G.ACTIVE_MOD_UI.ui_config or {}).bg_colour), + back_colour = G.ACTIVE_MOD_UI and ((G.ACTIVE_MOD_UI.ui_config or {}).collection_back_colour or + (G.ACTIVE_MOD_UI.ui_config or {}).back_colour), + outline_colour = G.ACTIVE_MOD_UI and ((G.ACTIVE_MOD_UI.ui_config or {}).collection_outline_colour or + (G.ACTIVE_MOD_UI.ui_config or {}).outline_colour), + back_func = G.ACTIVE_MOD_UI and "openModUI_" .. G.ACTIVE_MOD_UI.id or 'your_collection', contents = { t } } + ) else return nil end @@ -494,7 +550,16 @@ G.FUNCS.your_collection_consumables = function(e) end function create_UIBox_your_collection_consumables() - local t = create_UIBox_generic_options({ back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or 'your_collection', contents = { + local t = create_UIBox_generic_options({ + colour = G.ACTIVE_MOD_UI and ((G.ACTIVE_MOD_UI.ui_config or {}).collection_colour or + (G.ACTIVE_MOD_UI.ui_config or {}).colour), + bg_colour = G.ACTIVE_MOD_UI and ((G.ACTIVE_MOD_UI.ui_config or {}).collection_bg_colour or + (G.ACTIVE_MOD_UI.ui_config or {}).bg_colour), + back_colour = G.ACTIVE_MOD_UI and ((G.ACTIVE_MOD_UI.ui_config or {}).collection_back_colour or + (G.ACTIVE_MOD_UI.ui_config or {}).back_colour), + outline_colour = G.ACTIVE_MOD_UI and ((G.ACTIVE_MOD_UI.ui_config or {}).collection_outline_colour or + (G.ACTIVE_MOD_UI.ui_config or {}).outline_colour), + back_func = G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or 'your_collection', contents = { { n = G.UIT.C, config = { align = 'cm', minw = 11.5, minh = 6 }, nodes = { { n = G.UIT.O, config = { id = 'consumable_collection', object = Moveable() },} }}, @@ -527,11 +592,11 @@ G.UIDEF.consumable_collection_page = function(page) local page_offset = nodes_per_page * ((page or 1) - 1) local type_buf = {} if G.ACTIVE_MOD_UI then - for _, v in ipairs(SMODS.ConsumableType.ctype_buffer) do + for _, v in ipairs(SMODS.ConsumableType.visible_buffer) do if modsCollectionTally(G.P_CENTER_POOLS[v]).of > 0 then type_buf[#type_buf + 1] = v end end else - type_buf = SMODS.ConsumableType.ctype_buffer + type_buf = SMODS.ConsumableType.visible_buffer end local center_options = {} for i = 1, math.ceil(#type_buf / nodes_per_page) do @@ -546,7 +611,7 @@ G.UIDEF.consumable_collection_page = function(page) opt_callback = 'your_collection_consumables_page', focus_args = { snap_to = true, nav = 'wide' }, current_option = page or 1, - colour = G.C.RED, + colour = G.ACTIVE_MOD_UI and (G.ACTIVE_MOD_UI.ui_config or {}).collection_option_cycle_colour or G.C.RED, no_pips = true }) } local function create_consumable_nodes(_start, _end) @@ -558,7 +623,7 @@ G.UIDEF.consumable_collection_page = function(page) t[#t+1] = { n = G.UIT.R, config = { align ='cm', minh = 0.81 }, nodes = {}} else local id = 'your_collection_'..key:lower()..'s' - t[#t+1] = UIBox_button({button = id, label = {localize('b_'..key:lower()..'_cards')}, count = G.ACTIVE_MOD_UI and modsCollectionTally(G.P_CENTER_POOLS[key]) or G.DISCOVER_TALLIES[key:lower()..'s'], minw = 4, id = id, colour = G.C.SECONDARY_SET[key]}) + t[#t+1] = UIBox_button({button = id, label = {localize('b_'..key:lower()..'_cards')}, count = G.ACTIVE_MOD_UI and modsCollectionTally(G.P_CENTER_POOLS[key]) or G.DISCOVER_TALLIES[key:lower()..'s'], minw = 4, id = id, colour = G.C.SECONDARY_SET[key], text_colour = G.C.UI[key]}) end end return t @@ -596,7 +661,7 @@ function buildAchievementsTab(mod, current_page) for i = 1, achievements_per_row*2 do local v = achievement_tab[i+((achievements_per_row*2)*(current_page-1))] if not v then break end - local temp_achievement = Sprite(0,0,1.1,1.1,G.ASSET_ATLAS[v.atlas or "achievements"], v.earned and v.pos or {x=0, y=0}) + local temp_achievement = Sprite(0,0,1.1,1.1,G.ASSET_ATLAS[v.atlas or "achievements"], v.earned and v.pos or v.hidden_pos) temp_achievement:define_draw_steps({ {shader = 'dissolve', shadow_height = 0.05}, {shader = 'dissolve'} @@ -659,9 +724,15 @@ function buildAchievementsTab(mod, current_page) return wrappedText end - local loc_target = (v.hidden_text and not v.earned) and {localize("hidden_achievement", 'achievement_descriptions')} or localize(v.key, 'achievement_descriptions') + local loc_target + if (v.hidden_text and not v.earned) then + loc_target = (localize(v.key.."_hidden", 'achievement_descriptions') ~= 'ERROR') and localize(v.key.."_hidden", 'achievement_descriptions') or {localize("hidden_achievement", 'achievement_descriptions')} + else loc_target = localize(v.key, 'achievement_descriptions') end if type(loc_target) == 'string' then loc_target = wrapText(loc_target, maxCharsPerLine) end - local loc_name = (v.hidden_name and not v.earned) and localize("hidden_achievement", 'achievement_names') or localize(v.key, 'achievement_names') + local loc_name + if (v.hidden_name and not v.earned) then + loc_name = (localize(v.key.."_hidden", 'achievement_names') ~= 'ERROR') and localize(v.key.."_hidden", 'achievement_names') or localize("hidden_achievement", 'achievement_names') + else loc_name = localize(v.key, 'achievement_names') end local ability_text = {} if loc_target then @@ -823,11 +894,17 @@ function buildModtag(mod) local tag_atlas, tag_pos, tag_message, specific_vars = getModtagInfo(mod) local tag_sprite_tab = nil - - local tag_sprite = Sprite(0, 0, 0.8*1, 0.8*1, G.ASSET_ATLAS[tag_atlas] or G.ASSET_ATLAS['tags'], tag_pos) + local units = SMODS.pixels_to_unit(34) * 2 + local animated = G.ANIMATION_ATLAS[tag_atlas] or nil + local tag_sprite + if animated then + tag_sprite = AnimatedSprite(0, 0, 0.8*1, 0.8*1, animated or G.ASSET_ATLAS[tag_atlas] or G.ASSET_ATLAS['tags'], tag_pos) + else + tag_sprite = Sprite(0, 0, 0.8*1, 0.8*1, G.ASSET_ATLAS[tag_atlas] or G.ASSET_ATLAS['tags'], tag_pos) + end tag_sprite.T.scale = 1 tag_sprite_tab = {n= G.UIT.C, config={align = "cm", padding = 0}, nodes={ - {n=G.UIT.O, config={w=0.8*1, h=0.8*1, colour = G.C.BLUE, object = tag_sprite, focus_with_object = true}}, + {n=G.UIT.O, config={w=units, h=units, colour = G.C.BLUE, object = tag_sprite, focus_with_object = true}}, }} tag_sprite:define_draw_steps({ {shader = 'dissolve', shadow_height = 0.05}, @@ -835,6 +912,7 @@ function buildModtag(mod) }) tag_sprite.float = true tag_sprite.states.hover.can = true + tag_sprite.states.click.can = true tag_sprite.states.drag.can = false tag_sprite.states.collide.can = true @@ -850,7 +928,7 @@ function buildModtag(mod) end tag_sprite.ability_UIBox_table = generate_card_ui({set = "Other", discovered = false, key = tag_message}, nil, specific_vars, 'Other', nil, false) _self.config.h_popup = G.UIDEF.card_h_popup(_self) - _self.config.h_popup_config ={align = 'cl', offset = {x=-0.1,y=0},parent = _self} + _self.config.h_popup_config ={align = 'tm', offset = {x= 0,y=-0.1},parent = _self} Node.hover(_self) if _self.children.alert then _self.children.alert:remove() @@ -860,6 +938,11 @@ function buildModtag(mod) end end end + tag_sprite.click = function(self) + play_sound('button', 1, 0.3) + G.ROOM.jiggle = G.ROOM.jiggle + 0.5 + G.FUNCS["openModUI_" .. mod.id](self) + end tag_sprite.stop_hover = function(_self) _self.hovering = false; Node.stop_hover(_self); _self.hover_tilt = 0 end tag_sprite:juice_up() @@ -867,122 +950,181 @@ function buildModtag(mod) return tag_sprite_tab end +local function createTextColNode(text, scale, colour, node) + return { n = node or G.UIT.R, config = { padding = 0, align = "lc", maxw = 2.8, maxh = 1.5, }, nodes = { + { n = G.UIT.T, config = { text = text, colour = colour or G.C.UI.TEXT_LIGHT, scale = scale * 0.7 } }, + } + } +end + + -- Helper function to create a clickable mod box local function createClickableModBox(modInfo, scale) local function invert(c) return {1-c[1], 1-c[2], 1-c[3], c[4]} end - local col, text_col + local col, text_col, bg_col if modInfo.should_enable == nil then modInfo.should_enable = not modInfo.disabled end if SMODS.full_restart == nil then SMODS.full_restart = 0 end + if modInfo.can_load then - col = G.C.BOOSTER + col = mix_colours(G.C.UI.TEXT_DARK, {0.7,0.8,0.9,1}, 0.8) elseif modInfo.disabled then - col = G.C.UI.BACKGROUND_INACTIVE - elseif G.SETTINGS.reduced_motion then - col = mix_colours(G.C.RED, G.C.UI.BACKGROUND_INACTIVE, 0.7) + col = mix_colours(G.C.UI.BACKGROUND_INACTIVE, {0,0,0,1}, 0.6) + else + col = G.C.RED text_col = G.C.TEXT_DARK - else - col = SMODS.Gradients.warning_bg - text_col = SMODS.Gradients.warning_text end - local label = { " " .. modInfo.name .. " " } - if modInfo.lovely_only then - label[2] = localize('b_lovely_mod') - else - label[2] = localize('b_by') .. concatAuthors(modInfo.author) .. " " + bg_col = mix_colours({0.5,0.5,0.5,0.2},col,0.5) + local label_nodes = {} + local modname_split = SMODS.smart_line_splitter(modInfo.name,18,true) + for _,v in ipairs(modname_split) do + table.insert(label_nodes,createTextColNode(v, scale * 1.2, text_col)) end - local but = UIBox_button { - label = label, - shadow = true, - scale = scale, - colour = col, - text_colour = text_col, - button = "openModUI_" .. modInfo.id, - minh = 0.8, - minw = 7 - } local version_col = copy_table(G.C.WHITE) version_col[4] = 0.6 if modInfo.lovely_only then - local config = but.nodes[1].nodes[2].nodes[1].config - config.colour = version_col - config.scale = scale * .8 + table.insert(label_nodes,createTextColNode(localize('b_lovely_mod'), scale, version_col)) end + local sub_node_1 = {} + local under_checkbox_nodes = {} if modInfo.version and modInfo.version ~= '0.0.0' then - table.insert(but.nodes[1].nodes[1].nodes, { - n = G.UIT.T, - config = { - text = ('(%s) '):format(modInfo.version), - scale = scale*0.8, - colour = version_col, - shadow = true, - }, - }) + table.insert(sub_node_1, createTextColNode(('%s'):format(modInfo.version), scale, version_col, G.UIT.C)) end if modInfo.config_tab then - table.insert(but.nodes[1].nodes[1].nodes, { - n = G.UIT.O, + local is_config_func = type(modInfo.config_tab) == "function" + table.insert(under_checkbox_nodes, { + n = G.UIT.R, + config = { + page = is_config_func and "config", + padding = 0.1, + align = "cm", + colour = is_config_func and G.C.BLUE, + button = is_config_func and ("openModUI_" .. modInfo.id), shadow = is_config_func, shadow_height = 0.5, r = 0.1, hover = is_config_func }, + nodes = { + { + n = G.UIT.O, + config = { + object = Sprite(0,0,0.3,0.3, G.ASSET_ATLAS['mod_tags'], {x=2,y=0}) + } + } + } + }) + end + if #sub_node_1 > 0 then + table.insert(label_nodes, { + n = G.UIT.R, config = { - object = Sprite(0,0,0.4,0.4, G.ASSET_ATLAS['mod_tags'], {x=2,y=0}) + + }, + nodes = sub_node_1 + }) + end + if not modInfo.lovely_only then + local tx = concatAuthors(modInfo.author, 12) + local the_colour = mix_colours(G.C.BLACK, G.C.WHITE, 0.2) + the_colour[4] = 0.8 + local authorDynatext = DynaText{ + string = tx, + scale = scale * 0.7, + colours = {the_colour}, + shadow = true, + maxw = 2.4, + marquee = true, + } + table.insert(label_nodes, + { n = G.UIT.R, config = { padding = 0, align = "lc", maxw = 4.5, maxh = 1.5, }, nodes = { + { n = G.UIT.T, config = {text= localize('b_by'), scale = scale*0.7, colour = the_colour}}, + { + n = G.UIT.O, config = {object = authorDynatext} + } } }) end if not _RELEASE_MODE and modInfo.priority then - table.insert(but.nodes[1].nodes[2].nodes, { - n = G.UIT.T, - config = { - text = ('(%s%s) '):format(localize('b_priority'), number_format(modInfo.priority)), - scale = scale*0.8, - colour = version_col, - shadow = true, - }, - }) + table.insert(label_nodes, createTextColNode(('%s%s'):format(localize('b_priority'), number_format(modInfo.priority)), scale, version_col)) end + return { - n = G.UIT.R, - config = { padding = 0, align = "cm" }, + n = G.UIT.C, + config = { align = "cm", padding = 0.05 }, nodes = { - { - n = G.UIT.C, - config = { align = "cm" }, + { n = G.UIT.C, config = { padding = 0.05, align = "cm", colour = bg_col, r = 0.1, minw = 1.5, minh = 1}, nodes = { - buildModtag(modInfo) + { + n = G.UIT.C, + config = { + padding = 0.1, + align = "lc", + button = "openModUI_" .. modInfo.id, + minw = 4.25, + minh = 1.4, + maxh = 1.4, + r = 0.1, + colour = col, + shadow = true, + shadow_height = 0.5, + hover = true, + }, + nodes = { + { + n = G.UIT.C, + config = { align = "cm" }, + nodes = { + buildModtag(modInfo), + } + }, + { + n = G.UIT.C, + config = { align = "lc",}, + nodes = label_nodes + }, + } + }, + { + n = G.UIT.C, + config = { padding = 0.05, align = "cm"}, + nodes = { + { + n = G.UIT.R, + config = { align = "cm"}, + nodes = { + create_toggle({ + label = '', + ref_table = modInfo, + ref_value = 'should_enable', + col = true, + hide_label = true, + w = 0, + h = 0.2, + scale = 1, + callback = ( + function(_set_toggle) + if not modInfo.should_enable then + NFS.write(modInfo.path .. '.lovelyignore', '') + else + NFS.remove(modInfo.path .. '.lovelyignore') + end + local toChange = 1 + if modInfo.should_enable == not modInfo.disabled then + toChange = -1 + end + SMODS.full_restart = SMODS.full_restart + toChange + end) + }) + } + }, + unpack(under_checkbox_nodes) + } + } } - }, - { - n = G.UIT.C, - config = { align = "cm", padding = 0.1 }, - nodes = {}, - }, - { n = G.UIT.C, config = { padding = 0, align = "cm" }, nodes = { but } }, - create_toggle({ - label = '', - ref_table = modInfo, - ref_value = 'should_enable', - col = true, - w = 0, - h = 0.5, - callback = ( - function(_set_toggle) - if not modInfo.should_enable then - NFS.write(modInfo.path .. '.lovelyignore', '') - else - NFS.remove(modInfo.path .. '.lovelyignore') - end - local toChange = 1 - if modInfo.should_enable == not modInfo.disabled then - toChange = -1 - end - SMODS.full_restart = SMODS.full_restart + toChange - end - ) - }), - }} + } + } + } end @@ -1502,7 +1644,6 @@ local function generateBaseNode(staticPageDefinition) r = 0.1, minw = 8, align = "cm", - padding = 0.2, colour = G.C.BLACK }, nodes = { @@ -1533,7 +1674,7 @@ function SMODS.GUI.DynamicUIManager.updateDynamicAreas(uiDefinitions) dynamicArea.config.object:remove() dynamicArea.config.object = UIBox{ definition = uiDefinition, - config = {offset = {x=0, y=0}, align = 'cm', parent = dynamicArea} + config = {offset = {x=0, y=0.5}, align = 'cm', parent = dynamicArea} } end end @@ -1542,10 +1683,11 @@ end local function recalculateModsList(page) page = page or SMODS.LAST_VIEWED_MODS_PAGE or 1 SMODS.LAST_VIEWED_MODS_PAGE = page - local modsPerPage = 4 - local startIndex = (page - 1) * modsPerPage + 1 - local endIndex = startIndex + modsPerPage - 1 - local totalPages = math.ceil(#SMODS.mod_list / modsPerPage) + local modsRowPerPage = 4 + local modsColPerRow = 3 + local startIndex = (page - 1) * modsRowPerPage * modsColPerRow + 1 + local endIndex = startIndex + modsRowPerPage * modsColPerRow - 1 + local totalPages = math.ceil(#SMODS.mod_list / (modsRowPerPage * modsColPerRow)) local currentPage = localize('k_page') .. ' ' .. page .. "/" .. totalPages local pageOptions = {} for i = 1, totalPages do @@ -1553,7 +1695,7 @@ local function recalculateModsList(page) end local showingList = #SMODS.mod_list > 0 - return currentPage, pageOptions, showingList, startIndex, endIndex, modsPerPage + return currentPage, pageOptions, showingList, startIndex, endIndex, modsRowPerPage, modsColPerRow end -- Define the content in the pane that does not need to update @@ -1563,25 +1705,25 @@ function SMODS.GUI.staticModListContent() local scale = 0.75 local currentPage, pageOptions, showingList = recalculateModsList() return { - n = G.UIT.ROOT, + n = G.UIT.R, config = { - minh = 6, + minh = 8.5, r = 0.1, - minw = 10, - align = "tm", - padding = 0.2, + minw = 17, + align = "cm", + padding = 0.05, colour = G.C.BLACK }, nodes = { -- row container { - n = G.UIT.R, + n = G.UIT.C, config = { align = "cm", padding = 0.05 }, nodes = { -- column container { n = G.UIT.C, - config = { align = "cm", minw = 3, padding = 0.2, r = 0.1, colour = G.C.CLEAR }, + config = { align = "cm", minw = 5, padding = 0.05, r = 0.1, colour = G.C.CLEAR }, nodes = { -- title row { @@ -1626,27 +1768,26 @@ function SMODS.GUI.staticModListContent() }, -- dynamic content rendered in this row container - -- list of 4 mods on the current page + -- list of 4 x 4 mods on the current page { n = G.UIT.R, config = { padding = 0.05, align = "cm", - minh = 2, - minw = 4 + minh = 5, + minw = 5 }, nodes = { - {n=G.UIT.O, config={id = 'modsList', object = Moveable()}}, + {n=G.UIT.O, config={align = "cm", id = 'modsList', object = Moveable()}}, } }, -- another empty row for spacing { n = G.UIT.R, - config = { align = "cm", padding = 0.3 }, + config = { align = "cm", padding = 0.8 }, nodes = {} }, - -- page selector -- does not appear when list of mods is empty showingList and SMODS.GUI.createOptionSelector({label = "", scale = 0.8, options = pageOptions, opt_callback = 'update_mod_list', no_pips = true, current_option = ( @@ -1662,7 +1803,7 @@ end function SMODS.GUI.dynamicModListContent(page) local scale = 0.75 - local _, __, showingList, startIndex, endIndex, modsPerPage = recalculateModsList(page) + local _, __, showingList, startIndex, endIndex, modsRowPerPage, modsColPerRow = recalculateModsList(page) local modNodes = {} @@ -1689,6 +1830,7 @@ function SMODS.GUI.dynamicModListContent(page) else local modCount = 0 local id = 0 + local current_row = {} for _, condition in ipairs({ function(m) return not m.can_load and not m.disabled end, @@ -1697,16 +1839,31 @@ function SMODS.GUI.dynamicModListContent(page) function(m) return m.disabled end, }) do for _, modInfo in ipairs(SMODS.mod_list) do - if modCount >= modsPerPage then break end + if modCount >= modsRowPerPage * modsColPerRow then break end if condition(modInfo) then id = id + 1 if id >= startIndex and id <= endIndex then - table.insert(modNodes, createClickableModBox(modInfo, scale * 0.5)) + table.insert(current_row, createClickableModBox(modInfo, scale * 0.5)) modCount = modCount + 1 + if math.fmod(modCount, modsColPerRow) == 0 then + table.insert(modNodes, { + n = G.UIT.R, + config = { padding = 0, align = "lc"}, + nodes = current_row + }) + current_row = {} + end end end end end + if #current_row > 0 then + table.insert(modNodes, { + n = G.UIT.R, + config = { padding = 0, align = "lc"}, + nodes = current_row + }) + end end return { @@ -1714,7 +1871,7 @@ function SMODS.GUI.dynamicModListContent(page) config = { r = 0.1, align = "cm", - padding = 0.2, + padding = 0, }, nodes = modNodes } @@ -1785,10 +1942,16 @@ SMODS.card_collection_UIBox = function(_pool, rows, args) G.FUNCS.SMODS_card_collection_page{ cycle_config = { current_option = 1 }} - local t = create_UIBox_generic_options({ back_func = (args and args.back_func) or G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or 'your_collection', snap_back = args.snap_back, infotip = args.infotip, contents = { + local t = create_UIBox_generic_options({ + colour = G.ACTIVE_MOD_UI and ((G.ACTIVE_MOD_UI.ui_config or {}).collection_colour or (G.ACTIVE_MOD_UI.ui_config or {}).colour), + bg_colour = G.ACTIVE_MOD_UI and ((G.ACTIVE_MOD_UI.ui_config or {}).collection_bg_colour or (G.ACTIVE_MOD_UI.ui_config or {}).bg_colour), + back_colour = G.ACTIVE_MOD_UI and ((G.ACTIVE_MOD_UI.ui_config or {}).collection_back_colour or (G.ACTIVE_MOD_UI.ui_config or {}).back_colour), + outline_colour = G.ACTIVE_MOD_UI and ((G.ACTIVE_MOD_UI.ui_config or {}).collection_outline_colour or + (G.ACTIVE_MOD_UI.ui_config or {}).outline_colour), + back_func = (args and args.back_func) or G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or 'your_collection', snap_back = args.snap_back, infotip = args.infotip, contents = { {n=G.UIT.R, config={align = "cm", r = 0.1, colour = G.C.BLACK, emboss = 0.05}, nodes=deck_tables}, (not args.hide_single_page or cards_per_page < #pool) and {n=G.UIT.R, config={align = "cm"}, nodes={ - create_option_cycle({options = options, w = 4.5, cycle_shoulders = true, opt_callback = 'SMODS_card_collection_page', current_option = 1, colour = G.C.RED, no_pips = true, focus_args = {snap_to = true, nav = 'wide'}}) + create_option_cycle({options = options, w = 4.5, cycle_shoulders = true, opt_callback = 'SMODS_card_collection_page', current_option = 1, colour = G.ACTIVE_MOD_UI and (G.ACTIVE_MOD_UI.ui_config or {}).collection_option_cycle_colour or G.C.RED, no_pips = true, focus_args = {snap_to = true, nav = 'wide'}}) }} or nil, }}) return t @@ -1915,3 +2078,99 @@ function G.UIDEF.run_setup_option(_type) end return ret end + +-- Hand Score UI Utils + +function SMODS.GUI.hand_score_display_ui(scale) + return + -- Outer shell container + {n=G.UIT.R, config={align = "cm", id = 'hand_text_area', func = 'SMODS_scoring_calculation_function', colour = darken(G.C.BLACK, 0.1), r = 0.1, emboss = 0.05, padding = 0.03}, nodes={ + -- Inner shell container + {n=G.UIT.C, config={align = "cm"}, nodes={ + -- Hand type display container + SMODS.GUI.current_hand_ui(scale), + -- Chips X Mult container + SMODS.GUI.hand_chips_container(scale), + }} + }} +end + +function SMODS.GUI.current_hand_ui(scale) + return + {n=G.UIT.R, config={align = "cm", minh = 1.1}, nodes={ + {n=G.UIT.O, config={id = 'hand_name', func = 'hand_text_UI_set',object = DynaText({string = {{ref_table = G.GAME.current_round.current_hand, ref_value = "handname_text"}}, colours = {G.C.UI.TEXT_LIGHT}, shadow = true, float = true, scale = scale*1.4})}}, + {n=G.UIT.O, config={id = 'hand_chip_total', func = 'hand_chip_total_UI_set',object = DynaText({string = {{ref_table = G.GAME.current_round.current_hand, ref_value = "chip_total_text"}}, colours = {G.C.UI.TEXT_LIGHT}, shadow = true, float = true, scale = scale*1.4})}}, + {n=G.UIT.T, config={ref_table = G.GAME.current_round.current_hand, ref_value='hand_level', scale = scale, colour = G.C.UI.TEXT_LIGHT, id = 'hand_level', shadow = true}}, + }} +end + +function SMODS.GUI.hand_chips_container(scale) + return + {n=G.UIT.R, config={align = "cm", minh = 1, padding = 0.1}, nodes={ + -- Chips container + SMODS.GUI.chips_container(scale), + -- Operator + SMODS.GUI.operator(scale), + -- Mult container + SMODS.GUI.mult_container(scale) + }} +end + +function SMODS.GUI.chips_container(scale) + return + {n=G.UIT.C, config={align = 'cm', id = 'hand_chips_container'}, nodes = { + SMODS.GUI.score_container({ + type = 'chips', + text = 'chip_text', + align = 'cr', + }) + }} +end + +function SMODS.GUI.operator(scale) + return + {n=G.UIT.C, config={align = "cm", id = 'hand_operator_container'}, nodes={ + {n=G.UIT.T, config={text = "X", lang = G.LANGUAGES['en-us'], scale = scale*2, colour = G.C.UI_MULT, shadow = true}}, + }} +end + +function SMODS.GUI.mult_container(scale) + return + {n=G.UIT.C, config={align = 'cm', id = 'hand_mult_container'}, nodes = { + SMODS.GUI.score_container({ + type = 'mult' + }) + }} +end + +function SMODS.GUI.score_container(args) + local scale = args.scale or 0.4 + local type = args.type or 'mult' + local colour = args.colour or SMODS.Scoring_Parameters[type].colour + local align = args.align or 'cl' + local func = args.func or 'hand_type_UI_set' + local text = args.text or type..'_text' + local w = args.w or 2 + local h = args.h or 1 + return + {n=G.UIT.R, config={align = align, minw = w, minh = h, r = 0.1, colour = colour, id = 'hand_'..type..'_area', emboss = 0.05}, nodes={ + {n=G.UIT.O, config={func = 'flame_handler', no_role = true, id = 'flame_'..type, object = Moveable(0,0,0,0), w = 0, h = 0, _w = w * 1.25, _h = h * 2.5}}, + align == 'cl' and {n=G.UIT.B, config={w = 0.1, h = 0.1}} or nil, + {n=G.UIT.O, config={id = 'hand_'..type, func = func, text = text, type = type, scale = scale*2.3, object = DynaText({ + string = {{ref_table = G.GAME.current_round.current_hand, ref_value = text}}, + colours = {G.C.UI.TEXT_LIGHT}, font = G.LANGUAGES['en-us'].font, shadow = true, float = true, scale = scale*2.3 + })}}, + align ~= 'cl' and {n=G.UIT.B, config={w = 0.1, h = 0.1}} or nil, + }} +end + +-- Internal function to automatically update UI boxes for new scoring parameters +G.FUNCS.hand_type_UI_set = function(e) + local new_mult_text = number_format(G.GAME.current_round.current_hand[e.config.type] or SMODS.Scoring_Parameters[e.config.type].default_value) + if new_mult_text ~= G.GAME.current_round.current_hand[e.config.text] then + G.GAME.current_round.current_hand[e.config.text] = new_mult_text + e.config.object.scale = scale_number(G.GAME.current_round.current_hand[e.config.type], e.config.scale, 1000) + e.config.object:update_text() + if not G.TAROT_INTERRUPT_PULSE then G.FUNCS.text_super_juice(e, math.max(0,math.floor(math.log10(type(G.GAME.current_round.current_hand[e.config.type]) == 'number' and G.GAME.current_round.current_hand[e.config.type] or 1)))) end + end +end \ No newline at end of file diff --git a/Steamodded/src/utils.lua b/Steamodded/src/utils.lua index c7575ce..4e35224 100644 --- a/Steamodded/src/utils.lua +++ b/Steamodded/src/utils.lua @@ -67,7 +67,7 @@ function inspectFunction(func) end function SMODS._save_d_u(o) - assert(not o._discovered_unlocked_overwritten) + assert(not o._discovered_unlocked_overwritten, ("Internal: discovery/unlocked of object \"%s\" should not be overwritten at this stage."):format(o and o.key or "UNKNOWN")) o._d, o._u = o.discovered, o.unlocked o._saved_d_u = true end @@ -225,6 +225,7 @@ function SMODS.handle_loc_file(path, mod_id) end function SMODS.insert_pool(pool, center, replace) + assert(pool, ("Attempted to insert object \"%s\" into an empty pool."):format(center.key or "UNKNOWN")) if replace == nil then replace = center.taken_ownership end if replace then for k, v in ipairs(pool) do @@ -242,6 +243,7 @@ function SMODS.insert_pool(pool, center, replace) end function SMODS.remove_pool(pool, key) + assert(pool, ("Attempted to remove object \"%s\" from an empty pool."):format(key or "UNKNOWN")) local j for i, v in ipairs(pool) do if v.key == key then j = i end @@ -281,20 +283,20 @@ end -- Change a card's suit, rank, or both. -- Accepts keys for both objects instead of needing to build a card key yourself. -function SMODS.change_base(card, suit, rank) +function SMODS.change_base(card, suit, rank, manual_sprites) if not card then return nil, "SMODS.change_base called with no card" end local _suit = SMODS.Suits[suit or card.base.suit] local _rank = SMODS.Ranks[rank or card.base.value] if not _suit or not _rank then return nil, ('Tried to call SMODS.change_base with invalid arguments: suit="%s", rank="%s"'):format(suit, rank) end - card:set_base(G.P_CARDS[('%s_%s'):format(_suit.card_key, _rank.card_key)]) + card:set_base(G.P_CARDS[('%s_%s'):format(_suit.card_key, _rank.card_key)], nil, manual_sprites) return card end -- Modify a card's rank by the specified amount. -- Increase rank if amount is positive, decrease rank if negative. -function SMODS.modify_rank(card, amount) +function SMODS.modify_rank(card, amount, manual_sprites) local rank_key = card.base.value local rank_data = SMODS.Ranks[card.base.value] if amount > 0 then @@ -306,7 +308,7 @@ function SMODS.modify_rank(card, amount) rank_key = pseudorandom_element( rank_data.next, pseudoseed('strength'), - { in_pool = function(key) return SMODS.Ranks[key]:in_pool({ suit = card.base.suit}) end } + { in_pool = function(key) return SMODS.add_to_pool(SMODS.Ranks[key], { suit = card.base.suit }) end } ) else local i = (behavior.fixed and rank_data.next[behavior.fixed]) and behavior.fixed or 1 @@ -323,7 +325,7 @@ function SMODS.modify_rank(card, amount) rank_key = pseudorandom_element( rank_data.prev, pseudoseed('weakness'), - { in_pool = function(key) return SMODS.Ranks[key]:in_pool({ suit = card.base.suit}) end } + { in_pool = function(key) return SMODS.add_to_pool(SMODS.Ranks[key], { suit = card.base.suit }) end } ) else local i = (behavior.fixed and rank_data.prev[behavior.fixed]) and behavior.fixed or 1 @@ -333,7 +335,7 @@ function SMODS.modify_rank(card, amount) end end - return SMODS.change_base(card, nil, rank_key) + return SMODS.change_base(card, nil, rank_key, manual_sprites) end -- Return an array of all (non-debuffed) jokers or consumables with key `key`. @@ -362,25 +364,37 @@ function SMODS.create_card(t) if not t.area and not t.key and t.set and SMODS.ConsumableTypes[t.set] then t.area = G.consumeables end + if not t.key and t.set == 'Playing Card' or t.set == 'Base' or t.set == 'Enhanced' or (not t.set and (t.front or t.rank or t.suit)) then + t.set = t.set == 'Playing Card' and (t.enhancement and 'Base' or (pseudorandom('front' .. (t.key_append or '') .. G.GAME.round_resets.ante) > (t.enhanced_poll or 0.6) and 'Enhanced' or 'Base')) or t.set or 'Base' + t.area = t.area or G.hand + if not t.front and (t.suit or t.rank) then + t.suit = t.suit and (SMODS.Suits["".. t.suit] or {}).card_key or t.suit or + pseudorandom_element(SMODS.Suits, pseudoseed('front' .. (t.key_append or '') .. G.GAME.round_resets.ante)).card_key + t.rank = t.rank and (SMODS.Ranks["".. t.rank] or {}).card_key or t.rank or + pseudorandom_element(SMODS.Ranks, pseudoseed('front' .. (t.key_append or '') .. G.GAME.round_resets.ante)).card_key + end + t.front = t.front or (t.suit and t.rank and (t.suit .. "_" .. t.rank)) or nil + end SMODS.bypass_create_card_edition = t.no_edition or t.edition SMODS.bypass_create_card_discover = t.discover SMODS.bypass_create_card_discovery_center = t.bypass_discovery_center + SMODS.set_create_card_front = G.P_CARDS[t.front] + SMODS.create_card_allow_duplicates = t.allow_duplicates local _card = create_card(t.set, t.area, t.legendary, t.rarity, t.skip_materialize, t.soulable, t.key, t.key_append) SMODS.bypass_create_card_edition = nil SMODS.bypass_create_card_discover = nil SMODS.bypass_create_card_discovery_center = nil + SMODS.set_create_card_front = nil + SMODS.create_card_allow_duplicates = nil -- Should this be restricted to only cards able to handle these -- or should that be left to the person calling SMODS.create_card to use it correctly? if t.edition then _card:set_edition(t.edition) end if t.enhancement then _card:set_ability(G.P_CENTERS[t.enhancement]) end - if t.seal then _card:set_seal(t.seal) end + if t.seal then _card:set_seal(t.seal, nil, true) end if t.stickers then for i, v in ipairs(t.stickers) do - local s = SMODS.Stickers[v] - if not s or type(s.should_apply) ~= 'function' or s:should_apply(_card, t.area, true) then - SMODS.Stickers[v]:apply(_card, true) - end + _card:add_sticker(v, t.force_stickers) end end @@ -389,6 +403,11 @@ end function SMODS.add_card(t) local card = SMODS.create_card(t) + if t.set == "Base" or t.set == "Enhanced" then + G.playing_card = (G.playing_card and G.playing_card + 1) or 1 + card.playing_card = G.playing_card + table.insert(G.playing_cards, card) + end card:add_to_deck() local area = t.area or G.jokers area:emplace(card) @@ -428,7 +447,7 @@ function SMODS.restart_game() if love.system.getOS() ~= 'OS X' then love.thread.newThread("os.execute(...)\n"):start('"' .. arg[-2] .. '" ' .. table.concat(arg, " ")) else - os.execute('sh "/Users/$USER/Library/Application Support/Steam/steamapps/common/Balatro/run_lovely.sh" &') + os.execute('sh "/Users/$USER/Library/Application Support/Steam/steamapps/common/Balatro/run_lovely_macos.sh" &') end love.event.quit() @@ -442,7 +461,7 @@ function SMODS.create_mod_badges(obj, badges) badges.mod_set[obj.mod.id] = true if obj.dependencies then for _, v in ipairs(obj.dependencies) do - local m = assert(SMODS.find_mod(v)[1]) + local m = assert(SMODS.find_mod(v)[1], ("Could not find mod \"%s\"."):format(v)) if not badges.mod_set[m.id] then table.insert(mods, m) badges.mod_set[m.id] = true @@ -450,7 +469,7 @@ function SMODS.create_mod_badges(obj, badges) end end for i, mod in ipairs(mods) do - local mod_name = string.sub(mod.display_name, 1, 20) + local mod_name = mod.display_name local size = 0.9 local font = G.LANG.font local max_text_width = 2 - 2*0.05 - 4*0.03*size - 2*0.03 @@ -460,13 +479,13 @@ function SMODS.create_mod_badges(obj, badges) 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 + local scale_fac = 1 + -- calced_text_width > max_text_width and max_text_width/calced_text_width + -- or 1 badges[#badges + 1] = {n=G.UIT.R, config={align = "cm"}, nodes={ {n=G.UIT.R, config={align = "cm", colour = mod.badge_colour or G.C.GREEN, r = 0.1, minw = 2, minh = 0.36, emboss = 0.05, padding = 0.03*size}, nodes={ {n=G.UIT.B, config={h=0.1,w=0.03}}, - {n=G.UIT.O, config={object = DynaText({string = mod_name or 'ERROR', colours = {mod.badge_text_colour or G.C.WHITE},float = true, shadow = true, offset_y = -0.05, silent = true, spacing = 1*scale_fac, scale = 0.33*size*scale_fac})}}, + {n=G.UIT.O, config={object = DynaText({string = mod_name or 'ERROR', colours = {mod.badge_text_colour or G.C.WHITE},float = true, shadow = true, offset_y = -0.05, silent = true, spacing = 1*scale_fac, scale = 0.33*size*scale_fac, marquee = calced_text_width > max_text_width and not mod.no_marquee, maxw = max_text_width})}}, {n=G.UIT.B, config={h=0.1,w=0.03}}, }} }} @@ -555,6 +574,15 @@ function serialize_string(s) return string.format("%q", s) end +function SMODS.shallow_copy(t) + local copy = {} + for k, v in next, t, nil do + copy[k] = v + end + setmetatable(copy, getmetatable(t)) + return copy +end + -- Starting with `t`, insert any key-value pairs from `defaults` that don't already -- exist in `t` into `t`. Modifies `t`. -- Returns `t`, the result of the merge. @@ -645,7 +673,7 @@ function SMODS.merge_lists(...) local ret = {} local seen = {} for _, li in ipairs(t) do - assert(type(li) == 'table') + assert(type(li) == 'table', ("\"%s\" is not a table."):format(tostring(li))) for _, v in ipairs(li) do if not seen[v] then ret[#ret+1] = v @@ -691,10 +719,10 @@ function SMODS.poll_seal(args) if v ~= "UNAVAILABLE" then local seal_option = {} if type(v) == 'string' then - assert(G.P_SEALS[v]) + assert(G.P_SEALS[v], ("Could not find seal \"%s\"."):format(v)) seal_option = { key = v, weight = G.P_SEALS[v].weight or 5 } -- default weight set to 5 to replicate base game weighting elseif type(v) == 'table' then - assert(G.P_SEALS[v.key]) + assert(G.P_SEALS[v.key], ("Could not find seal \"%s\"."):format(v.key)) seal_option = { key = v.key, weight = v.weight } end if seal_option.weight > 0 then @@ -840,10 +868,10 @@ function SMODS.poll_enhancement(args) if v ~= "UNAVAILABLE" then local enhance_option = {} if type(v) == 'string' then - assert(G.P_CENTERS[v]) + assert(G.P_CENTERS[v], ("Could not find enhancement \"%s\"."):format(v)) enhance_option = { key = v, weight = G.P_CENTERS[v].weight or 5 } -- default weight set to 5 to replicate base game weighting elseif type(v) == 'table' then - assert(G.P_CENTERS[v.key]) + assert(G.P_CENTERS[v.key], ("Could not find enhancement \"%s\"."):format(v.key)) enhance_option = { key = v.key, weight = v.weight } end if enhance_option.weight > 0 then @@ -907,8 +935,8 @@ function Card:calculate_sticker(context, key) end end -function Card:can_calculate(ignore_debuff) - local is_available = (not self.debuff or ignore_debuff) and not self.getting_sliced +function Card:can_calculate(ignore_debuff, ignore_sliced) + local is_available = (not self.debuff or ignore_debuff) and (not self.getting_sliced or ignore_sliced) -- TARGET : Add extra conditions here return is_available end @@ -992,14 +1020,23 @@ function SMODS.calculate_quantum_enhancements(card, effects, context) local old_ability = copy_table(card.ability) local old_center = card.config.center local old_center_key = card.config.center_key + -- Note: For now, just trigger extra enhancements in order. + -- Future work: combine enhancements during + -- playing card scoring (ex. Mult comes before Glass because +_mult + -- naturally comes before x_mult) + local extra_enhancements_list = {} for k, _ in pairs(extra_enhancements) do if G.P_CENTERS[k] then - card:set_ability(G.P_CENTERS[k], nil, 'quantum') - card.ability.extra_enhancement = k - local eval = eval_card(card, context) - table.insert(effects, eval) + table.insert(extra_enhancements_list, k) end end + table.sort(extra_enhancements_list, function(a, b) return G.P_CENTERS[a].order < G.P_CENTERS[b].order end) + for _, k in ipairs(extra_enhancements_list) do + card:set_ability(G.P_CENTERS[k], nil, 'quantum') + card.ability.extra_enhancement = k + local eval = eval_card(card, context) + table.insert(effects, eval) + end card.ability = old_ability card.config.center = old_center card.config.center_key = old_center_key @@ -1130,13 +1167,26 @@ G.FUNCS.update_collab_cards = function(key, suit, silent) local card_code = suit_data.card_key .. '_' .. rank.card_key cards_order[#cards_order+1] = card_code local card = Card(G.cdds_cards.T.x+G.cdds_cards.T.w/2, G.cdds_cards.T.y+G.cdds_cards.T.h/2, G.CARD_W*1.2, G.CARD_H*1.2, G.P_CARDS[card_code], G.P_CENTERS.c_base) - -- Instead of no ui it would be nice to pass info queue to this so that artist credits can be done? + card.no_ui = true G.cdds_cards:emplace(card) end end G.cdds_cards.config.card_limit = bufferCardLimitForSmallDS(cards, 2.5) + + for i, _card in ipairs(G.cdds_cards.cards) do + if deckskin.generate_ds_card_ui and type(deckskin.generate_ds_card_ui) == 'function' and deckskin.has_ds_card_ui and type(deckskin.has_ds_card_ui) == 'function' then + _card.no_ui = not deckskin.has_ds_card_ui(_card, deckskin, palette) + if not _card.no_ui then + _card.generate_ds_card_ui = deckskin.generate_ds_card_ui + _card.deckskin = deckskin + _card.palette = palette + end + else + _card.no_ui = true + end + end end G.FUNCS.update_suit_colours = function(suit, skin, palette_num) @@ -1152,52 +1202,40 @@ G.FUNCS.update_suit_colours = function(suit, skin, palette_num) G.C.SUITS[suit] = new_colour_proto end +SMODS.smart_level_up_hand = function(card, hand, instant, amount) + -- Cases: + -- Level ups in context.before on the played hand + -- -> direct level_up_hand(), keep displaying + -- Level ups in context.before on another hand AND any level up during scoring + -- -> restore the current chips/mult + -- Level ups outside anything -> always update to empty chips/mult + local vals_after_level + if SMODS.displaying_scoring and not (SMODS.displayed_hand == hand) then + vals_after_level = copy_table(G.GAME.current_round.current_hand) + local text,disp_text,_,_,_ = G.FUNCS.get_poker_hand_info(G.play.cards) + vals_after_level.handname = disp_text or '' + vals_after_level.level = (G.GAME.hands[text] or {}).level or '' + vals_after_level.chips = number_format(hand_chips) or 0 + vals_after_level.mult = number_format(mult) or 0 + end + if not (instant or SMODS.displayed_hand == hand) then + update_hand_text({sound = 'button', volume = 0.7, pitch = 0.8, delay = 0.3}, {handname=localize(hand, 'poker_hands'),chips = G.GAME.hands[hand].chips, mult = G.GAME.hands[hand].mult, level=G.GAME.hands[hand].level}) + end + level_up_hand(card, hand, instant, type(amount) == 'number' and amount or 1) + if not (instant or SMODS.displayed_hand == hand) then + update_hand_text({sound = 'button', volume = 0.7, pitch = 1.1, delay = 0}, vals_after_level or {mult = 0, chips = 0, handname = '', level = ''}) + end +end + -- This function handles the calculation of each effect returned to evaluate play. -- Can easily be hooked to add more calculation effects ala Talisman SMODS.calculate_individual_effect = function(effect, scored_card, key, amount, from_edition) - if (key == 'chips' or key == 'h_chips' or key == 'chip_mod') and amount then - if effect.card and effect.card ~= scored_card then juice_card(effect.card) end - hand_chips = mod_chips(hand_chips + amount) - update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) - if not effect.remove_default_message then - if from_edition then - card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = localize{type = 'variable', key = amount > 0 and 'a_chips' or 'a_chips_minus', vars = {amount}}, chip_mod = amount, colour = G.C.EDITION, edition = true}) - else - if key ~= 'chip_mod' then - if effect.chip_message then - card_eval_status_text(effect.message_card or effect.juice_card or scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.chip_message) - else - card_eval_status_text(effect.message_card or effect.juice_card or scored_card or effect.card or effect.focus, 'chips', amount, percent) - end - end - end - end - return true - end - - if (key == 'mult' or key == 'h_mult' or key == 'mult_mod') and amount then - if effect.card and effect.card ~= scored_card then juice_card(effect.card) end - mult = mod_mult(mult + amount) - update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) - if not effect.remove_default_message then - if from_edition then - card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = localize{type = 'variable', key = amount > 0 and 'a_mult' or 'a_mult_minus', vars = {amount}}, mult_mod = amount, colour = G.C.DARK_EDITION, edition = true}) - else - if key ~= 'mult_mod' then - if effect.mult_message then - card_eval_status_text(effect.message_card or effect.juice_card or scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.mult_message) - else - card_eval_status_text(effect.message_card or effect.juice_card or scored_card or effect.card or effect.focus, 'mult', amount, percent) - end - end - end - end - return true + if SMODS.Scoring_Parameter_Calculation[key] then + return SMODS.Scoring_Parameters[SMODS.Scoring_Parameter_Calculation[key]]:calc_effect(effect, scored_card, key, amount, from_edition) end if (key == 'p_dollars' or key == 'dollars' or key == 'h_dollars') and amount then if effect.card and effect.card ~= scored_card then juice_card(effect.card) end - ease_dollars(amount) if not effect.remove_default_message then if effect.dollar_message then card_eval_status_text(effect.message_card or effect.juice_card or scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.dollar_message) @@ -1205,51 +1243,13 @@ SMODS.calculate_individual_effect = function(effect, scored_card, key, amount, f card_eval_status_text(effect.message_card or effect.juice_card or scored_card or effect.card or effect.focus, 'dollars', amount, percent) end end + ease_dollars(amount) return true end - if (key == 'x_chips' or key == 'xchips' or key == 'Xchip_mod') and amount ~= 1 then - if effect.card and effect.card ~= scored_card then juice_card(effect.card) end - hand_chips = mod_chips(hand_chips * amount) - update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) - if not effect.remove_default_message then - if from_edition then - card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = localize{type='variable',key= amount > 0 and 'a_xchips' or 'a_xchips_minus',vars={amount}}, Xchips_mod = amount, colour = G.C.EDITION, edition = true}) - else - if key ~= 'Xchip_mod' then - if effect.xchip_message then - card_eval_status_text(effect.message_card or effect.juice_card or scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.xchip_message) - else - card_eval_status_text(effect.message_card or effect.juice_card or scored_card or effect.card or effect.focus, 'x_chips', amount, percent) - end - end - end - end - return true - end - - if (key == 'x_mult' or key == 'xmult' or key == 'Xmult' or key == 'x_mult_mod' or key == 'Xmult_mod') and amount ~= 1 then - if effect.card and effect.card ~= scored_card then juice_card(effect.card) end - mult = mod_mult(mult * amount) - update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) - if not effect.remove_default_message then - if from_edition then - card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = localize{type='variable',key= amount > 0 and 'a_xmult' or 'a_xmult_minus',vars={amount}}, Xmult_mod = amount, colour = G.C.EDITION, edition = true}) - else - if key ~= 'Xmult_mod' then - if effect.xmult_message then - card_eval_status_text(effect.message_card or effect.juice_card or scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.xmult_message) - else - card_eval_status_text(effect.message_card or effect.juice_card or scored_card or effect.card or effect.focus, 'x_mult', amount, percent) - end - end - end - end - return true - end - - if key == 'message' then + if key == 'message' and not SMODS.no_resolve then if effect.card and effect.card ~= scored_card then juice_card(effect.card) end + if effect.retrigger_juice then juice_card(effect.retrigger_juice) end card_eval_status_text(effect.message_card or effect.juice_card or scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect) return true end @@ -1265,13 +1265,66 @@ SMODS.calculate_individual_effect = function(effect, scored_card, key, amount, f mult = mod_mult(hand_chips) hand_chips = mod_chips(old_mult) update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + juice_card(scored_card) + return true + end + + if key == 'balance' then + if effect.card and effect.card ~= scored_card then juice_card(effect.card) end + local total = mult + hand_chips + mult = mod_mult(total/2) + hand_chips = mod_chips(total/2) + update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + G.E_MANAGER:add_event(Event({ + func = (function() + -- scored_card:juice_up() + play_sound('gong', 0.94, 0.3) + play_sound('gong', 0.94*1.5, 0.2) + play_sound('tarot1', 1.5) + ease_colour(G.C.UI_CHIPS, {0.8, 0.45, 0.85, 1}) + ease_colour(G.C.UI_MULT, {0.8, 0.45, 0.85, 1}) + G.E_MANAGER:add_event(Event({ + trigger = 'after', + blockable = false, + blocking = false, + delay = 0.8, + func = (function() + ease_colour(G.C.UI_CHIPS, G.C.BLUE, 0.8) + ease_colour(G.C.UI_MULT, G.C.RED, 0.8) + return true + end) + })) + G.E_MANAGER:add_event(Event({ + trigger = 'after', + blockable = false, + blocking = false, + no_delete = true, + delay = 1.3, + func = (function() + G.C.UI_CHIPS[1], G.C.UI_CHIPS[2], G.C.UI_CHIPS[3], G.C.UI_CHIPS[4] = G.C.BLUE[1], G.C.BLUE[2], G.C.BLUE[3], G.C.BLUE[4] + G.C.UI_MULT[1], G.C.UI_MULT[2], G.C.UI_MULT[3], G.C.UI_MULT[4] = G.C.RED[1], G.C.RED[2], G.C.RED[3], G.C.RED[4] + return true + end) + })) + return true + end) + })) + if not effect.remove_default_message then + if effect.balance_message then + card_eval_status_text(effect.message_card or effect.juice_card or scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.balance_message) + else + card_eval_status_text(effect.message_card or effect.juice_card or scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, {message = localize('k_balanced'), colour = {0.8, 0.45, 0.85, 1}}) + end + end + delay(0.6) + return true end if key == 'level_up' then if effect.card and effect.card ~= scored_card then juice_card(effect.card) end local hand_type = effect.level_up_hand or G.GAME.last_hand_played - level_up_hand(scored_card, hand_type, effect.instant, type(amount) == 'number' and amount or 1) + SMODS.smart_level_up_hand(scored_card, hand_type, effect.instant, amount) return true end @@ -1281,6 +1334,7 @@ SMODS.calculate_individual_effect = function(effect, scored_card, key, amount, f if key == 'saved' then SMODS.saved = amount + G.GAME.saved_text = amount return true end @@ -1288,40 +1342,77 @@ SMODS.calculate_individual_effect = function(effect, scored_card, key, amount, f return true end - if key == 'remove' or key == 'prevent_debuff' or key == 'add_to_hand' or key == 'remove_from_hand' or key == 'stay_flipped' or key == 'prevent_stay_flipped' then + if key == 'prevent_debuff' or key == 'add_to_hand' or key == 'remove_from_hand' or key == 'stay_flipped' or key == 'prevent_stay_flipped' or key == 'prevent_trigger' then return key end + if key == 'remove' or key == 'debuff_text' or key == 'cards_to_draw' or key == 'numerator' or key == 'denominator' or key == 'no_destroy' or + key == 'replace_scoring_name' or key == 'replace_display_name' or key == 'replace_poker_hands' or key == 'modify' then + return { [key] = amount } + end + if key == 'debuff' then return { [key] = amount, debuff_source = scored_card } end - if key == 'debuff_text' then - return { [key] = amount } - end end -- Used to calculate a table of effects generated in evaluate_play SMODS.trigger_effects = function(effects, card) local ret = {} - for i, effect_table in ipairs(effects) do - for key, effect in pairs(effect_table) do - if key ~= 'smods' then - if type(effect) == 'table' then - local calc = SMODS.calculate_effect(effect, effect.scored_card or card, key == 'edition') - for k,v in pairs(calc) do ret[k] = v end - end - end + for _, effect_table in ipairs(effects) do + -- note: these sections happen to be mutually exclusive: + -- Playing cards in scoring + for _, key in ipairs({'playing_card', 'enhancement', 'edition', 'seals'}) do + SMODS.calculate_effect_table_key(effect_table, key, card, ret) + end + for _, k in ipairs(SMODS.Sticker.obj_buffer) do + local v = SMODS.Stickers[k] + SMODS.calculate_effect_table_key(effect_table, v, card, ret) + end + -- Playing cards at end of round + SMODS.calculate_effect_table_key(effect_table, 'end_of_round', card, ret) + -- Jokers + for _, key in ipairs({'jokers', 'retriggers'}) do + SMODS.calculate_effect_table_key(effect_table, key, card, ret) + end + SMODS.calculate_effect_table_key(effect_table, 'individual', card, ret) + -- todo: might want to move these keys to a customizable list/lists + end + + if SMODS.post_prob and next(SMODS.post_prob) then + local prob_tables = SMODS.post_prob + SMODS.post_prob = {} + for i, v in ipairs(prob_tables) do + v.pseudorandom_result = true + SMODS.calculate_context(v) end end + return ret end +-- Calculate one key of an effect table returned from eval_card. +SMODS.calculate_effect_table_key = function(effect_table, key, card, ret) + local effect = effect_table[key] + if key ~= 'smods' and type(effect) == 'table' then + local calc = SMODS.calculate_effect(effect, effect.scored_card or card, key == 'edition') + for k, v in pairs(calc) do ret[k] = type(ret[k]) == 'number' and ret[k] + v or v end + end +end + SMODS.calculate_effect = function(effect, scored_card, from_edition, pre_jokers) local ret = {} for _, key in ipairs(SMODS.calculation_keys) do if effect[key] then - if effect.juice_card then G.E_MANAGER:add_event(Event({trigger = 'immediate', func = function () effect.juice_card:juice_up(0.1); scored_card:juice_up(0.1); return true end})) end + if effect.juice_card and not SMODS.no_resolve then + G.E_MANAGER:add_event(Event({trigger = 'immediate', func = function () + effect.juice_card:juice_up(0.1) + if (not effect.message_card) or (effect.message_card and effect.message_card ~= scored_card) then + scored_card:juice_up(0.1) + end + return true end})) + end local calc = SMODS.calculate_individual_effect(effect, scored_card, key, effect[key], from_edition) if calc == true then ret.calculated = true end if type(calc) == 'string' then @@ -1329,25 +1420,45 @@ SMODS.calculate_effect = function(effect, scored_card, from_edition, pre_jokers) elseif type(calc) == 'table' then for k,v in pairs(calc) do ret[k] = v end end - percent = (percent or 0) + (percent_delta or 0.08) + if not SMODS.silent_calculation[key] then + percent = (percent or 0) + (percent_delta or 0.08) + end end end return ret end -SMODS.calculation_keys = { +SMODS.calculation_keys = {} +SMODS.scoring_parameter_keys = { 'chips', 'h_chips', 'chip_mod', 'mult', 'h_mult', 'mult_mod', 'x_chips', 'xchips', 'Xchip_mod', 'x_mult', 'Xmult', 'xmult', 'x_mult_mod', 'Xmult_mod', +} +SMODS.other_calculation_keys = { 'p_dollars', 'dollars', 'h_dollars', - 'swap', + 'swap', 'balance', 'saved', 'effect', 'remove', 'debuff', 'prevent_debuff', 'debuff_text', 'add_to_hand', 'remove_from_hand', 'stay_flipped', 'prevent_stay_flipped', + 'cards_to_draw', 'message', 'level_up', 'func', 'extra', + 'numerator', 'denominator', + 'modify', + 'no_destroy', 'prevent_trigger', + 'replace_scoring_name', 'replace_display_name', 'replace_poker_hands' +} +SMODS.silent_calculation = { + saved = true, effect = true, remove = true, + debuff = true, prevent_debuff = true, debuff_text = true, + add_to_hand = true, remove_from_hand = true, + stay_flipped = true, prevent_stay_flipped = true, + cards_to_draw = true, + func = true, extra = true, + numerator = true, denominator = true, + no_destroy = true } SMODS.insert_repetitions = function(ret, eval, effect_card, _type) @@ -1363,6 +1474,7 @@ SMODS.insert_repetitions = function(ret, eval, effect_card, _type) if _type == 'joker_retrigger' then effect.retrigger_card = effect_card effect.message_card = effect.message_card or effect_card + effect.retrigger_flag = true elseif _type == 'individual_retrigger' then effect.retrigger_card = effect_card.object effect.message_card = effect.message_card or effect_card.scored_card @@ -1371,7 +1483,7 @@ SMODS.insert_repetitions = function(ret, eval, effect_card, _type) end effect.message = effect.message or (not effect.remove_default_message and localize('k_again_ex')) for h=1, effect.repetitions do - table.insert(ret, { key = effect}) + table.insert(ret, _type == "joker_retrigger" and effect or { retriggers = effect}) end eval = eval.extra until not eval @@ -1398,10 +1510,33 @@ SMODS.calculate_repetitions = function(card, context, reps) for _, _card in ipairs(area.cards) do --calculate the joker effects local eval, post = eval_card(_card, context) - if next(post) then SMODS.trigger_effects({post}, card) end + local first = true for key, value in pairs(eval) do if key ~= 'retriggers' then + local curr_size = #reps SMODS.insert_repetitions(reps, value, _card) + -- After each inserted repetition we insert the post effects + local new_size = #reps + for i = curr_size + 1, new_size do + if not first then + post = {} + if not context.post_trigger and SMODS.optional_features.post_trigger then + SMODS.calculate_context({blueprint_card = context.blueprint_card, post_trigger = true, other_card = _card, other_context = context, other_ret = eval}, post) + end + end + first = nil + if next(post) then + reps[#reps - new_size + i].retriggers.retrigger_flag = true + else break end + -- index from behind since that doesn't change + for idx, eff in ipairs(post) do + if next(eff) then + select(2, next(eff)).retrigger_flag = true + table.insert(reps, #reps + 1 - new_size + i, eff) + end + end + select(2, next(reps[#reps - new_size + i])).retrigger_flag = false + end end end if eval.retriggers then @@ -1409,10 +1544,13 @@ SMODS.calculate_repetitions = function(card, context, reps) for rt = 1, #eval.retriggers do context.retrigger_joker = eval.retriggers[rt].retrigger_card local rt_eval, rt_post = eval_card(_card, context) - if next(rt_post) then SMODS.trigger_effects({rt_post}, card) end - for key, value in pairs(rt_eval) do - if key ~= 'retriggers' then - SMODS.insert_repetitions(reps, value, _card) + if next(rt_eval) then + SMODS.insert_repetitions(reps, eval.retriggers[rt], eval.retriggers[rt].message_card or _card) + if next(rt_post) then SMODS.trigger_effects({rt_post}, card) end + for key, value in pairs(rt_eval) do + if key ~= 'retriggers' then + SMODS.insert_repetitions(reps, value, _card) + end end end end @@ -1433,10 +1571,12 @@ SMODS.calculate_repetitions = function(card, context, reps) for rt = 1, #eval.retriggers do context.retrigger_joker = eval.retriggers[rt].retrigger_card local rt_eval, rt_post = SMODS.eval_individual(area, context) - if next(rt_post) then SMODS.trigger_effects({rt_post}, card) end - for key, value in pairs(rt_eval) do - if key ~= 'retriggers' then - SMODS.insert_repetitions(reps, value, area.scored_card) + if next(rt_eval) then + if next(rt_post) then SMODS.trigger_effects({rt_post}, card) end + for key, value in pairs(rt_eval) do + if key ~= 'retriggers' then + SMODS.insert_repetitions(reps, value, area.scored_card) + end end end end @@ -1452,19 +1592,26 @@ SMODS.calculate_retriggers = function(card, context, _ret) for _, area in ipairs(SMODS.get_card_areas('jokers')) do for _, _card in ipairs(area.cards) do local eval, post = eval_card(_card, {retrigger_joker_check = true, other_card = card, other_context = context, other_ret = _ret}) - if next(post) then SMODS.trigger_effects({post}, _card) end - for key, value in pairs(eval) do - SMODS.insert_repetitions(retriggers, value, _card, 'joker_retrigger') + if next(eval) then + if next(post) then SMODS.trigger_effects({post}, _card) end + for key, value in pairs(eval) do + if not value.no_retrigger_juice then + value.retrigger_juice = card + end + SMODS.insert_repetitions(retriggers, value, _card, 'joker_retrigger') + end end end end for _, area in ipairs(SMODS.get_card_areas('individual')) do local eval, post = SMODS.eval_individual(area, {retrigger_joker_check = true, other_card = card, other_context = context, other_ret = _ret}) - if next(post) then SMODS.trigger_effects({post}, _card) end - for key, value in pairs(eval) do - if value.repetitions then - SMODS.insert_repetitions(retriggers, value, area, 'individual_retrigger') + if next(eval) then + if next(post) then SMODS.trigger_effects({post}, _card) end + for key, value in pairs(eval) do + if value.repetitions then + SMODS.insert_repetitions(retriggers, value, area, 'individual_retrigger') + end end end end @@ -1495,7 +1642,7 @@ function SMODS.calculate_card_areas(_type, context, return_table, args) local eval, post = eval_card(_card, context) if args and args.main_scoring and eval.jokers then eval.jokers.juice_card = eval.jokers.juice_card or eval.jokers.card or _card - eval.jokers.message_card = eval.jokers.message_card or eval.jokers.card or context.other_card + eval.jokers.message_card = eval.jokers.message_card or context.other_card end local effects = {eval} @@ -1514,11 +1661,15 @@ function SMODS.calculate_card_areas(_type, context, return_table, args) local rt_eval, rt_post = eval_card(_card, context) if args and args.main_scoring and rt_eval.jokers then rt_eval.jokers.juice_card = rt_eval.jokers.juice_card or rt_eval.jokers.card or _card - rt_eval.jokers.message_card = rt_eval.jokers.message_card or rt_eval.jokers.card or context.other_card + rt_eval.jokers.message_card = rt_eval.jokers.message_card or context.other_card + end + if next(rt_eval) then + if next(rt_eval) then + table.insert(effects, {retriggers = eval.retriggers[rt]}) + table.insert(effects, rt_eval) + for _,v in ipairs(rt_post) do effects[#effects+1] = v end + end end - table.insert(effects, {eval.retriggers[rt]}) - table.insert(effects, rt_eval) - for _,v in ipairs(rt_post) do effects[#effects+1] = v end end context.retrigger_joker = nil end @@ -1530,6 +1681,9 @@ function SMODS.calculate_card_areas(_type, context, return_table, args) else local f = SMODS.trigger_effects(effects, _card) for k,v in pairs(f) do flags[k] = v end + if flags.numerator then context.numerator = flags.numerator end + if flags.denominator then context.denominator = flags.denominator end + if flags.cards_to_draw then context.amount = flags.cards_to_draw end end end end @@ -1541,7 +1695,22 @@ function SMODS.calculate_card_areas(_type, context, return_table, args) for _,v in ipairs(context.scoring_hand) do scoring_map[v] = true end end for _, area in ipairs(SMODS.get_card_areas('playing_cards')) do - if area == G.play and not context.scoring_hand then goto continue end + if area == G.play and not context.scoring_hand then + -- If context is for probability, eval_card() anyway + -- This allows Seals, etc. to affect Joker probabilities during individual scoring: + -- For example; A seal can double the probability of Blood Stone hitting for the playing card it is applied to. + if context.mod_probability or context.fix_probability then + for _, card in ipairs(area.cards) do + local effects = {eval_card(card, context)} + local f = SMODS.trigger_effects(effects, card) + for k,v in pairs(f) do flags[k] = v end + if flags.numerator then context.numerator = flags.numerator end + if flags.denominator then context.denominator = flags.denominator end + if flags.cards_to_draw then context.amount = flags.cards_to_draw end + end + end + goto continue + end if not args or not args.has_area then context.cardarea = area end for _, card in ipairs(area.cards) do if not args or not args.has_area then @@ -1560,8 +1729,11 @@ function SMODS.calculate_card_areas(_type, context, return_table, args) else local effects = {eval_card(card, context)} SMODS.calculate_quantum_enhancements(card, effects, context) - local f = SMODS.trigger_effects(effects, _card) + local f = SMODS.trigger_effects(effects, card) for k,v in pairs(f) do flags[k] = v end + if flags.numerator then context.numerator = flags.numerator end + if flags.denominator then context.denominator = flags.denominator end + if flags.cards_to_draw then context.amount = flags.cards_to_draw end end end ::continue:: @@ -1582,9 +1754,13 @@ function SMODS.calculate_card_areas(_type, context, return_table, args) for rt = 1, #effects[1].retriggers do context.retrigger_joker = effects[1].retriggers[rt].retrigger_card local rt_eval, rt_post = SMODS.eval_individual(area, context) - table.insert(effects, {effects[1].retriggers[rt]}) - table.insert(effects, rt_eval) - for _,v in ipairs(rt_post) do effects[#effects+1] = v end + if next(rt_eval) then + if next(rt_eval) then + table.insert(effects, {retriggers = effects[1].retriggers[rt]}) + table.insert(effects, rt_eval) + for _,v in ipairs(rt_post) do effects[#effects+1] = v end + end + end end context.retrigger_joker = nil end @@ -1593,26 +1769,76 @@ function SMODS.calculate_card_areas(_type, context, return_table, args) else local f = SMODS.trigger_effects(effects, area.scored_card) for k,v in pairs(f) do flags[k] = v end + if flags.numerator then context.numerator = flags.numerator end + if flags.denominator then context.denominator = flags.denominator end end end end return flags end +-- The context stack list, structured like so; +-- SMODS.context_stack = {1: {context = [unique context 1], count = [number of times it was added consecutively]}, ...} +-- (Contexts may repeat non-consecutively, though I don't think they ever should..) +-- Allows some advanced effects, like: +-- Individual playing cards modifying probabilities checked during individual scoring, only when they're the context.other_card +-- (-> By checking the context in the stack PRIOR to the mod_probability context for the .individual / .other_card flags) +SMODS.context_stack = {} + +function SMODS.push_to_context_stack(context, func) + if not context or type(context) ~= "table" then + sendWarnMessage(('Called SMODS.push_to_context_stack with invalid context \'%s\', in function \'%s\''):format(context, func), 'Util') + end + local len = #SMODS.context_stack + if len <= 0 or SMODS.context_stack[len].context ~= context then + SMODS.context_stack[len+1] = {context = context, count = 1} + else + SMODS.context_stack[len].count = SMODS.context_stack[len].count + 1 + end +end + +function SMODS.pop_from_context_stack(context, func) + local len = #SMODS.context_stack + if len <= 0 or SMODS.context_stack[len].context ~= context then + sendWarnMessage(('Called SMODS.pop_from_context_stack with invalid context \'%s\', in function \'%s\''):format(context, func), 'Util') + else + SMODS.context_stack[len].count = SMODS.context_stack[len].count - 1 + if SMODS.context_stack[len].count <= 0 then + table.remove(SMODS.context_stack, len) + end + end +end + +function SMODS.get_previous_context() + return (SMODS.context_stack[#SMODS.context_stack-1] or {}).context +end + -- Used to calculate contexts across G.jokers, scoring_hand (if present), G.play and G.GAME.selected_back -- Hook this function to add different areas to MOST calculations -function SMODS.calculate_context(context, return_table) +function SMODS.calculate_context(context, return_table, no_resolve) + if G.STAGE ~= G.STAGES.RUN then return end + + SMODS.push_to_context_stack(context, "utils.lua : SMODS.calculate_context") + local has_area = context.cardarea and true or nil + if no_resolve then SMODS.no_resolve = true end local flags = {} context.main_eval = true flags[#flags+1] = SMODS.calculate_card_areas('jokers', context, return_table, { joker_area = true, has_area = has_area }) context.main_eval = nil flags[#flags+1] = SMODS.calculate_card_areas('playing_cards', context, return_table, { has_area = has_area }) + context.main_eval = true flags[#flags+1] = SMODS.calculate_card_areas('individual', context, return_table) + context.main_eval = nil + + if SMODS.no_resolve then SMODS.no_resolve = nil end + + SMODS.pop_from_context_stack(context, "utils.lua : SMODS.calculate_context") + if not return_table then local ret = {} - for _,f in ipairs(flags) do + for i,f in ipairs(flags) do for k,v in pairs(f) do ret[k] = v end end return ret @@ -1620,6 +1846,7 @@ function SMODS.calculate_context(context, return_table) end function SMODS.in_scoring(card, scoring_hand) + if SMODS.always_scores(card) then return true end for _, _card in pairs(scoring_hand) do if card == _card then return true end end @@ -1631,6 +1858,9 @@ function SMODS.score_card(card, context) while j <= #reps do if reps[j] ~= 1 then local _, eff = next(reps[j]) + while eff.retrigger_flag do + SMODS.calculate_effect(eff, eff.card); j = j+1; _, eff = next(reps[j]) + end SMODS.calculate_effect(eff, eff.card) percent = percent + percent_delta end @@ -1728,6 +1958,7 @@ function SMODS.calculate_end_of_round_effects(context) context.repetition = nil context.card_effects = nil + context.other_card = nil j = j + (flags.calculated and 1 or #reps) -- TARGET: effects after end of round evaluation @@ -1740,7 +1971,7 @@ function SMODS.calculate_destroying_cards(context, cards_destroyed, scoring_hand local destroyed = nil --un-highlight all cards local in_scoring = scoring_hand and SMODS.in_scoring(card, context.scoring_hand) - if scoring_hand and in_scoring then + if scoring_hand and in_scoring and not card.destroyed then -- Use index of card in scoring hand to determine pitch local m = 1 for j, _card in pairs(scoring_hand) do @@ -1766,6 +1997,7 @@ function SMODS.calculate_destroying_cards(context, cards_destroyed, scoring_hand -- TARGET: card destroyed if destroyed then + card.getting_sliced = true if SMODS.shatters(card) then card.shattered = true else @@ -1777,21 +2009,43 @@ function SMODS.calculate_destroying_cards(context, cards_destroyed, scoring_hand end function SMODS.blueprint_effect(copier, copied_card, context) - if copied_card == copier then return end + if not copied_card or copied_card == copier or copied_card.debuff or context.no_blueprint then return end + if (context.blueprint or 0) > #G.jokers.cards then return end + local old_context_blueprint = context.blueprint context.blueprint = (context.blueprint and (context.blueprint + 1)) or 1 + local old_context_blueprint_card = context.blueprint_card context.blueprint_card = context.blueprint_card or copier - if context.blueprint > #G.jokers.cards + 1 then return end + local eff_card = context.blueprint_card local other_joker_ret = copied_card:calculate_joker(context) - context.blueprint = nil - local eff_card = context.blueprint_card or copier - context.blueprint_card = nil + context.blueprint = old_context_blueprint + context.blueprint_card = old_context_blueprint_card if other_joker_ret then - other_joker_ret.card = copier + other_joker_ret.card = eff_card other_joker_ret.colour = G.C.BLUE return other_joker_ret end end +function SMODS.get_mods_scoring_targets() + local ret = {} + for _, mod in ipairs(SMODS.mod_list) do + if mod.can_load and mod.calculate and type(mod.calculate) == "function" then + table.insert(ret, mod) + end + end + return ret +end + +function SMODS.get_stake_scoring_targets() + local ret = {} + for _, stake in ipairs(G.GAME.applied_stakes or {}) do + if G.P_CENTER_POOLS.Stake[stake].calculate and type(G.P_CENTER_POOLS.Stake[stake].calculate) == "function" then + table.insert(ret, G.P_CENTER_POOLS.Stake[stake]) + end + end + return ret +end + function SMODS.get_card_areas(_type, _context) if _type == 'playing_cards' then local t = {} @@ -1811,7 +2065,14 @@ function SMODS.get_card_areas(_type, _context) local t = { { object = G.GAME.selected_back, scored_card = G.deck.cards[1] or G.deck }, } - if G.GAME.blind then t[#t+1] = { object = G.GAME.blind, scored_card = G.GAME.blind.children.animatedSprite } end + if G.GAME.blind then t[#t + 1] = { object = G.GAME.blind, scored_card = G.GAME.blind.children.animatedSprite } end + if G.GAME.challenge then t[#t + 1] = { object = SMODS.Challenges[G.GAME.challenge], scored_card = G.deck.cards[1] or G.deck } end + for _, stake in ipairs(SMODS.get_stake_scoring_targets()) do + t[#t + 1] = { object = stake, scored_card = G.deck.cards[1] or G.deck } + end + for _, mod in ipairs(SMODS.get_mods_scoring_targets()) do + t[#t + 1] = { object = mod, scored_card = G.deck.cards[1] or G.deck } + end -- TARGET: add your own individual scoring targets return t end @@ -1829,6 +2090,7 @@ function Blind:calculate(context) end function SMODS.eval_individual(individual, context) + SMODS.push_to_context_stack(context, "utils.lua : SMODS.eval_individual") local ret = {} local post_trig = {} @@ -1839,7 +2101,6 @@ function SMODS.eval_individual(individual, context) if (eff and not eff.no_retrigger) or triggered then --if type(eff) == 'table' then eff.juice_card = eff.juice_card or individual.scored_card end ret.individual = eff - if not (context.retrigger_joker_check or context.retrigger_joker) then local retriggers = SMODS.calculate_retriggers(individual.object, context, ret) if next(retriggers) then @@ -1850,6 +2111,7 @@ function SMODS.eval_individual(individual, context) SMODS.calculate_context({blueprint_card = context.blueprint_card, post_trigger = true, other_card = individual.object, other_context = context, other_ret = ret}, post_trig) end end + SMODS.pop_from_context_stack(context, "utils.lua : SMODS.eval_individual") return ret, post_trig end @@ -1941,7 +2203,7 @@ local function insert(t, res) if type(v) == 'table' and type(t[k]) == 'table' then insert(t[k], v) else - t[k] = v + t[k] = true end end end @@ -1962,7 +2224,7 @@ end G.FUNCS.can_select_from_booster = function(e) local card = e.config.ref_table local area = booster_obj and card:selectable_from_pack(booster_obj) - local edition_card_limit = card.edition and card.edition.card_limit or 0 + local edition_card_limit = card.ability.card_limit if area and #G[area].cards < G[area].config.card_limit + edition_card_limit then e.config.colour = G.C.GREEN e.config.button = 'use_card' @@ -2012,11 +2274,13 @@ function SMODS.get_next_vouchers(vouchers) return vouchers end -function SMODS.add_voucher_to_shop(key) +function SMODS.add_voucher_to_shop(key, dont_save) if key then assert(G.P_CENTERS[key], "Invalid voucher key: "..key) else key = get_next_voucher_key() - G.GAME.current_round.voucher.spawn[key] = true - G.GAME.current_round.voucher[#G.GAME.current_round.voucher + 1] = key + if not dont_save then + G.GAME.current_round.voucher.spawn[key] = true + G.GAME.current_round.voucher[#G.GAME.current_round.voucher + 1] = key + end end local card = Card(G.shop_vouchers.T.x + G.shop_vouchers.T.w/2, G.shop_vouchers.T.y, G.CARD_W, G.CARD_H, G.P_CARDS.empty, G.P_CENTERS[key],{bypass_discovery_center = true, bypass_discovery_ui = true}) @@ -2030,7 +2294,7 @@ end function SMODS.change_voucher_limit(mod) G.GAME.modifiers.extra_vouchers = (G.GAME.modifiers.extra_vouchers or 0) + mod - if mod > 0 and (G.STATE == G.STATES.SHOP or G.TAROT_INTERRUPT == G.STATES.SHOP) then + if mod > 0 and G.shop then for i=1, mod do SMODS.add_voucher_to_shop() end @@ -2050,7 +2314,7 @@ end function SMODS.change_booster_limit(mod) G.GAME.modifiers.extra_boosters = (G.GAME.modifiers.extra_boosters or 0) + mod - if mod > 0 and (G.STATE == G.STATES.SHOP or G.TAROT_INTERRUPT == G.STATES.SHOP) then + if mod > 0 and G.shop then for i = 1, mod do SMODS.add_booster_to_shop() end @@ -2073,12 +2337,15 @@ end function SMODS.multiplicative_stacking(base, perma) base = (base ~= 0 and base or 1) - perma = (perma ~= 0 and perma + 1 or 1) - local ret = base * perma + local ret = base * (perma + 1) return (ret == 1 and 0) or (ret > 0 and ret) or 0 end function SMODS.smeared_check(card, suit) + if not next(find_joker('Smeared Joker')) then + return false + end + if ((card.base.suit == 'Hearts' or card.base.suit == 'Diamonds') and (suit == 'Hearts' or suit == 'Diamonds')) then return true elseif (card.base.suit == 'Spades' or card.base.suit == 'Clubs') and (suit == 'Spades' or suit == 'Clubs') then @@ -2112,17 +2379,665 @@ function SMODS.seeing_double_check(hand, suit) for k, v in pairs(suit_tally) do if hand[i]:is_suit(k) then suit_tally[k] = suit_tally[k] + 1 end end - elseif SMODS.has_any_suit(hand[i]) then - if hand[i]:is_suit('Clubs') and suit_tally["Clubs"] == 0 then suit_tally["Clubs"] = suit_tally["Clubs"] + 1 - elseif hand[i]:is_suit('Diamonds') and suit_tally["Diamonds"] == 0 then suit_tally["Diamonds"] = suit_tally["Diamonds"] + 1 - elseif hand[i]:is_suit('Spades') and suit_tally["Spades"] == 0 then suit_tally["Spades"] = suit_tally["Spades"] + 1 - elseif hand[i]:is_suit('Hearts') and suit_tally["Hearts"] == 0 then suit_tally["Hearts"] = suit_tally["Hearts"] + 1 end + end + end + for i = 1, #hand do + if SMODS.has_any_suit(hand[i]) then + if hand[i]:is_suit(suit) and suit_tally[suit] == 0 then suit_tally[suit] = suit_tally[suit] + 1 end for k, v in pairs(suit_tally) do - if k ~= "Clubs" and k ~= "Diamonds" and k ~= "Hearts" and k ~= "Spades" then - if hand[i]:is_suit(k) and suit_tally[k] == 0 then suit_tally[k] = suit_tally[k] + 1 end - end + if hand[i]:is_suit(k) and suit_tally[k] == 0 then suit_tally[k] = suit_tally[k] + 1 end end end end if saw_double(suit_tally, suit) then return true else return false end end + +function SMODS.localize_box(lines, args) + local final_line = {} + for _, part in ipairs(lines) do + local assembled_string = '' + for _, subpart in ipairs(part.strings) do + assembled_string = assembled_string..(type(subpart) == 'string' and subpart or format_ui_value(args.vars[tonumber(subpart[1])]) or 'ERROR') + end + local desc_scale = (SMODS.Fonts[part.control.f] or G.FONTS[tonumber(part.control.f)] or G.LANG.font).DESCSCALE + if G.F_MOBILE_UI then desc_scale = desc_scale*1.5 end + if part.control.E then + local _float, _silent, _pop_in, _bump, _spacing = nil, true, nil, nil, nil + if part.control.E == '1' then + _float = true; _silent = true; _pop_in = 0 + elseif part.control.E == '2' then + _bump = true; _spacing = 1 + end + final_line[#final_line+1] = {n=G.UIT.C, config={align = "m", colour = part.control.B and args.vars.colours[tonumber(part.control.B)] or part.control.X and loc_colour(part.control.X) or nil, r = 0.05, padding = 0.03, res = 0.15}, nodes={}} + final_line[#final_line].nodes[1] = {n=G.UIT.O, config={ + underline = part.control.u and loc_colour(part.control.u), + object = DynaText({string = {assembled_string}, colours = {part.control.V and args.vars.colours[tonumber(part.control.V)] or loc_colour(part.control.C or nil)}, + float = _float, + silent = _silent, + pop_in = _pop_in, + bump = _bump, + spacing = _spacing, + font = SMODS.Fonts[part.control.f] or (tonumber(part.control.f) and G.FONTS[tonumber(part.control.f)]), + scale = 0.32*(part.control.s and tonumber(part.control.s) or args.scale or 1)*desc_scale}) + } + } + elseif part.control.X or part.control.B then + final_line[#final_line+1] = {n=G.UIT.C, config={align = "m", colour = part.control.B and args.vars.colours[tonumber(part.control.B)] or loc_colour(part.control.X), r = 0.05, padding = 0.03, res = 0.15}, nodes={ + {n=G.UIT.T, config={ + text = assembled_string, + colour = part.control.V and args.vars.colours[tonumber(part.control.V)] or loc_colour(part.control.C or nil), + font = SMODS.Fonts[part.control.f] or (tonumber(part.control.f) and G.FONTS[tonumber(part.control.f)]), + underline = part.control.u and loc_colour(part.control.u), + scale = 0.32*(part.control.s and tonumber(part.control.s) or args.scale or 1)*desc_scale}}, + }} + else + final_line[#final_line+1] = {n=G.UIT.T, config={ + detailed_tooltip = part.control.T and (G.P_CENTERS[part.control.T] or G.P_TAGS[part.control.T]) or nil, + text = assembled_string, + shadow = args.shadow, + colour = part.control.V and args.vars.colours[tonumber(part.control.V)] or not part.control.C and args.text_colour or loc_colour(part.control.C or nil, args.default_col), + font = SMODS.Fonts[part.control.f] or (tonumber(part.control.f) and G.FONTS[tonumber(part.control.f)]), + underline = part.control.u and loc_colour(part.control.u), + scale = 0.32*(part.control.s and tonumber(part.control.s) or args.scale or 1)*desc_scale},} + end + end + return final_line +end + +function SMODS.get_multi_boxes(multi_box) + local multi_boxes = {} + if multi_box then + for i, box in ipairs(multi_box) do + if i > 1 then multi_boxes[#multi_boxes+1] = {n=G.UIT.R, config={minh = 0.07}} end + local _box = desc_from_rows(box) + multi_boxes[#multi_boxes+1] = _box + end + end + return multi_boxes +end + +function SMODS.info_queue_desc_from_rows(desc_nodes, empty, maxw) + local t = {} + for k, v in ipairs(desc_nodes) do + t[#t+1] = {n=G.UIT.R, config={align = "cm", maxw = maxw}, nodes=v} + end + return {n=G.UIT.R, config={align = "cm", colour = desc_nodes.background_colour or empty and G.C.CLEAR or G.C.UI.BACKGROUND_WHITE, r = 0.1, emboss = not empty and 0.05 or nil, filler = true, main_box_flag = desc_nodes.main_box_flag and true or nil}, nodes={ + {n=G.UIT.R, config={align = "cm"}, nodes=t} + }} +end + +function SMODS.destroy_cards(cards, bypass_eternal, immediate, skip_anim) + if not cards[1] then + cards = {cards} + end + local glass_shattered = {} + local playing_cards = {} + for _, card in ipairs(cards) do + if bypass_eternal or not SMODS.is_eternal(card, {destroy_cards = true}) then + card.getting_sliced = true + if SMODS.shatters(card) then + card.shattered = true + glass_shattered[#glass_shattered + 1] = card + else + card.destroyed = true + end + if card.base.name then + playing_cards[#playing_cards + 1] = card + end + card.skip_destroy_animation = skip_anim + end + end + + check_for_unlock{type = 'shatter', shattered = glass_shattered} + + if next(playing_cards) then SMODS.calculate_context({scoring_hand = cards, remove_playing_cards = true, removed = playing_cards}) end + + for i = 1, #cards do + if immediate then + if cards[i].shattered then + cards[i]:shatter() + elseif cards[i].destroyed then + cards[i]:start_dissolve() + end + else + G.E_MANAGER:add_event(Event({ + func = function() + if cards[i].shattered then + cards[i]:shatter() + elseif cards[i].destroyed then + cards[i]:start_dissolve() + end + return true + end + })) + end + end +end + +-- Hand Limit API +SMODS.hand_limit_strings = {play = '', discard = ''} +function SMODS.change_play_limit(mod) + G.GAME.starting_params.play_limit = G.GAME.starting_params.play_limit + mod + if G.GAME.starting_params.play_limit < 1 then + sendErrorMessage('Play limit is less than 1', 'HandLimitAPI') + end + G.hand.config.highlighted_limit = math.max(G.GAME.starting_params.discard_limit, G.GAME.starting_params.play_limit, 5) + SMODS.update_hand_limit_text(true) +end + +function SMODS.change_discard_limit(mod) + G.GAME.starting_params.discard_limit = G.GAME.starting_params.discard_limit + mod + if G.GAME.starting_params.discard_limit < 0 then + sendErrorMessage('Discard limit is less than 0', 'HandLimitAPI') + end + G.hand.config.highlighted_limit = math.max(G.GAME.starting_params.discard_limit, G.GAME.starting_params.play_limit, 5) + SMODS.update_hand_limit_text(nil, true) +end + +function SMODS.update_hand_limit_text(play, discard) + if play then SMODS.hand_limit_strings.play = G.GAME.starting_params.play_limit ~= 5 and localize('b_limit') .. math.max(1, G.GAME.starting_params.play_limit) or '' end + if discard then SMODS.hand_limit_strings.discard = G.GAME.starting_params.discard_limit ~= 5 and localize('b_limit') .. math.max(0, G.GAME.starting_params.discard_limit) or '' end +end + +function SMODS.draw_cards(hand_space) + if not (G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK or G.STATE == G.STATES.SMODS_BOOSTER_OPENED) and + G.hand.config.card_limit <= 0 and #G.hand.cards == 0 then + G.STATE = G.STATES.GAME_OVER; G.STATE_COMPLETE = false + return true + end + + local flags = SMODS.calculate_context({drawing_cards = true, amount = hand_space}) + hand_space = math.min(#G.deck.cards, flags.cards_to_draw or hand_space) + delay(0.3) + SMODS.drawn_cards = {} + for i=1, hand_space do --draw cards from deckL + if G.STATE == G.STATES.TAROT_PACK or G.STATE == G.STATES.SPECTRAL_PACK then + draw_card(G.deck,G.hand, i*100/hand_space,'up', true) + else + draw_card(G.deck,G.hand, i*100/hand_space,'up', true) + end + end + G.E_MANAGER:add_event(Event({ + trigger = 'before', + delay = 0.4, + func = function() + if #SMODS.drawn_cards > 0 then + SMODS.calculate_context({first_hand_drawn = not G.GAME.current_round.any_hand_drawn and G.GAME.facing_blind, + hand_drawn = G.GAME.facing_blind and SMODS.drawn_cards, + other_drawn = not G.GAME.facing_blind and SMODS.drawn_cards}) + SMODS.drawn_cards = {} + if G.GAME.facing_blind then G.GAME.current_round.any_hand_drawn = true end + end + return true + end + })) +end + +function SMODS.showman(card_key) + if SMODS.create_card_allow_duplicates or next(SMODS.find_card('j_ring_master')) then + return true + end + return false +end + +function SMODS.four_fingers(hand_type) + if next(SMODS.find_card('j_four_fingers')) then + return 4 + end + return 5 +end + +function SMODS.shortcut() + if next(SMODS.find_card('j_shortcut')) then + return true + end + return false +end + +function SMODS.wrap_around_straight() + return false +end + +function SMODS.merge_effects(...) + local t = {} + for _, v in ipairs({...}) do + for _, vv in ipairs(v) do + if vv == true or (type(vv) == "table" and next(vv)) then + table.insert(t, vv) + end + end + end + local ret = table.remove(t, 1) + ret = ret == true and { remove = true } or ret + local current = ret + for _, eff in ipairs(t) do + assert(eff == true or type(eff) == 'table', ("\"%s\" is not a valid calculate return."):format(tostring(eff))) + while current.extra ~= nil do + if current.extra == true then + current.extra = { remove = true } + end + assert(type(current.extra) == 'table', ("\"%s\" is not a valid calculate return."):format(tostring(current.extra))) + current = current.extra + end + current.extra = eff == true and { remove = true } or eff + end + return ret +end + +function SMODS.get_probability_vars(trigger_obj, base_numerator, base_denominator, identifier, from_roll, no_mod) + if not G.jokers then return base_numerator, base_denominator end + if no_mod then return base_numerator, base_denominator end + local additive = SMODS.calculate_context({mod_probability = true, from_roll = from_roll, trigger_obj = trigger_obj, identifier = identifier, numerator = base_numerator, denominator = base_denominator}, nil, not from_roll) + additive.numerator = (additive.numerator or base_numerator) * ((G.GAME and G.GAME.probabilities.normal or 1) / (2 ^ #SMODS.find_card('j_oops'))) + local fixed = SMODS.calculate_context({fix_probability = true, from_roll = from_roll, trigger_obj = trigger_obj, identifier = identifier, numerator = additive.numerator or base_numerator, denominator = additive.denominator or base_denominator}, nil, not from_roll) + return fixed.numerator or additive.numerator or base_numerator, fixed.denominator or additive.denominator or base_denominator +end + +function SMODS.pseudorandom_probability(trigger_obj, seed, base_numerator, base_denominator, identifier, no_mod) + local numerator, denominator = SMODS.get_probability_vars(trigger_obj, base_numerator, base_denominator, identifier or seed, true, no_mod) + local result = pseudorandom(seed) < numerator / denominator + SMODS.post_prob = SMODS.post_prob or {} + SMODS.post_prob[#SMODS.post_prob+1] = {pseudorandom_result = true, result = result, trigger_obj = trigger_obj, numerator = numerator, denominator = denominator, identifier = identifier or seed} + return result +end + +function SMODS.is_poker_hand_visible(handname) + if SMODS.PokerHands[handname] and SMODS.PokerHands[handname].visible and type(SMODS.PokerHands[handname].visible) == "function" then + return not not SMODS.PokerHands[handname]:visible() + end + assert(G.GAME.hands[handname], "handname '" .. handname .. "' not found!") + return not not SMODS.PokerHands[handname] and G.GAME.hands[handname].visible +end + +G.FUNCS.update_blind_debuff_text = function(e) + if not e.config.object then return end + local new_str = SMODS.debuff_text or G.GAME.blind:get_loc_debuff_text() + if new_str ~= e.config.object.string then + e.config.object.config.string = {new_str} + e.config.object:update_text(true) + e.UIBox:recalculate() + end +end + +function Card:should_hide_front() + return self.ability.effect == 'Stone Card' or self.config.center.replace_base_card +end + +function SMODS.is_eternal(card, trigger) + local calc_return = {} + local ovr_compat = false + local ret = false + if not trigger then trigger = {} end + SMODS.calculate_context({check_eternal = true, other_card = card, trigger = trigger, no_blueprint = true,}, calc_return) + for _,eff in pairs(calc_return) do + for _,tab in pairs(eff) do + if tab.no_destroy then --Reuses key from context.joker_type_destroyed + ret = true + if type(tab.no_destroy) == 'table' then + if tab.no_destroy.override_compat then ovr_compat = true end + end + end + end + end + if card.ability.eternal then ret = true end + if not card.config.center.eternal_compat and not ovr_compat then ret = false end + return ret +end + +-- Scoring Calculation API +function SMODS.set_scoring_calculation(key) + G.GAME.current_scoring_calculation = SMODS.Scoring_Calculations[key]:new() +end + +G.FUNCS.SMODS_scoring_calculation_function = function(e) + local first = false + if not (e.config.current_scoring_calculation and e.config.current_scoring_calculation == G.GAME.current_scoring_calculation.key) then + first = true + local scale = 0.4 + e.children[1].children[2]:remove() + e.children[1].children[2] = nil + if G.GAME.current_scoring_calculation.replace_ui then + e.children[1].UIBox:add_child(G.GAME.current_scoring_calculation:replace_ui(), e.children[1]) + else + e.children[1].UIBox:add_child(SMODS.GUI.hand_chips_container(scale), e.children[1]) + end + e.config.current_scoring_calculation = G.GAME.current_scoring_calculation.key + end + + local container = e.children[1].children[2] + local chip_display = container.UIBox:get_UIE_by_ID('hand_chips_container') + local operator = container.UIBox:get_UIE_by_ID('hand_operator_container') + local mult_display = container.UIBox:get_UIE_by_ID('hand_mult_container') + + if G.GAME.current_scoring_calculation.update_ui then + G.GAME.current_scoring_calculation:update_ui(container, chip_display, mult_display, operator) + else + if G.GAME.current_scoring_calculation.text and operator then + operator.children[1].config.text = type(G.GAME.current_scoring_calculation.text) == 'function' and G.GAME.current_scoring_calculation:text() or G.GAME.current_scoring_calculation.text + end + if G.GAME.current_scoring_calculation.colour and operator then + operator.children[1].config.colour = type(G.GAME.current_scoring_calculation.colour) == 'function' and G.GAME.current_scoring_calculation:colour() or G.GAME.current_scoring_calculation.colour + end + if operator and (type(G.GAME.current_scoring_calculation.colour) == 'function' or type(G.GAME.current_scoring_calculation.text) == 'function') then operator.UIBox:recalculate() end + end +end + +SMODS.calculate_round_score = function(flames) + if not G.GAME.current_scoring_calculation then return 0 end + return G.GAME.current_scoring_calculation:func(SMODS.get_scoring_parameter('chips', flames), SMODS.get_scoring_parameter('mult', flames), flames) +end + +function SMODS.get_scoring_parameter(key, flames) + if flames then return G.GAME.current_round.current_hand[key] end + return SMODS.Scoring_Parameters[key].current or SMODS.Scoring_Parameters[key].default_value +end + + +-- Adds tag_triggered context +local tag_apply = Tag.apply_to_run +function Tag:apply_to_run(_context) + local res = tag_apply(self, _context) + if self.triggered and not self.triggered_calc then + SMODS.calculate_context({tag_triggered = self}) + self.triggered_calc = true + end + return res +end + +function SMODS.scale_card(card, args) + if not G.deck then return end + if not args.operation then args.operation = "+" end + args.block_overrides = args.block_overrides or {} + args.ref_table = args.ref_table or card.ability.extra + args.scalar_table = args.scalar_table or args.ref_table + local initial = args.ref_table[args.ref_value] + local scalar_value = args.scalar_table[args.scalar_value] + if args.operation == '-' and scalar_value < 0 then scalar_value = scalar_value * -1 end + local scaling_message = args.scaling_message + local scaling_responses = {} + for _, area in ipairs(SMODS.get_card_areas('jokers')) do + for _, _card in ipairs(area.cards) do + local obj = _card.config.center + if obj.calc_scaling and type(obj.calc_scaling) == "function" then + local ret = obj:calc_scaling(_card, card, initial, scalar_value, args) + if ret then + if ret.override_value and not args.block_overrides.value then initial = ret.override_value.value; SMODS.calculate_effect(ret.override_value, _card) end + if ret.override_scalar_value and not args.block_overrides.scalar then scalar_value = ret.override_scalar_value.value; SMODS.calculate_effect(ret.override_scalar_value, _card) end + if ret.override_message and not args.block_overrides.message then scaling_message = SMODS.merge_defaults(ret.override_message, scaling_message) end + if ret.post then ret.post.source = _card; scaling_responses[#scaling_responses + 1] = ret.post end + SMODS.calculate_effect(ret, _card) + end + end + end + end + + if type(args.operation) == 'function' then + args.operation(args.ref_table, args.ref_value, initial, scalar_value) + elseif args.operation == 'X' then + SMODS.multiplicative_scaling(args.ref_table, args.ref_value, initial, scalar_value) + elseif args.operation == '-' then + SMODS.additive_scaling(args.ref_table, args.ref_value, initial, -1 * scalar_value) + else + SMODS.additive_scaling(args.ref_table, args.ref_value, initial, scalar_value) + end + + scaling_message = scaling_message or { + message = localize(args.message_key and {type='variable',key=args.message_key,vars={args.message_key =='a_xmult' and args.ref_table[args.ref_value] or scalar_value}} or 'k_upgrade_ex'), + colour = args.message_colour or G.C.FILTER + } + if next(scaling_message) and not args.no_message then + SMODS.calculate_effect(scaling_message, card) + end + for _, ret in ipairs(scaling_responses) do + SMODS.calculate_effect(ret, ret.source) + end +end + +function SMODS.additive_scaling(ref_table, ref_value, initial, modifier) + ref_table[ref_value] = initial + modifier +end + +function SMODS.multiplicative_scaling(ref_table, ref_value, initial, modifier) + ref_table[ref_value] = initial * modifier +end + +function SMODS.quip(quip_type) + if not quip_type then return nil end + local pool = {} + local total_weight = 0 + for k, v in pairs(SMODS.JimboQuips) do + local add = true + local in_pool, pool_opts, deck_pool_opts, mod_pool_opts + if v.filter and type(v.filter) == 'function' then + in_pool, pool_opts = v:filter(quip_type) + end + local deck = G.P_CENTERS[G.GAME.selected_back.effect.center.key] or SMODS.Centers[G.GAME.selected_back.effect.center.key] + if deck and deck.quip_filter and type(deck.quip_filter) == 'function' then + add, deck_pool_opts = deck.quip_filter(v, quip_type) + end + for _, mod in ipairs(SMODS.mod_list) do + if mod.can_load and mod.quip_filter and type(mod.quip_filter) == "function" then + local mod_add + mod_add, mod_pool_opts = mod.quip_filter(v, quip_type) + add = add and mod_add + end + end + if v.filter and type(v.filter) == 'function' then + add = in_pool and (add or (mod_pool_opts and mod_pool_opts.override_base_checks) or (deck_pool_opts and deck_pool_opts.override_base_checks) or (pool_opts and pool_opts.override_base_checks)) + end + if v.type and v.type ~= quip_type then + add = false + end + if add then + local weight = (mod_pool_opts and mod_pool_opts.weight and math.max(1, math.floor(mod_pool_opts.weight))) or (deck_pool_opts and deck_pool_opts.weight and math.max(1, math.floor(deck_pool_opts.weight))) or (pool_opts and pool_opts.weight and math.max(1, math.floor(pool_opts.weight))) or 1 + pool[#pool+1] = {quip = v, weight = weight} + total_weight = total_weight + weight + end + end + local quip_poll = pseudorandom(quip_type) + local it = 0 + for _, v in ipairs(pool) do + it = it + v.weight + if it/total_weight >= quip_poll then + local args = {} + if v.quip.extra then + if type(v.quip.extra) == 'function' then + args = v.quip.extra() + else + args = v.quip.extra + end + end + return v.quip.key, args + end + end +end + + +local ref_challenge_desc = G.UIDEF.challenge_description_tab +function G.UIDEF.challenge_description_tab(args) + args = args or {} + + if args._tab == 'Restrictions' then + local challenge = G.CHALLENGES[args._id] + if challenge.restrictions then + if challenge.restrictions.banned_cards and type(challenge.restrictions.banned_cards) == 'function' then + challenge.restrictions.banned_cards = challenge.restrictions.banned_cards() + end + + if challenge.restrictions.banned_tags and type(challenge.restrictions.banned_tags) == 'function' then + challenge.restrictions.banned_tags = challenge.restrictions.banned_tags() + end + + if challenge.restrictions.banned_other and type(challenge.restrictions.banned_other) == 'function' then + challenge.restrictions.banned_other = challenge.restrictions.banned_other() + end + end + end + + return ref_challenge_desc(args) +end +function SMODS.localize_perma_bonuses(specific_vars, desc_nodes) + if specific_vars and specific_vars.bonus_x_chips then + localize{type = 'other', key = 'card_x_chips', nodes = desc_nodes, vars = {specific_vars.bonus_x_chips}} + end + if specific_vars and specific_vars.bonus_mult then + localize{type = 'other', key = 'card_extra_mult', nodes = desc_nodes, vars = {SMODS.signed(specific_vars.bonus_mult)}} + end + if specific_vars and specific_vars.bonus_x_mult then + localize{type = 'other', key = 'card_x_mult', nodes = desc_nodes, vars = {specific_vars.bonus_x_mult}} + end + if specific_vars and specific_vars.bonus_h_chips then + localize{type = 'other', key = 'card_extra_h_chips', nodes = desc_nodes, vars = {SMODS.signed(specific_vars.bonus_h_chips)}} + end + if specific_vars and specific_vars.bonus_x_chips then + localize{type = 'other', key = 'card_h_x_chips', nodes = desc_nodes, vars = {specific_vars.bonus_h_x_chips}} + end + if specific_vars and specific_vars.bonus_h_mult then + localize{type = 'other', key = 'card_extra_h_mult', nodes = desc_nodes, vars = {SMODS.signed(specific_vars.bonus_h_mult)}} + end + if specific_vars and specific_vars.bonus_h_x_mult then + localize{type = 'other', key = 'card_h_x_mult', nodes = desc_nodes, vars = {specific_vars.bonus_h_x_mult}} + end + if specific_vars and specific_vars.bonus_p_dollars then + localize{type = 'other', key = 'card_extra_p_dollars', nodes = desc_nodes, vars = {SMODS.signed_dollars(specific_vars.bonus_p_dollars)}} + end + if specific_vars and specific_vars.bonus_h_dollars then + localize{type = 'other', key = 'card_extra_h_dollars', nodes = desc_nodes, vars = {SMODS.signed_dollars(specific_vars.bonus_h_dollars)}} + end + if specific_vars and specific_vars.bonus_repetitions then + localize{type = 'other', key = 'card_extra_repetitions', nodes = desc_nodes, vars = {specific_vars.bonus_repetitions, localize(specific_vars.bonus_repetitions > 1 and 'b_retrigger_plural' or 'b_retrigger_single')}} + end +end + +local ease_dollar_ref = ease_dollars +function ease_dollars(mod, instant) + ease_dollar_ref(mod, instant) + SMODS.calculate_context({ + money_altered = true, + amount = mod, + from_shop = (G.STATE == G.STATES.SHOP or G.STATE == G.STATES.SMODS_BOOSTER_OPENED or G.STATE == G.STATES.SMODS_REDEEM_VOUCHER) or nil, + from_consumeable = (G.STATE == G.STATES.PLAY_TAROT) or nil, + from_scoring = (G.STATE == G.STATES.HAND_PLAYED) or nil, + }) +end +function SMODS.add_to_pool(prototype_obj, args) + if type(prototype_obj.in_pool) == "function" then + return prototype_obj:in_pool(args) + end + return true +end + + +function Card:is_rarity(rarity) + if self.ability.set ~= "Joker" then return false end + local rarities = {"Common", "Uncommon", "Rare", "Legendary"} + rarity = rarities[rarity] or rarity + local own_rarity = rarities[self.config.center.rarity] or self.config.center.rarity + return own_rarity == rarity or SMODS.Rarities[own_rarity] == rarity +end + +function UIElement:draw_pixellated_under(_type, _parallax, _emboss, _progress) + if not self.pixellated_rect or + #self.pixellated_rect[_type].vertices < 1 or + _parallax ~= self.pixellated_rect.parallax or + self.pixellated_rect.w ~= self.VT.w or + self.pixellated_rect.h ~= self.VT.h or + self.pixellated_rect.sw ~= self.shadow_parrallax.x or + self.pixellated_rect.sh ~= self.shadow_parrallax.y or + self.pixellated_rect.progress ~= (_progress or 1) + then + self.pixellated_rect = { + w = self.VT.w, + h = self.VT.h, + sw = self.shadow_parrallax.x, + sh = self.shadow_parrallax.y, + progress = (_progress or 1), + fill = {vertices = {}}, + shadow = {vertices = {}}, + line = {vertices = {}}, + emboss = {vertices = {}}, + line_emboss = {vertices = {}}, + parallax = _parallax + } + local ext_up = self.config.ext_up and self.config.ext_up*G.TILESIZE or 0 + local totw, toth = self.VT.w*G.TILESIZE, (self.VT.h + math.abs(ext_up)/G.TILESIZE)*G.TILESIZE + + local vertices = { + totw,toth+ext_up, + 0, toth+ext_up, + 0, toth+ext_up+0.5, + totw,toth+ext_up+0.5 + } + for k, v in ipairs(vertices) do + if k%2 == 1 and v > totw*self.pixellated_rect.progress then v = totw*self.pixellated_rect.progress end + self.pixellated_rect.fill.vertices[k] = v + if k > 4 then + self.pixellated_rect.line.vertices[k-4] = v + if _emboss then + self.pixellated_rect.line_emboss.vertices[k-4] = v + (k%2 == 0 and -_emboss*self.shadow_parrallax.y or -0.7*_emboss*self.shadow_parrallax.x) + end + end + if k%2 == 0 then + self.pixellated_rect.shadow.vertices[k] = v -self.shadow_parrallax.y*_parallax + if _emboss then + self.pixellated_rect.emboss.vertices[k] = v + _emboss*G.TILESIZE + end + else + self.pixellated_rect.shadow.vertices[k] = v -self.shadow_parrallax.x*_parallax + if _emboss then + self.pixellated_rect.emboss.vertices[k] = v + end + end + end + end + love.graphics.polygon("fill", self.pixellated_rect.fill.vertices) + +end + +function CardArea:count_extra_slots_used(cards) + local slots = #cards + if (self.config.type == 'joker' or self.config.type == 'hand') and not self.config.fixed_limit then + for _, card in ipairs(cards) do + slots = slots + card.ability.extra_slots_used + end + end + return slots +end + +function SMODS.should_handle_limit(area) + if (area.config.type == 'joker' or area.config.type == 'hand') and not area.config.fixed_limit then + return true + end +end + +function CardArea:handle_card_limit(card_limit, card_slots) + if SMODS.should_handle_limit(self) then + card_limit = card_limit or 0 + card_slots = card_slots or 0 + if card_limit ~= 0 then + G.E_MANAGER:add_event(Event({ + trigger = 'immediate', + func = function() + self.config.card_limit = self.config.card_limit + card_limit + return true + end + })) + end + if card_slots ~= 0 then + G.E_MANAGER:add_event(Event({ + trigger = 'immediate', + func = function() + self.config.no_true_limit = true + self.config.card_limit = self.config.card_limit - card_slots + self.config.no_true_limit = false + return true + end + })) + + end + if G.hand and self == G.hand and card_limit - card_slots > 0 then + if G.STATE == G.STATES.SELECTING_HAND then G.FUNCS.draw_from_deck_to_hand(math.min(card_limit - card_slots, (self.config.card_limit + card_limit - card_slots) - #self.cards)) end + check_for_unlock({type = 'min_hand_size'}) + end + end +end diff --git a/Steamodded/version.lua b/Steamodded/version.lua index a6711c8..238bf80 100644 --- a/Steamodded/version.lua +++ b/Steamodded/version.lua @@ -1 +1 @@ -return "1.0.0~BETA-0406a-STEAMODDED" +return "1.0.0~BETA-0827c-STEAMODDED" \ No newline at end of file diff --git a/Talisman/.gitattributes b/Talisman/.gitattributes deleted file mode 100644 index dfe0770..0000000 --- a/Talisman/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto diff --git a/Talisman/.gitignore b/Talisman/.gitignore deleted file mode 100644 index b65a9d4..0000000 --- a/Talisman/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -config.lua -.vscode \ No newline at end of file diff --git a/Talisman/LICENSE b/Talisman/LICENSE new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/Talisman/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/Talisman/README.md b/Talisman/README.md index eadcb02..fd39717 100644 --- a/Talisman/README.md +++ b/Talisman/README.md @@ -5,11 +5,12 @@ The "BigNum" representation used by Talisman is a modified version of [this](htt The "OmegaNum" representation used by Talisman is a port of [OmegaNum.js](https://github.com/Naruyoko/OmegaNum.js/blob/master/OmegaNum.js) by [Mathguy23](https://github.com/Mathguy23) ## Installation -Talisman requires [Lovely](https://github.com/ethangreen-dev/lovely-injector) to be installed in order to be loaded by Balatro. The code for Talisman must be installed in `%AppData%/Balatro/Mods/Talisman`. +Talisman requires [Lovely](https://github.com/ethangreen-dev/lovely-injector) to be installed in order to be loaded by Balatro. ## Limitations - High scores will not be saved to your profile (this is to prevent your profile save from being incompatible with an unmodified instance of Balatro) - Savefiles created/opened with Talisman aren't backwards-compatible with unmodified versions of Balatro. - Depending on the amount of retriggers, there may be lag when computing a score with Talisman. -- The largest ante before score requirements reach the new limit is approximately 2e153. -- When using Talisman with other mods, comparison operations with numbers used by scoring will not work by default (these must be handled by the mod developer). +- The largest ante before the new limit is approximately 1e300 due to BigNumber antes not being supported. +- When using Talisman with other mods because of how Talisman works, comparison operations with numbers used by scoring will not work by default, a lot of interactions without explicit support will break with Talisman enabled. +- [Luajit2 (Balatro Discord)](https://discord.com/channels/1116389027176787968/1336473631483760791) can be used to mitigate some of the issues but it will not fix everything. diff --git a/Talisman/big-num/bignumber.lua b/Talisman/big-num/bignumber.lua index 6ca6e6e..968027b 100644 --- a/Talisman/big-num/bignumber.lua +++ b/Talisman/big-num/bignumber.lua @@ -177,6 +177,10 @@ function Big:round() end end +function Big:arraySize() + return 1 +end + function Big:floor() if self.e > 100 then return self end return Big:new(math.floor(self:to_number())) diff --git a/Talisman/big-num/notations.lua b/Talisman/big-num/notations.lua index 94d8cde..26a778f 100644 --- a/Talisman/big-num/notations.lua +++ b/Talisman/big-num/notations.lua @@ -1,18 +1,18 @@ local lovely = require("lovely") local nativefs = require("nativefs") Notations = { - BaseLetterNotation = nativefs.load(lovely.mod_dir.."/Talisman/big-num/notations/baseletternotation.lua")(), - LetterNotation = nativefs.load(lovely.mod_dir.."/Talisman/big-num/notations/letternotation.lua")(), - CyrillicNotation = nativefs.load(lovely.mod_dir.."/Talisman/big-num/notations/cyrillicnotation.lua")(), - GreekNotation = nativefs.load(lovely.mod_dir.."/Talisman/big-num/notations/greeknotation.lua")(), - HebrewNotation = nativefs.load(lovely.mod_dir.."/Talisman/big-num/notations/hebrewnotation.lua")(), - ScientificNotation = nativefs.load(lovely.mod_dir.."/Talisman/big-num/notations/scientificnotation.lua")(), - EngineeringNotation = nativefs.load(lovely.mod_dir.."/Talisman/big-num/notations/engineeringnotation.lua")(), - BaseStandardNotation = nativefs.load(lovely.mod_dir.."/Talisman/big-num/notations/basestandardnotation.lua")(), - StandardNotation = nativefs.load(lovely.mod_dir.."/Talisman/big-num/notations/standardnotation.lua")(), - ThousandNotation = nativefs.load(lovely.mod_dir.."/Talisman/big-num/notations/thousandnotation.lua")(), - DynamicNotation = nativefs.load(lovely.mod_dir.."/Talisman/big-num/notations/dynamicnotation.lua")(), - Balatro = nativefs.load(lovely.mod_dir.."/Talisman/big-num/notations/Balatro.lua")(), + BaseLetterNotation = nativefs.load(Talisman.mod_path.."/big-num/notations/baseletternotation.lua")(), + LetterNotation = nativefs.load(Talisman.mod_path.."/big-num/notations/letternotation.lua")(), + CyrillicNotation = nativefs.load(Talisman.mod_path.."/big-num/notations/cyrillicnotation.lua")(), + GreekNotation = nativefs.load(Talisman.mod_path.."/big-num/notations/greeknotation.lua")(), + HebrewNotation = nativefs.load(Talisman.mod_path.."/big-num/notations/hebrewnotation.lua")(), + ScientificNotation = nativefs.load(Talisman.mod_path.."/big-num/notations/scientificnotation.lua")(), + EngineeringNotation = nativefs.load(Talisman.mod_path.."/big-num/notations/engineeringnotation.lua")(), + BaseStandardNotation = nativefs.load(Talisman.mod_path.."/big-num/notations/basestandardnotation.lua")(), + StandardNotation = nativefs.load(Talisman.mod_path.."/big-num/notations/standardnotation.lua")(), + ThousandNotation = nativefs.load(Talisman.mod_path.."/big-num/notations/thousandnotation.lua")(), + DynamicNotation = nativefs.load(Talisman.mod_path.."/big-num/notations/dynamicnotation.lua")(), + Balatro = nativefs.load(Talisman.mod_path.."/big-num/notations/Balatro.lua")(), } return Notations diff --git a/Talisman/big-num/notations/Balatro.lua b/Talisman/big-num/notations/Balatro.lua index ef70a4a..7e7757e 100644 --- a/Talisman/big-num/notations/Balatro.lua +++ b/Talisman/big-num/notations/Balatro.lua @@ -1,6 +1,6 @@ local lovely = require("lovely") local nativefs = require("nativefs") -Notation = nativefs.load(lovely.mod_dir.."/Talisman/big-num/notations/notation.lua")() +Notation = nativefs.load(Talisman.mod_path.."/big-num/notations/notation.lua")() BalaNotation = {} BalaNotation.__index = BalaNotation BalaNotation.__tostring = function () @@ -15,10 +15,11 @@ end function BalaNotation:format(n, places) --vanilla balatro number_format function basically local function e_ify(num) + --if not num then return "0" end if type(num) == "table" then num = num:to_number() end - if num >= 10^6 then + if (num or 0) >= 10^6 then local x = string.format("%.4g",num) local fac = math.floor(math.log(tonumber(x), 10)) return string.format("%.3f",x/(10^fac))..'e'..fac @@ -36,12 +37,12 @@ function BalaNotation:format(n, places) local mantissa = 10^(n.array[1]-math.floor(n.array[1])) mantissa = math.floor(mantissa*10^places+0.5)/10^places local exponent = math.floor(n.array[1]) - return mantissa.."e"..e_ify(exponent) + return (n.sign == -1 and "-" or "")..mantissa.."e"..e_ify(exponent) else local exponent = math.floor(math.log(n.array[1],10)) local mantissa = n.array[1]/10^exponent mantissa = math.floor(mantissa*10^places+0.5)/10^places - return mantissa.."e"..e_ify(exponent) + return (n.sign == -1 and "-" or "")..mantissa.."e"..e_ify(exponent) end elseif to_big(n:log10()) < to_big(10)^1000000 then --e1.234e56789 @@ -54,32 +55,34 @@ function BalaNotation:format(n, places) local mantissa = 10^(n.array[1]-math.floor(n.array[1])) mantissa = math.floor(mantissa*10^places+0.5)/10^places local exponent = math.floor(n.array[1]) - return "e"..mantissa.."e"..e_ify(exponent) + return (n.sign == -1 and "-" or "").."e"..mantissa.."e"..e_ify(exponent) else local exponent = math.floor(math.log(n.array[1],10)) local mantissa = n.array[1]/10^exponent mantissa = math.floor(mantissa*10^places+0.5)/10^places - return "e"..mantissa.."e"..e_ify(exponent) + return (n.sign == -1 and "-" or "").."e"..mantissa.."e"..e_ify(exponent) end + elseif n:isNaN() then + return "nan" elseif not n.array or not (n.isFinite and n:isFinite()) then return "Infinity" - elseif n.array[2] and #n.array == 2 and n.array[2] <= 8 then + elseif n.array[2] and n:arraySize() == 2 and n.array[2] <= 8 then --eeeeeee1.234e56789 local mantissa = 10^(n.array[1]-math.floor(n.array[1])) mantissa = math.floor(mantissa*10^places+0.5)/10^places local exponent = math.floor(n.array[1]) - return string.rep("e", n.array[2]-1)..mantissa.."e"..e_ify(exponent) - elseif #n.array < 8 then + return (n.sign == -1 and "-" or "")..string.rep("e", n.array[2]-1)..mantissa.."e"..e_ify(exponent) + elseif n:arraySize() < 8 then --e12#34#56#78 - local r = "e"..e_ify(math.floor(n.array[1]*10^places+0.5)/10^places).."#"..e_ify(n.array[2]) - for i = 3, #n.array do - r = r.."#"..e_ify(n.array[i]+1) + local r = (n.sign == -1 and "-e" or "e")..e_ify(math.floor(n.array[1]*10^places+0.5)/10^places).."#"..e_ify(n.array[2] or 1) + for i = 3, n:arraySize() do + r = r.."#"..e_ify((n.array[i] or 0)+1) end return r else --e12#34##5678 - return "e"..e_ify(math.floor(n.array[1]*10^places+0.5)/10^places).."#"..e_ify(n.array[#n.array]).."##"..e_ify(#n.array-2) + return (n.sign == -1 and "-e" or "e")..e_ify(math.floor(n.array[1]*10^places+0.5)/10^places).."#"..e_ify(n.array[n:arraySize()] or 0).."##"..e_ify(n:arraySize()-2) end end -return BalaNotation +return BalaNotation \ No newline at end of file diff --git a/Talisman/big-num/notations/baseletternotation.lua b/Talisman/big-num/notations/baseletternotation.lua index 998ca4d..b763597 100644 --- a/Talisman/big-num/notations/baseletternotation.lua +++ b/Talisman/big-num/notations/baseletternotation.lua @@ -1,6 +1,6 @@ local lovely = require("lovely") local nativefs = require("nativefs") -Notation = nativefs.load(lovely.mod_dir.."/Talisman/big-num/notations/notation.lua")() +Notation = nativefs.load(Talisman.mod_path.."/big-num/notations/notation.lua")() BaseLetterNotation = {} BaseLetterNotation.__index = BaseLetterNotation diff --git a/Talisman/big-num/notations/basestandardnotation.lua b/Talisman/big-num/notations/basestandardnotation.lua index f0aa9f5..0c5687b 100644 --- a/Talisman/big-num/notations/basestandardnotation.lua +++ b/Talisman/big-num/notations/basestandardnotation.lua @@ -1,6 +1,6 @@ local lovely = require("lovely") local nativefs = require("nativefs") -Notation = nativefs.load(lovely.mod_dir.."/Talisman/big-num/notations/notation.lua")() +Notation = nativefs.load(Talisman.mod_path.."/big-num/notations/notation.lua")() BaseStandardNotation = {} BaseStandardNotation.__index = BaseStandardNotation BaseStandardNotation.__tostring = function (notation) diff --git a/Talisman/big-num/notations/cyrillicnotation.lua b/Talisman/big-num/notations/cyrillicnotation.lua index 230d03b..8a31e5b 100644 --- a/Talisman/big-num/notations/cyrillicnotation.lua +++ b/Talisman/big-num/notations/cyrillicnotation.lua @@ -1,6 +1,6 @@ local lovely = require("lovely") local nativefs = require("nativefs") -BaseLetterNotation = nativefs.load(lovely.mod_dir.."/Talisman/big-num/notations/baseletternotation.lua")() +BaseLetterNotation = nativefs.load(Talisman.mod_path.."/big-num/notations/baseletternotation.lua")() CyrillicNotation = {} CyrillicNotation.__index = LetterNotation diff --git a/Talisman/big-num/notations/dynamicnotation.lua b/Talisman/big-num/notations/dynamicnotation.lua index df5a17d..b626525 100644 --- a/Talisman/big-num/notations/dynamicnotation.lua +++ b/Talisman/big-num/notations/dynamicnotation.lua @@ -1,7 +1,7 @@ local lovely = require("lovely") local nativefs = require("nativefs") -Notation = nativefs.load(lovely.mod_dir.."/Talisman/big-num/notations/notation.lua")() -ThousandNotation = nativefs.load(lovely.mod_dir.."/Talisman/big-num/notations/thousandnotation.lua")() +Notation = nativefs.load(Talisman.mod_path.."/big-num/notations/notation.lua")() +ThousandNotation = nativefs.load(Talisman.mod_path.."/big-num/notations/thousandnotation.lua")() DynamicNotation = {} DynamicNotation.__index = DynamicNotation diff --git a/Talisman/big-num/notations/engineeringnotation.lua b/Talisman/big-num/notations/engineeringnotation.lua index 98f847f..fefadc9 100644 --- a/Talisman/big-num/notations/engineeringnotation.lua +++ b/Talisman/big-num/notations/engineeringnotation.lua @@ -1,6 +1,6 @@ local lovely = require("lovely") local nativefs = require("nativefs") -Notation = nativefs.load(lovely.mod_dir.."/Talisman/big-num/notations/notation.lua")() +Notation = nativefs.load(Talisman.mod_path.."/big-num/notations/notation.lua")() EngineeringNotation = {} EngineeringNotation.__index = EngineeringNotation diff --git a/Talisman/big-num/notations/greeknotation.lua b/Talisman/big-num/notations/greeknotation.lua index 9f6099a..b4e4e57 100644 --- a/Talisman/big-num/notations/greeknotation.lua +++ b/Talisman/big-num/notations/greeknotation.lua @@ -1,6 +1,6 @@ local lovely = require("lovely") local nativefs = require("nativefs") -BaseLetterNotation = nativefs.load(lovely.mod_dir.."/Talisman/big-num/notations/baseletternotation.lua")() +BaseLetterNotation = nativefs.load(Talisman.mod_path.."/big-num/notations/baseletternotation.lua")() GreekNotation = {} GreekNotation.__index = LetterNotation diff --git a/Talisman/big-num/notations/hebrewnotation.lua b/Talisman/big-num/notations/hebrewnotation.lua index e93eb73..f00eacb 100644 --- a/Talisman/big-num/notations/hebrewnotation.lua +++ b/Talisman/big-num/notations/hebrewnotation.lua @@ -1,6 +1,6 @@ local lovely = require("lovely") local nativefs = require("nativefs") -BaseLetterNotation = nativefs.load(lovely.mod_dir.."/Talisman/big-num/notations/baseletternotation.lua")() +BaseLetterNotation = nativefs.load(Talisman.mod_path.."/big-num/notations/baseletternotation.lua")() HebrewNotation = {} HebrewNotation.__index = LetterNotation diff --git a/Talisman/big-num/notations/letternotation.lua b/Talisman/big-num/notations/letternotation.lua index 473661e..92b6543 100644 --- a/Talisman/big-num/notations/letternotation.lua +++ b/Talisman/big-num/notations/letternotation.lua @@ -1,6 +1,6 @@ local lovely = require("lovely") local nativefs = require("nativefs") -BaseLetterNotation = nativefs.load(lovely.mod_dir.."/Talisman/big-num/notations/baseletternotation.lua")() +BaseLetterNotation = nativefs.load(Talisman.mod_path.."/big-num/notations/baseletternotation.lua")() LetterNotation = {} LetterNotation.__index = LetterNotation diff --git a/Talisman/big-num/notations/scientificnotation.lua b/Talisman/big-num/notations/scientificnotation.lua index 005d563..9f24224 100644 --- a/Talisman/big-num/notations/scientificnotation.lua +++ b/Talisman/big-num/notations/scientificnotation.lua @@ -1,6 +1,6 @@ local lovely = require("lovely") local nativefs = require("nativefs") -Notation = nativefs.load(lovely.mod_dir.."/Talisman/big-num/notations/notation.lua")() +Notation = nativefs.load(Talisman.mod_path.."/big-num/notations/notation.lua")() ScientificNotation = {} ScientificNotation.__index = ScientificNotation ScientificNotation.__tostring = function () diff --git a/Talisman/big-num/notations/standardnotation.lua b/Talisman/big-num/notations/standardnotation.lua index 6b2fe82..783dd76 100644 --- a/Talisman/big-num/notations/standardnotation.lua +++ b/Talisman/big-num/notations/standardnotation.lua @@ -1,6 +1,6 @@ local lovely = require("lovely") local nativefs = require("nativefs") -BaseStandardNotation = nativefs.load(lovely.mod_dir.."/Talisman/big-num/notations/basestandardnotation.lua")() +BaseStandardNotation = nativefs.load(Talisman.mod_path.."/big-num/notations/basestandardnotation.lua")() StandardNotation = {} StandardNotation.__index = StandardNotation diff --git a/Talisman/big-num/notations/thousandnotation.lua b/Talisman/big-num/notations/thousandnotation.lua index f6ca0c3..5a66378 100644 --- a/Talisman/big-num/notations/thousandnotation.lua +++ b/Talisman/big-num/notations/thousandnotation.lua @@ -1,6 +1,6 @@ local lovely = require("lovely") local nativefs = require("nativefs") -Notation = nativefs.load(lovely.mod_dir.."/Talisman/big-num/notations/notation.lua")() +Notation = nativefs.load(Talisman.mod_path.."/big-num/notations/notation.lua")() ThousandNotation = {} ThousandNotation.__index = ThousandNotation diff --git a/Talisman/big-num/omeganum.lua b/Talisman/big-num/omeganum.lua index f5b1d51..21124bf 100644 --- a/Talisman/big-num/omeganum.lua +++ b/Talisman/big-num/omeganum.lua @@ -42,6 +42,9 @@ R.E_MAX_SAFE_INTEGER="e"..tostring(R.MAX_SAFE_INTEGER) R.EE_MAX_SAFE_INTEGER="ee"..tostring(R.MAX_SAFE_INTEGER) R.TETRATED_MAX_SAFE_INTEGER="10^^"..tostring(R.MAX_SAFE_INTEGER) +-- this will be populated with bignum equivalents of R's values at the end of the file +B = {} + --------------make the numbers look good---------------------- function thousands_format(number) return string.format("%.2f", number) @@ -69,6 +72,16 @@ end ------------------------------------------------------ +function Big:arraySize() + local total = 0 + for i, v in pairs(self.array) do + if type(i) == "number" and v ~= 0 then + total = i + end + end + return total +end + function Big:new(arr) return setmetatable({array = arr, sign = 1}, OmegaMeta):normalize() end @@ -89,15 +102,20 @@ function Big:isint() if (self.sign==-1) then return self:abs():isint() end - if (self:gt(R.MAX_SAFE_INTEGER)) then + if (self:gt(B.MAX_SAFE_INTEGER)) then return true; end local num = self:to_number() - return (math.floor(num) == num); + if (math.floor(num) == num) then + return true + end + return Big:create(math.floor(self:to_number())) == self; end function Big:compareTo(other) - other = Big:create(other) + other = Big:ensureBig(other) + local other_array_size = other:arraySize() + local self_array_size = self:arraySize() if ((self.array[1] ~= self.array[1]) or (other.array[1] ~= other.array[1])) then return R.NaN; end @@ -107,24 +125,42 @@ function Big:compareTo(other) if ((self.array[1]~=R.POSITIVE_INFINITY) and (other.array[1]==R.POSITIVE_INFINITY)) then return other.sign end - if ((#self.array==1) and (self.array[1]==0) and (#other.array==1) and (other.array[1]==0)) then - return 0 + if ((self_array_size==1) and (self.array[1]==other.array[1]) and (other_array_size==1)) then + --return 0 end if (self.sign~=other.sign) then - return self.sign + return self.sign end local m = self.sign; local r = nil; - if (#self.array>#other.array) then + if (self_array_size>other_array_size) then r = 1; - elseif (#self.array<#other.array) then + elseif (self_array_sizeother.array[i]) then + if self_array_size == 1 then + if self.array[1] > other.array[1] then + return 1 * m + elseif self.array[1] < other.array[1] then + return -1 * m + else + return 0 + end + end + local barray = {} + for i, v in pairs(self.array) do + barray[#barray+1]=i + end + --make sure to include both sets of indeces so that it actually checks every non 0 value + for i, v in pairs(other.array) do + barray[#barray+1]=i + end + table.sort(barray, function(a,b) return a > b end) + for i, v in pairs(barray) do + if ((self.array[v] or 0)>(other.array[v] or 0)) then r = 1; break; - elseif (self.array[i] l then - l = i - end - end - for i=1,l do - local e = x.array[i]; - if ((e == nil)) then - x.array[i] = 0 - e = 0 - end + for i, v in pairs(x.array) do + local e = x.array[i] or 0; if (e ~= e) then x.array={R.NaN}; return x; @@ -227,26 +253,31 @@ function Big:normalize() if (i ~= 1) then x.array[i]=math.floor(e) end + --first 3 values kept because they are hardcoded in a few places + --it also doesnt hurt memory that much to keep them anyway + if ((e == 0)) and i > 3 then + x.array[i] = nil + end end local doOnce = true while (doOnce or b) do -- if (OmegaNum.debug>=OmegaNum.ALL) console.log(x.toString()); b=false; - while ((#x.array ~= 0) and (x.array[#x.array]==0)) do - x.array[#x.array] = nil; + while ((x:arraySize() ~= 0) and (x.array[x:arraySize()]==0)) do + x.array[x:arraySize()] = nil; b=true; end - if (x.array[1] > R.MAX_DISP_INTEGER) then --modified, should make printed values easier to display + if ((x.array[1] or 0) > R.MAX_DISP_INTEGER) then --modified, should make printed values easier to display x.array[2]=(x.array[2] or 0) + 1; x.array[1]= math.log(x.array[1], 10); b=true; end - while ((x.array[1] < math.log(R.MAX_DISP_INTEGER,10)) and ((x.array[2] ~= nil) and (x.array[2] ~= 0))) do + while (((x.array[1] or 0) < math.log(R.MAX_DISP_INTEGER,10)) and ((x.array[2] ~= nil) and (x.array[2] ~= 0))) do x.array[1] = math.pow(10,x.array[1], 10); x.array[2] = x.array[2] - 1 b=true; end - -- if ((#x.array>2) and ((x.array[2] == nil) or (x.array[2] == 0))) then + -- if ((x:arraySize()>2) and ((x.array[2] == nil) or (x.array[2] == 0))) then -- local i = 3 -- while (x.array[i] == nil) or (x.array[i] == 0) do -- i = i + 1 @@ -257,35 +288,37 @@ function Big:normalize() -- b=true; -- end doOnce = false; - l = #x.array - for i=1,l do - if (x.array[i]>R.MAX_SAFE_INTEGER) then - x.array[i+1]=(x.array[i+1] or 0)+1; - x.array[1]=x.array[i]+1; - for j=2,i do - x.array[j]=0; + --l = x:arraySize() + for i, v in pairs(x.array) do + if type(i) == "number" then + if ((x.array[i] or 0)>R.MAX_SAFE_INTEGER) then + x.array[i+1]=(x.array[i+1] or 0)+1; + x.array[1]=x.array[i]+1; + for j=2,i do + x.array[j]=0; + end + b=true; end - b=true; end end end - if (#x.array == 0) then + if (x:arraySize() == 0) then x.array = {0} end return x; end function Big:toString() - if (self.sign==-1) then + if (self.sign==-1) then return "-" .. self:abs():toString() end if (self.array[1] ~= self.array[1]) then - return "NaN" + return "NaN" end -- if (!isFinite(this.array[0])) return "Infinity"; local s = ""; - if (#self.array>=2) then - for i=#self.array,3,-1 do + if (self:arraySize()>=2) then + for i=self:arraySize(),3,-1 do local q = nil if (i >= 6) then q = "{"..(i-1).."}" @@ -311,17 +344,17 @@ function Big:toString() s = s .. string.rep("e", self.array[2]-1) .. AThousandNotation(math.pow(10,self.array[1]-math.floor(self.array[1])), 2) .. "e" .. AThousandNotation(math.floor(self.array[1]), 0); elseif (self.array[2]<8) then s = s .. string.rep("e", self.array[2]) .. AThousandNotation(self.array[1], 0) - else + else s = s .. "(10^)^" .. AThousandNotation(self.array[2], 0) .. " " .. AThousandNotation(self.array[1],0) end return s end -function log10LongString(str) +function log10LongString(str) return math.log(tonumber(string.sub(str, 1, LONG_STRING_MIN_LENGTH)), 10)+(string.len(str)- LONG_STRING_MIN_LENGTH); end -function Big:parse(input) +function Big:parse(input) -- if (typeof input!="string") throw Error(invalidArgument+"Expected String"); -- var isJSON=false; -- if (typeof input=="string"&&(input[0]=="["||input[0]=="{")){ @@ -467,7 +500,7 @@ function Big:parse(input) local decimalPointPos = 1; while ((string.sub(a[i], decimalPointPos, decimalPointPos) ~= ".") and (decimalPointPos <= #a[i])) do decimalPointPos = decimalPointPos + 1 - end + end if decimalPointPos == #a[i] + 1 then decimalPointPos = -1 end @@ -524,15 +557,17 @@ function Big:to_number() if (self.sign==-1) then return -1*(self:neg():to_number()); end - if ((#self.array>=2) and ((self.array[2]>=2) or (self.array[2]==1) and (self.array[1]>308))) then + if not self.array[1] then return 0 end + if self.array[2] == nil then self.array[2] = 0 end + if ((self:arraySize()>=2) and ((self.array[2]>=2) or (self.array[2]==1) and (self.array[1]>308))) then return R.POSITIVE_INFINITY; end - if (#self.array >= 3) and ((self.array[1] >= 3) or (self.array[2] >= 1) or (self.array[3] >= 1)) then + if (self:arraySize() >= 3) and ((self.array[1] >= 3) or (self.array[2] >= 1) or (self.array[3] >= 1)) then return R.POSITIVE_INFINITY; end - if (#self.array >= 4) and ((self.array[1] > 1) or (self.array[2] >= 1) or (self.array[3] >= 1)) then - for i = 4, #self.array do - if self.array[i] > 0 then + if (self:arraySize() >= 4) and ((self.array[1] > 1) or (self.array[2] >= 1) or (self.array[3] >= 1)) then + for i, v in pairs(self.array) do + if self.array[i] > 0 and i > 4 then return R.POSITIVE_INFINITY; end end @@ -547,7 +582,7 @@ function Big:to_number() end function Big:floor() - if (self:isint()) then + if (self:isint(true)) then return self:clone() end return Big:create(math.floor(self:to_number())); @@ -562,7 +597,7 @@ end function Big:clone() local newArr = {} - for i, j in ipairs(self.array) do + for i, j in pairs(self.array) do newArr[i] = j end local result = Big:new(newArr) @@ -582,9 +617,17 @@ function Big:create(input) end end +function Big:ensureBig(input) + if ((type(input) == "table") and getmetatable(input) == OmegaMeta) then + return input + else + return Big:create(input) + end +end + function Big:add(other) - local x = self:clone() - other = Big:create(other) + local x = self + other = Big:ensureBig(other) -- if (OmegaNum.debug>=OmegaNum.NORMAL){ -- console.log(this+"+"+other); -- if (!debugMessageSent) console.warn(omegaNumError+"Debug output via 'debug' is being deprecated and will be removed in the future!"),debugMessageSent=true; @@ -595,33 +638,33 @@ function Big:add(other) if (other.sign==-1) then return x:sub(other:neg()); end - if (x:eq(R.ZERO)) then - return other; + if (x:eq(B.ZERO)) then + return other:clone(); end - if (other:eq(R.ZERO)) then - return x; + if (other:eq(B.ZERO)) then + return x:clone(); end if (x:isNaN() or other:isNaN() or (x:isInfinite() and other:isInfinite() and x:eq(other:neg()))) then - return Big:create(R.NaN); + return Big:create(B.NaN); end if (x:isInfinite()) then - return x; + return x:clone(); end if (other:isInfinite()) then - return other; + return other:clone(); end local p=x:min(other); local q=x:max(other); local t = -1; - if (p.array[2] == 2) and not p:gt(R.E_MAX_SAFE_INTEGER) then + if (p.array[2] == 2) and not p:gt(B.E_MAX_SAFE_INTEGER) then p.array[2] = 1 p.array[1] = 10 ^ p.array[1] end - if (q.array[2] == 2) and not q:gt(R.E_MAX_SAFE_INTEGER) then + if (q.array[2] == 2) and not q:gt(B.E_MAX_SAFE_INTEGER) then q.array[2] = 1 q.array[1] = 10 ^ q.array[1] end - if (q:gt(R.E_MAX_SAFE_INTEGER) or q:div(p):gt(R.MAX_SAFE_INTEGER)) then + if (q:gt(B.E_MAX_SAFE_INTEGER) or q:div(p):gt(B.MAX_SAFE_INTEGER)) then t = q; elseif (q.array[2] == nil) or (q.array[2] == 0) then t= Big:create(x:to_number()+other:to_number()); @@ -639,8 +682,8 @@ function Big:add(other) end function Big:sub(other) - local x = self:clone() - other = Big:create(other) + local x = self + other = Big:ensureBig(other) -- if (OmegaNum.debug>=OmegaNum.NORMAL) console.log(x+"-"+other); if (x.sign==-1) then return x:neg():sub(other:neg()):neg() @@ -649,16 +692,16 @@ function Big:sub(other) return x:add(other:neg()) end if (x:eq(other)) then - return Big:create(R.ZERO) + return Big:create(B.ZERO) end - if (other:eq(R.ZERO)) then - return x; + if (other:eq(B.ZERO)) then + return x:clone(); end if (x:isNaN() or other:isNaN() or (x:isInfinite() and other:isInfinite() and x:eq(other:neg()))) then - return Big:create(R.NaN) + return Big:create(B.NaN) end if (x:isInfinite()) then - return x + return x:clone() end if (other:isInfinite()) then return other:neg() @@ -667,15 +710,15 @@ function Big:sub(other) local q = x:max(other); local n = other:gt(x); local t = -1; - if (p.array[2] == 2) and not p:gt(R.E_MAX_SAFE_INTEGER) then + if (p.array[2] == 2) and not p:gt(B.E_MAX_SAFE_INTEGER) then p.array[2] = 1 p.array[1] = 10 ^ p.array[1] end - if (q.array[2] == 2) and not q:gt(R.E_MAX_SAFE_INTEGER) then + if (q.array[2] == 2) and not q:gt(B.E_MAX_SAFE_INTEGER) then q.array[2] = 1 q.array[1] = 10 ^ q.array[1] end - if (q:gt(R.E_MAX_SAFE_INTEGER) or q:div(p):gt(R.MAX_SAFE_INTEGER)) then + if (q:gt(B.E_MAX_SAFE_INTEGER) or q:div(p):gt(B.MAX_SAFE_INTEGER)) then t = q; if n then t = t:neg() @@ -690,7 +733,7 @@ function Big:sub(other) else a = math.log(p.array[1], 10) end - + t = Big:new({a+math.log(math.pow(10,q.array[1]-a)-1, 10),1}); if n then t = t:neg() @@ -704,10 +747,8 @@ function Big:sub(other) end function Big:div(other) - local x = self:clone(); - other = Big:create(other); - -- if (OmegaNum.debug>=OmegaNum.NORMAL) then - -- console.log(x+"/"+other); + local x = self; + other = Big:ensureBig(other); if (x.sign*other.sign==-1) then return x:abs():div(other:abs()):neg() end @@ -715,28 +756,28 @@ function Big:div(other) return x:abs():div(other:abs()) end if (x:isNaN() or other:isNaN() or (x:isInfinite() and other:isInfinite() and x:eq(other:neg()))) then - return Big:create(R.NaN) + return Big:create(B.NaN) end - if (other:eq(R.ZERO)) then - return Big:create(R.POSITIVE_INFINITY) + if (other:eq(B.ZERO)) then + return Big:create(B.POSITIVE_INFINITY) end - if (other:eq(R.ONE)) then + if (other:eq(B.ONE)) then return x:clone() end if (x:eq(other)) then - return Big:create(R.ONE) + return Big:create(B.ONE) end if (x:isInfinite()) then - return x + return x:clone() end if (other:isInfinite()) then - return Big:create(R.ZERO) + return Big:create(B.ZERO) end - if (x:max(other):gt(R.EE_MAX_SAFE_INTEGER)) then + if (x:max(other):gt(B.EE_MAX_SAFE_INTEGER)) then if x:gt(other) then return x:clone() else - return Big:create(R.ZERO) + return Big:create(B.ZERO) end end local n = x:to_number()/other:to_number(); @@ -752,8 +793,8 @@ function Big:div(other) end function Big:mul(other) - local x = self:clone(); - other = Big:create(other); + local x = Big:ensureBig(self); + other = Big:ensureBig(other); -- if (OmegaNum.debug>=OmegaNum.NORMAL) console.log(x+"*"+other); if (x.sign*other.sign==-1) then return x:abs():mul(other:abs()):neg() @@ -762,21 +803,24 @@ function Big:mul(other) return x:abs():mul(other:abs()) end if (x:isNaN() or other:isNaN() or (x:isInfinite() and other:isInfinite() and x:eq(other:neg()))) then - return Big:create(R.NaN) + return Big:create(B.NaN) end - if (other:eq(R.ZERO)) then - return Big:create(R.ZERO) + if (other:eq(B.ZERO)) or x:eq(B.ZERO) then + return Big:create(B.ZERO) end - if (other:eq(R.ONE)) then + if (other:eq(B.ONE)) then return x:clone() end + if (x:eq(B.ONE)) then + return other:clone() + end if (x:isInfinite()) then - return x + return x:clone() end if (other:isInfinite()) then - return other + return other:clone() end - if (x:max(other):gt(R.EE_MAX_SAFE_INTEGER)) then + if (x:max(other):gt(B.EE_MAX_SAFE_INTEGER)) then return x:max(other) end local n = x:to_number()*other:to_number() @@ -787,83 +831,85 @@ function Big:mul(other) end function Big:rec() - if (self:isNaN() or self:eq(R.ZERO)) then - return Big:create(R.NaN) + if (self:isNaN() or self:eq(B.ZERO)) then + return Big:create(B.NaN) end if (self:abs():gt("2e323")) then - return Big:create(R.ZERO) + return Big:create(B.ZERO) end - return Big:create(R.ONE):div(self) + return Big:create(B.ONE):div(self) end function Big:logBase(base) if base == nil then - base = Big:create(R.E) + base = Big:create(B.E) end return self:log10():div(base:log10()) end function Big:log10() - local x = self:clone(); + local x = self; -- if (OmegaNum.debug>=OmegaNum.NORMAL) console.log("log"+this); - if (x:lt(R.ZERO)) then - return Big:create(R.NaN) + if (x:lt(B.ZERO)) then + return Big:create(B.NaN) end - if (x:eq(R.ZERO)) then - return Big:create(R.NEGATIVE_INFINITY) + if (x:eq(B.ZERO)) then + return Big:create(B.NEGATIVE_INFINITY) end - if (x:lte(R.MAX_SAFE_INTEGER)) then + if (x:lte(B.MAX_SAFE_INTEGER)) then return Big:create(math.log(x:to_number(), 10)) end if (not x:isFinite()) then - return x; + return x:clone(); end - if (x:gt(R.TETRATED_MAX_SAFE_INTEGER)) then - return x; + if (x:gt(B.TETRATED_MAX_SAFE_INTEGER)) then + return x:clone(); end - x.array[2] = x.array[2] - 1; + x = x:clone() + x.array[2] = (x.array[2] or 0) - 1; return x:normalize() end function Big:ln() - base = Big:create(R.E) + base = Big:create(B.E) return self:log10():div(base:log10()) end function Big:pow(other) - other = Big:create(other); + other = Big:ensureBig(other); -- if (OmegaNum.debug>=OmegaNum.NORMAL) console.log(this+"^"+other); - if (other:eq(R.ZERO)) then - return Big:create(R.ONE) + if (other:eq(B.ZERO)) then + return Big:create(B.ONE) end - if (other:eq(R.ONE)) then + if (other:eq(B.ONE)) then return self:clone() end - if (other:lt(R.ZERO)) then + if (other:lt(B.ZERO)) then return self:pow(other:neg()):rec() end - if (self:lt(R.ZERO) and other:isint()) then - if (other:mod(2):lt(R.ONE)) then + if (self:lt(B.ZERO) and other:isint()) then + if (other:mod(2):lt(B.ONE)) then return self:abs():pow(other) end return self:abs():pow(other):neg() end - if (self:lt(R.ZERO)) then - --return Big:create(R.NaN) + if (self:lt(B.ZERO)) then + --return Big:create(B.NaN) --Override this interaction to always make positive numbers return self:abs():pow(other) end - if (self:eq(R.ONE)) then - return Big:create(R.ONE) + if (self:eq(B.ONE)) then + return Big:create(B.ONE) end - if (self:eq(R.ZERO)) then - return Big:create(R.ZERO) + if (self:eq(B.ZERO)) then + return Big:create(B.ZERO) end - if (self:max(other):gt(R.TETRATED_MAX_SAFE_INTEGER)) then + if (self:max(other):gt(B.TETRATED_MAX_SAFE_INTEGER)) then return self:max(other); end if (self:eq(10)) then - if (other:gt(R.ZERO)) then + if (other:gt(B.ZERO)) then + other = other:clone(); other.array[2] = (other.array[2] or 0) + 1; other:normalize(); return other; @@ -871,7 +917,7 @@ function Big:pow(other) return Big:create(math.pow(10,other:to_number())); end end - if (other:lt(R.ONE)) then + if (other:lt(B.ONE)) then return self:root(other:rec()) end local n = math.pow(self:to_number(),other:to_number()) @@ -882,38 +928,38 @@ function Big:pow(other) end function Big:exp() - return Big:create(R.E, self) + return Big:create(B.E, self) end function Big:root(other) - other = Big:create(other) + other = Big:ensureBig(other) -- if (OmegaNum.debug>=OmegaNum.NORMAL) console.log(this+"root"+other); - if (other:eq(R.ONE)) then + if (other:eq(B.ONE)) then return self:clone() end - if (other:lt(R.ZERO)) then + if (other:lt(B.ZERO)) then return self:root(other:neg()):rec() end - if (other:lt(R.ONE)) then + if (other:lt(B.ONE)) then return self:pow(other:rec()) end - if (self:lt(R.ZERO) and other:isint() and other:mod(2):eq(R.ONE)) then + if (self:lt(B.ZERO) and other:isint() and other:mod(2):eq(B.ONE)) then return self:neg():root(other):neg() end - if (self:lt(R.ZERO)) then - return Big:create(R.NaN) + if (self:lt(B.ZERO)) then + return Big:create(B.NaN) end - if (self:eq(R.ONE)) then - return Big:create(R.ONE) + if (self:eq(B.ONE)) then + return Big:create(B.ONE) end - if (self:eq(R.ZERO)) then - return Big:create(R.ZERO) + if (self:eq(B.ZERO)) then + return Big:create(B.ZERO) end - if (self:max(other):gt(R.TETRATED_MAX_SAFE_INTEGER)) then + if (self:max(other):gt(B.TETRATED_MAX_SAFE_INTEGER)) then if self:gt(other) then return self:clone() else - Big:create(R.ZERO) + Big:create(B.ZERO) end end return Big:create(10):pow(self:log10():div(other)); @@ -923,49 +969,51 @@ function Big:slog(base) if base == nil then base = 10 end - local x = Big:create(self) - base = Big:create(base) + local x = self + base = Big:ensureBig(base) if (x:isNaN() or base:isNaN() or (x:isInfinite() and base:isInfinite())) then - return Big:create(R.NaN) + return Big:create(B.NaN) end if (x:isInfinite()) then - return x; + return x:clone(); end if (base:isInfinite()) then - return Big:create(R.ZERO) + return Big:create(B.ZERO) end - if (x:lt(R.ZERO)) then + if (x:lt(B.ZERO)) then return Big:create(-R.ONE) end - if (x:lt(R.ONE)) then - return Big:create(R.ZERO) + if (x:lt(B.ONE)) then + return Big:create(B.ZERO) end if (x:eq(base)) then - return Big:create(R.ONE) + return Big:create(B.ONE) end if (base:lt(math.exp(1/R.E))) then local a = base:tetrate(1/0) if (x:eq(a)) then - return Big:create(R.POSITIVE_INFINITY) + return Big:create(B.POSITIVE_INFINITY) end if (x:gt(a)) then - return Big:create(R.NaN) + return Big:create(B.NaN) end end if (x:max(base):gt("10^^^" .. R.MAX_SAFE_INTEGER)) then if (x:gt(base)) then - return x; + return x:clone(); end - return Big:create(R.ZERO) + return Big:create(B.ZERO) end - if (x:max(base):gt(R.TETRATED_MAX_SAFE_INTEGER)) then + if (x:max(base):gt(B.TETRATED_MAX_SAFE_INTEGER)) then if x:gt(base) then - x.array[3] = x.array[3] - 1 + x = x:clone() + x.array[3] = (x.array[3] or 0) - 1 x:normalize() return x:sub(x.array[2]) end - return Big:create(R.ZERO) + return Big:create(B.ZERO) end + x = x:clone() local r = 0 local t = (x.array[2] or 0) - (base.array[2] or 0) if (t > 3) then @@ -974,10 +1022,10 @@ function Big:slog(base) x.array[2] = x.array[2] - l end for i = 0, 99 do - if x:lt(R.ZERO) then + if x:lt(B.ZERO) then x = base:pow(x) r = r - 1 - elseif (x:lte(R.ONE)) then + elseif (x:lte(B.ONE)) then return Big:create(r + x:to_number() - 1) else r = r + 1 @@ -990,42 +1038,43 @@ function Big:slog(base) end function Big:tetrate(other) - local t = self:clone() - other = Big:create(other) + local t = self + if other == 1 then return Big:create(self) end + other = Big:ensureBig(other) local negln = nil if (t:isNaN() or other:isNaN()) then - return Big:create(R.NaN) + return Big:create(B.NaN) end if (other:isInfinite() and other.sign > 0) then negln = t:ln():neg() return negln:lambertw():div(negln) end if (other:lte(-2)) then - return Big:create(R.NaN) + return Big:create(B.NaN) end - if (t:eq(R.ZERO)) then - if (other:eq(R.ZERO)) then - return Big:create(R.NaN) + if (t:eq(B.ZERO)) then + if (other:eq(B.ZERO)) then + return Big:create(B.NaN) end - if (other:mod(2):eq(R.ZERO)) then - return Big:create(R.ZERO) + if (other:mod(2):eq(B.ZERO)) then + return Big:create(B.ZERO) end - return Big:create(R.ONE) + return Big:create(B.ONE) end - if (t:eq(R.ONE)) then + if (t:eq(B.ONE)) then if (other:eq(-1)) then - return Big:create(R.NaN) + return Big:create(B.NaN) end - return Big:create(R.ONE) + return Big:create(B.ONE) end if (other:eq(-1)) then - return Big:create(R.ZERO) + return Big:create(B.ZERO) end - if other:eq(R.ZERO) then - return Big:create(R.ONE) + if other:eq(B.ZERO) then + return Big:create(B.ONE) end - if other:eq(R.ONE) then - return t + if other:eq(B.ONE) then + return t:clone() end if other:eq(2) then return t:pow(t) @@ -1042,7 +1091,7 @@ function Big:tetrate(other) if (m:gt(Big:create("10^^^" .. tostring(R.MAX_SAFE_INTEGER)))) then return m end - if (m:gt(R.TETRATED_MAX_SAFE_INTEGER) or other:gt(MAX_SAFE_INTEGER)) then + if (m:gt(B.TETRATED_MAX_SAFE_INTEGER) or other:gt(R.MAX_SAFE_INTEGER)) then if (t:lt(math.exp(1/R.E))) then negln = t:ln():neg() return negln:lambertw():div(negln) @@ -1055,9 +1104,9 @@ function Big:tetrate(other) local y = other:to_number() local f = math.floor(y) local r = t:pow(y-f) - local l = Big:create(R.NaN) + local l = B.NaN local i = 0 - local m = Big:create(R.E_MAX_SAFE_INTEGER) + local m = B.E_MAX_SAFE_INTEGER while ((f ~= 0) and r:lt(m) and (i < 100)) do if (f > 0) then r = t:pow(r) @@ -1085,51 +1134,119 @@ function Big:tetrate(other) return r; end +function Big:max_for_op(arrows) + if type(arrows) == "table" then + arrows = arrows:to_number() + end + if arrows < 1 or arrows ~= arrows or arrows == R.POSITIVE_INFINITY then + return B.NaN:clone() + end + if arrows == 1 then + return B.E_MAX_SAFE_INTEGER:clone() + end + if arrows == 2 then + return B.TETRATED_MAX_SAFE_INTEGER:clone() + end + + local arr = {} + arr[1] = 10e9 + arr[arrows] = R.MAX_SAFE_INTEGER - 2 + for i = 2, math.min(arrows - 1, 1e6) do + arr[i] = 8 + end + if arrows > 1e6 then + local limit = math.floor(math.log(arrows, 10)) + for i = 6, limit do + arr[10^i] = 8 + end + end + arr[arrows - 1] = 8 + + local res = Big:new({0}) + res.array = arr + return res +end + function Big:arrow(arrows, other) local t = self:clone() - arrows = Big:create(arrows) - if (not arrows:isint() or arrows:lt(R.ZERO)) then - return Big:create(R.NaN) + local oldarrows = Big:ensureBig(arrows) + if oldarrows > Big:ensureBig(1e308) then --if too big return infinity + return Big:create(R.POSITIVE_INFINITY) end - if arrows:eq(R.ZERO) then + oldarrows = oldarrows:to_number() + arrows = Big:ensureBig(arrows) + if oldarrows >= 1e6 then --needed to stop "Infinity" + arrows = arrows:floor() + end + if oldarrows == 1 then + return Big:create(self) + end + if self:eq(B.ONE) then return 1 end + if self:eq(B.ZERO) then return 0 end + --idk why but arrows above 1e6 just sometimes randomly get treated as non ints even though they are + --this is technically inaccurate now but i think 1e7 +0.1 counting as an integer amount of arrow here is fine + if (not arrows:isint() or arrows:lt(B.ZERO)) and arrows:lt(1e6) then + return Big:create(B.NaN) + end + if type(oldarrows) == "number" and oldarrows ~= math.floor(oldarrows) and oldarrows < 1e6 then + return Big:create(B.NaN) + end + if arrows:eq(B.ZERO) then return t:mul(other) end - if arrows:eq(R.ONE) then - return t:pow(other) + if arrows:eq(B.ONE) or oldarrows == 1 then + return t ^ other--t:pow(other) idk why this was causing issues but it was so now theres this end - if arrows:eq(2) then + if arrows:eq(2) or oldarrows == 2 then return t:tetrate(other) end other = Big:create(other) - if (other:lt(R.ZERO)) then - return Big:create(R.NaN) + if (other:lt(B.ZERO)) then + return Big:create(B.NaN) end - if (other:eq(R.ZERO)) then - return Big:create(R.ONE) + if (other:eq(B.ZERO)) then + return Big:create(B.ONE) end - if (other:eq(R.ONE)) then + if (other:eq(B.ONE)) then return t:clone() end --[[if (arrows:gte(maxArrow)) then - return Big:create(R.POSITIVE_INFINITY) + return Big:create(B.POSITIVE_INFINITY) end--]] - local arrowsNum = arrows:to_number() + + --remove potential error from before + local arrowsNum = math.floor(oldarrows) if (other:eq(2)) then - return t:arrow(arrows:sub(R.ONE), t) + return t:arrow(arrowsNum - 1, t) end - if (t:max(other):gt("10{"..tostring(arrowsNum+1).."}"..tostring(R.MAX_SAFE_INTEGER))) then + local limit_plus = Big:max_for_op(arrowsNum+1) + local limit = Big:max_for_op(arrowsNum) + local limit_minus = Big:max_for_op(arrowsNum-1) + if (t:max(other):gt(limit_plus)) then return t:max(other) end local r = nil - if (t:gt("10{"..tostring(arrowsNum).."}"..tostring(R.MAX_SAFE_INTEGER)) or other:gt(R.MAX_SAFE_INTEGER)) then - if (t:gt("10{"..tostring(arrowsNum).."}"..tostring(R.MAX_SAFE_INTEGER))) then + -- if arrows >= Big:ensureBig(3500) then + -- if self:arrow(100, self) > other then + -- return Big:new({ + -- [1] = math.min(to_number(math.log(other, 10)), 1e300), + -- [2] = 0, + -- [3] = 0, + -- [to_number(arrows)+1] = 1 + -- }) + -- end + -- end + if (t:gt(limit) or other:gt(B.MAX_SAFE_INTEGER)) or arrows >= Big:ensureBig(350) then --just kinda chosen randomly + if (t:gt(limit)) then r = t:clone() r.array[arrowsNum + 1] = r.array[arrowsNum + 1] - 1 - r:normalize() - elseif (t:gt("10{"..tostring(arrowsNum - 1).."}"..tostring(R.MAX_SAFE_INTEGER))) then + if arrowsNum < 25000 then --arbitrary, normalisation is just extra steps when you get high enough + r:normalize() + end + elseif (t:gt(limit_minus)) then r = Big:create(t.array[arrowsNum]) else - r = Big:create(R.ZERO) + r = Big:create(B.ZERO) end local j = r:add(other) j.array[arrowsNum+1] = (j.array[arrowsNum+1] or 0) + 1 @@ -1138,9 +1255,9 @@ function Big:arrow(arrows, other) end local y = other:to_number() local f = math.floor(y) - local arrows_m1 = arrows:sub(R.ONE) + local arrows_m1 = arrows:sub(B.ONE) local i = 0 - local m = Big:create("10{"..tostring(arrowsNum - 1).."}"..tostring(R.MAX_SAFE_INTEGER)) + local m = limit_minus r = t:arrow(arrows_m1, y-f) while (f ~= 0) and r:lt(m) and (i<100) do if (f > 0) then @@ -1158,9 +1275,9 @@ function Big:arrow(arrows, other) end function Big:mod(other) - other = Big:create(other) - if (other:eq(R.ZERO)) then - Big:create(R.ZERO) + other = Big:ensureBig(other) + if (other:eq(B.ZERO)) then + Big:create(B.ZERO) end if (self.sign*other.sign == -1) then return self:abs():mod(other:abs()):neg() @@ -1172,23 +1289,23 @@ function Big:mod(other) end function Big:lambertw() - local x = self:clone() + local x = self if (x:isNaN()) then - return x; + return x:clone(); end if (x:lt(-0.3678794411710499)) then print("lambertw is unimplemented for results less than -1, sorry!") local a = nil return a.b end - if (x:gt(R.TETRATED_MAX_SAFE_INTEGER)) then - return x; + if (x:gt(B.TETRATED_MAX_SAFE_INTEGER)) then + return x:clone(); end - if (x:gt(R.EE_MAX_SAFE_INTEGER)) then + if (x:gt(B.EE_MAX_SAFE_INTEGER)) then x.array[1] = x.array[1] - 1 - return x; + return x:clone(); end - if (x:gt(R.E_MAX_SAFE_INTEGER)) then + if (x:gt(B.E_MAX_SAFE_INTEGER)) then return Big:d_lambertw(x) else return Big:create(Big:f_lambertw(x.sign*x.array[1])) @@ -1200,7 +1317,7 @@ function Big:f_lambertw(z) local w = nil local wn = nil local OMEGA = 0.56714329040978387299997 - if (not Big:create(z):isFinite()) then + if (not Big:ensureBig(z):isFinite()) then return z; end if z == 0 then @@ -1228,17 +1345,17 @@ end function Big:d_lambertw(z) local tol = 1e-10 - z = Big:create(z) + z = Big:ensureBig(z) local w = nil local ew = nil local wewz = nil local wn = nil local OMEGA = 0.56714329040978387299997 if (not z:isFinite()) then - return z; + return z:clone(); end if (z == 0) then - return z + return z:clone(); end if (z == 1) then return OMEGA @@ -1247,7 +1364,7 @@ function Big:d_lambertw(z) for i=0, 99 do ew = w:neg():exp() wewz = w:sub(z:mul(ew)) - wn = w:sub(wewz:div(w:add(R.ONE):sub((w:add(2)):mul(wewz):div((w:mul(2):add(2)))))) + wn = w:sub(wewz:div(w:add(B.ONE):sub((w:add(2)):mul(wewz):div((w:mul(2):add(2)))))) if (wn:sub(w):abs():lt(wn:abs():mul(tol))) then return wn end @@ -1261,29 +1378,29 @@ end ------------------------metastuff---------------------------- function OmegaMeta.__add(b1, b2) - if type(b1) == "number" then + if type(b1) == "number" then return Big:create(b1):add(b2) end return b1:add(b2) end function OmegaMeta.__sub(b1, b2) - if type(b1) == "number" then - return Big:create(b1):sub(b2) + if type(b1) == "number" then + return Big:create(b1):sub(b2) end return b1:sub(b2) end function OmegaMeta.__mul(b1, b2) - if type(b1) == "number" then - return Big:create(b1):mul(b2) + if type(b1) == "number" then + return Big:create(b1):mul(b2) end return b1:mul(b2) end function OmegaMeta.__div(b1, b2) - if type(b1) == "number" then - return Big:create(b1):div(b2) + if type(b1) == "number" then + return Big:create(b1):div(b2) end return b1:div(b2) end @@ -1299,34 +1416,34 @@ function OmegaMeta.__unm(b) end function OmegaMeta.__pow(b1, b2) - if type(b1) == "number" then - return Big:create(b1):pow(b2) + if type(b1) == "number" then + return Big:ensureBig(b1):pow(b2) end return b1:pow(b2) end function OmegaMeta.__le(b1, b2) - b1 = Big:create(b1) + b1 = Big:ensureBig(b1) return b1:lte(b2) end function OmegaMeta.__lt(b1, b2) - b1 = Big:create(b1) + b1 = Big:ensureBig(b1) return b1:lt(b2) end function OmegaMeta.__ge(b1, b2) - b1 = Big:create(b1) + b1 = Big:ensureBig(b1) return b1:gte(b2) end function OmegaMeta.__gt(b1, b2) - b1 = Big:create(b1) + b1 = Big:ensureBig(b1) return b1:gt(b2) end function OmegaMeta.__eq(b1, b2) - b1 = Big:create(b1) + b1 = Big:ensureBig(b1) return b1:eq(b2) end @@ -1335,12 +1452,17 @@ function OmegaMeta.__tostring(b) end function OmegaMeta.__concat(a, b) - a = Big:create(a) + a = Big:ensureBig(a) return tostring(a) .. tostring(b) end --------------------------------------- +for i,v in pairs(R) do + B[i] = Big:ensureBig(v) +end + return Big + diff --git a/Talisman/config.lua b/Talisman/config.lua new file mode 100644 index 0000000..0f706ea --- /dev/null +++ b/Talisman/config.lua @@ -0,0 +1 @@ +return {["disable_anims"]=false,["score_opt_id"]=3,["break_infinity"]="omeganum",} \ No newline at end of file diff --git a/Talisman/localization/en-us.lua b/Talisman/localization/en-us.lua new file mode 100644 index 0000000..9984c07 --- /dev/null +++ b/Talisman/localization/en-us.lua @@ -0,0 +1,29 @@ +return { + descriptions = { + Mod = { + Talisman = { + name = "Talisman", + text = {"A mod that increases Balatro's score limit and skips scoring animations."}, + } + } + }, + test = "j", + talisman_vanilla = 'Vanilla (e308)', + talisman_bignum = 'BigNum (ee308)', + talisman_omeganum = 'OmegaNum', + + talisman_string_A = 'Select features to enable:', + talisman_string_B = 'Disable Scoring Animations', + talisman_string_C = 'Score Limit (requires game restart)', + talisman_string_D = 'Calculating...', + talisman_string_E = 'Abort', + talisman_string_F = 'Elapsed calculations: ', + talisman_string_G = 'Cards yet to score: ', + talisman_string_H = 'Calculations last played hand: ', + talisman_string_I = 'Unknown', + + --These don't work out of the box because they would be called too early, find a workaround later? + talisman_error_A = 'Could not find proper Talisman folder. Please make sure the folder for Talisman is named exactly "Talisman" and not "Talisman-main" or anything else.', + talisman_error_B = '[Talisman] Error unpacking string: ', + talisman_error_C = '[Talisman] Error loading string: ' +} diff --git a/Talisman/localization/fr.lua b/Talisman/localization/fr.lua new file mode 100644 index 0000000..262f417 --- /dev/null +++ b/Talisman/localization/fr.lua @@ -0,0 +1,29 @@ +return { + descriptions = { + Mod = { + Talisman = { + name = "Talisman", + text = {"A mod that increases Balatro's score limit and skips scoring animations."}, + } + } + }, + test = "q", + talisman_vanilla = 'Vanilla (e308)', + talisman_bignum = 'BigNum (ee308)', + talisman_omeganum = 'OmegaNum', + + talisman_string_A = 'Select features to enable:', + talisman_string_B = 'Disable Scoring Animations', + talisman_string_C = 'Score Limit (requires game restart)', + talisman_string_D = 'Calculating...', + talisman_string_E = 'Abort', + talisman_string_F = 'Elapsed calculations: ', + talisman_string_G = 'Cards yet to score: ', + talisman_string_H = 'Calculations last played hand: ', + talisman_string_I = 'Unknown', + + --These don't work out of the box because they would be called too early, find a workaround later? + talisman_error_A = 'Could not find proper Talisman folder. Please make sure the folder for Talisman is named exactly "Talisman" and not "Talisman-main" or anything else.', + talisman_error_B = '[Talisman] Error unpacking string: ', + talisman_error_C = '[Talisman] Error loading string: ', +} diff --git a/Talisman/localization/vi.lua b/Talisman/localization/vi.lua new file mode 100644 index 0000000..ca905d3 --- /dev/null +++ b/Talisman/localization/vi.lua @@ -0,0 +1,29 @@ +return { + descriptions = { + Mod = { + Talisman = { + name = "Talisman", + text = {"Một mod tăng giới hạn điểm của Balatro và bỏ qua hoạt ảnh ghi điểm."}, + }, + } + }, + test = "j", + talisman_vanilla = 'Gốc (e308)', + talisman_bignum = 'BigNum (ee308)', + talisman_omeganum = 'OmegaNum', + + talisman_string_A = 'Chọn tính năng để bật:', + talisman_string_B = 'Tắt Hoạt Ảnh Ghi Điểm', + talisman_string_C = 'Giới Hạn Điểm (yêu cầu khởi động lại)', + talisman_string_D = 'Đang tính toán...', + talisman_string_E = 'Huỷ bỏ', + talisman_string_F = 'Phép tính đã thực hiện: ', + talisman_string_G = 'Số lá chưa ghi điểm: ', + talisman_string_H = 'Phép tính tay bài trước đó: ', + talisman_string_I = 'Không rõ', + + --These don't work out of the box because they would be called too early, find a workaround later? + talisman_error_A = 'Could not find proper Talisman folder. Please make sure the folder for Talisman is named exactly "Talisman" and not "Talisman-main" or anything else.', + talisman_error_B = '[Talisman] Error unpacking string: ', + talisman_error_C = '[Talisman] Error loading string: ' +} diff --git a/Talisman/lovely.toml b/Talisman/lovely.toml index e13d028..00359e2 100644 --- a/Talisman/lovely.toml +++ b/Talisman/lovely.toml @@ -19,7 +19,6 @@ pattern = "replace_card.states.visible = false" position = "before" payload = "replace_card:set_seal('Gold', true, true)" match_indent = true -overwrite = false [[patches]] [patches.module] @@ -35,7 +34,6 @@ pattern = "{n=G.UIT.T, config={text = G.GAME.hands[handname].chips, scale = 0.45 position = "at" payload = "{n=G.UIT.T, config={text = number_format(G.GAME.hands[handname].chips, 1000000), scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}," match_indent = true -overwrite = true [[patches]] [patches.pattern] @@ -44,7 +42,6 @@ pattern = "{n=G.UIT.T, config={text = G.GAME.hands[handname].mult, scale = 0.45, position = "at" payload = "{n=G.UIT.T, config={text = number_format(G.GAME.hands[handname].mult, 1000000), scale = 0.45, colour = G.C.UI.TEXT_LIGHT}}" match_indent = true -overwrite = true # Chip requirements for achievements/unlocks [[patches]] @@ -54,7 +51,6 @@ pattern = "if args.chips >= 10000 then" position = "at" payload = "if to_big(args.chips) >= to_big(10000) then" match_indent = true -overwrite = true [[patches]] [patches.pattern] @@ -63,7 +59,6 @@ pattern = "if args.chips >= 1000000 then" position = "at" payload = "if to_big(args.chips) >= to_big(1000000) then" match_indent = true -overwrite = true [[patches]] [patches.pattern] @@ -72,7 +67,6 @@ pattern = "if args.chips >= 100000000 then" position = "at" payload = "if to_big(args.chips) >= to_big(100000000) then" match_indent = true -overwrite = true [[patches]] [patches.pattern] @@ -81,7 +75,6 @@ pattern = "if card.unlock_condition.chips <= args.chips then" position = "at" payload = "if to_big(card.unlock_condition.chips) <= to_big(args.chips) then" match_indent = true -overwrite = true # More comparison issues [[patches]] @@ -91,7 +84,6 @@ pattern = "if hand_chips*mult > 0 then" position = "at" payload = "if to_big(hand_chips)*mult > to_big(0) then" match_indent = true -overwrite = true [[patches]] [patches.pattern] @@ -100,7 +92,6 @@ pattern = "if G.GAME.current_round.current_hand.chip_total < 1 then" position = "at" payload = "if to_big(G.GAME.current_round.current_hand.chip_total) < to_big(1) then" match_indent = true -overwrite = true [[patches]] [patches.pattern] @@ -109,7 +100,6 @@ pattern = "ease_chips(0)" position = "at" payload = "ease_chips(to_big(0))" match_indent = true -overwrite = true [[patches]] [patches.pattern] @@ -118,7 +108,6 @@ pattern = "chips = 0," position = "at" payload = "chips = to_big(0)," match_indent = true -overwrite = true # Patch for Steamodded Sound API [[patches]] @@ -128,7 +117,6 @@ pattern = "G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensit position = "at" payload = "G.ARGS.score_intensity.organ = G.video_organ or to_big(G.ARGS.score_intensity.required_score) > to_big(0) and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0" match_indent = true -overwrite = true [[patches]] [patches.pattern] @@ -137,7 +125,6 @@ pattern = "G.ARGS.score_intensity.organ = G.video_organ or G.ARGS.score_intensit position = "at" payload = "G.ARGS.score_intensity.organ = G.video_organ or to_big(G.ARGS.score_intensity.required_score) > to_big(0) and math.max(math.min(0.4, 0.1*math.log(G.ARGS.score_intensity.earned_score/(G.ARGS.score_intensity.required_score+1), 5)),0.) or 0" match_indent = true -overwrite = true [[patches]] [patches.pattern] @@ -146,7 +133,6 @@ pattern = "if G.ARGS.score_intensity.earned_score >= G.ARGS.score_intensity.requ position = "at" payload = "if to_big(G.ARGS.score_intensity.earned_score) >= to_big(G.ARGS.score_intensity.required_score) and to_big(G.ARGS.score_intensity.required_score) > to_big(0) then" match_indent = true -overwrite = true [[patches]] [patches.pattern] @@ -155,7 +141,6 @@ pattern = "if G.GAME.chips - G.GAME.blind.chips >= 0 or G.GAME.current_round.han position = "at" payload = '''if to_big(G.GAME.chips) >= to_big(G.GAME.blind.chips) or G.GAME.current_round.hands_left < 1 then''' match_indent = true -overwrite = true [[patches]] [patches.pattern] @@ -164,7 +149,6 @@ pattern = "if G.GAME.chips - G.GAME.blind.chips >= 0 then" position = "at" payload = "if to_big(G.GAME.chips) >= to_big(G.GAME.blind.chips) then" match_indent = true -overwrite = true [[patches]] [patches.pattern] @@ -173,7 +157,6 @@ pattern = "if self.boss and G.GAME.chips - G.GAME.blind.chips >= 0 then" position = "at" payload = "if self.boss and to_big(G.GAME.chips) - G.GAME.blind.chips >= to_big(0) then" match_indent = true -overwrite = true [[patches]] [patches.pattern] @@ -182,25 +165,38 @@ pattern = "G.GAME.chips/G.GAME.blind.chips >= 0.25 then" position = "at" payload = "to_big(G.GAME.chips)/G.GAME.blind.chips >= to_big(0.25) then" match_indent = true -overwrite = true [[patches]] [patches.pattern] target = "functions/button_callbacks.lua" pattern = "if not G.TAROT_INTERRUPT_PULSE then G.FUNCS.text_super_juice(e, math.max(0,math.floor(math.log10(type(G.GAME.current_round.current_hand.mult) == 'number' and G.GAME.current_round.current_hand.mult or 1)))) end" position = "at" -payload = "if not G.TAROT_INTERRUPT_PULSE then G.FUNCS.text_super_juice(e, math.min(2,math.max(0,math.floor(math.log10(is_number(G.GAME.current_round.current_hand.mult) and G.GAME.current_round.current_hand.mult or 1))))) end" +payload = ''' +local num = 0 +if to_big(is_number(G.GAME.current_round.current_hand.mult) and G.GAME.current_round.current_hand.mult or 1) > to_big(1e300) then + num = math.min(2,math.max(0,math.floor(math.log10(is_number(G.GAME.current_round.current_hand.mult) and G.GAME.current_round.current_hand.mult or 1)))) +else + num = 1e300 +end +if not G.TAROT_INTERRUPT_PULSE then G.FUNCS.text_super_juice(e, num) end +''' match_indent = true -overwrite = true [[patches]] [patches.pattern] target = "functions/button_callbacks.lua" pattern = "if not G.TAROT_INTERRUPT_PULSE then G.FUNCS.text_super_juice(e, math.max(0,math.floor(math.log10(type(G.GAME.current_round.current_hand.chips) == 'number' and G.GAME.current_round.current_hand.chips or 1)))) end" position = "at" -payload = "if not G.TAROT_INTERRUPT_PULSE then G.FUNCS.text_super_juice(e, math.min(2,math.max(0,math.floor(math.log10(is_number(G.GAME.current_round.current_hand.chips) and G.GAME.current_round.current_hand.chips or 1))))) end" +payload = ''' +local num = 0 +if to_big(is_number(G.GAME.current_round.current_hand.chips) and G.GAME.current_round.current_hand.chips or 1) > to_big(1e300) then + num = math.min(2,math.max(0,math.floor(math.log10(is_number(G.GAME.current_round.current_hand.chips) and G.GAME.current_round.current_hand.chips or 1)))) +else + num = 1e300 +end +if not G.TAROT_INTERRUPT_PULSE then G.FUNCS.text_super_juice(e, num) end +''' match_indent = true -overwrite = true [[patches]] [patches.pattern] @@ -209,7 +205,6 @@ pattern = "if type(G.GAME.current_round.current_hand.chips) ~= 'number' or type( position = "at" payload = "if not is_number(G.GAME.current_round.current_hand.chips) or not is_number(G.GAME.current_round.current_hand.mult) then" match_indent = true -overwrite = true [[patches]] [patches.pattern] @@ -218,7 +213,6 @@ pattern = "if type(G.GAME.current_round.current_hand.chips) ~= 'number' or type( position = "at" payload = "if not is_number(G.GAME.current_round.current_hand.chips) or not is_number(G.GAME.current_round.current_hand.mult) then" match_indent = true -overwrite = true [[patches]] [patches.pattern] @@ -227,7 +221,6 @@ pattern = "local delta = (type(vals.chips) == 'number' and type(G.GAME.current_r position = "at" payload = "local delta = (is_number(vals.chips) and is_number(G.GAME.current_round.current_hand.chips)) and (vals.chips - G.GAME.current_round.current_hand.chips) or 0" match_indent = true -overwrite = true [[patches]] [patches.pattern] @@ -236,7 +229,6 @@ pattern = "local delta = (type(vals.mult) == 'number' and type(G.GAME.current_ro position = "at" payload = "local delta = (is_number(vals.mult) and is_number(G.GAME.current_round.current_hand.mult))and (vals.mult - G.GAME.current_round.current_hand.mult) or 0" match_indent = true -overwrite = true [[patches]] [patches.pattern] @@ -245,7 +237,6 @@ pattern = "if delta < 0 then delta = ''..delta; col = G.C.RED" position = "at" payload = "if to_big(delta) < to_big(0) then delta = number_format(delta); col = G.C.RED" match_indent = true -overwrite = true [[patches]] [patches.pattern] @@ -254,7 +245,6 @@ pattern = "elseif delta > 0 then delta = '+'..delta" position = "at" payload = "elseif to_big(delta) > to_big(0) then delta = '+'..number_format(delta)" match_indent = true -overwrite = true [[patches]] [patches.pattern] @@ -263,7 +253,6 @@ pattern = "else delta = ''..delta" position = "at" payload = "else delta = number_format(delta)" match_indent = true -overwrite = true [[patches]] [patches.pattern] @@ -275,14 +264,13 @@ if v.m and v.e then v = "to_big("..v.m..","..v.e..")" elseif v.array and v.sign then local v0 = "to_big({" - for qi = 1,#v.array do - v0 = v0 .. v.array[qi] .. ", " + for i, v in pairs(v.array) do + v0 = v0 .. ("["..i.."] = "..(v or 0)) .. ", " end v0 = v0 .. "},"..v.sign..")" v = v0 ''' match_indent = true -overwrite = false [[patches]] [patches.pattern] @@ -291,7 +279,6 @@ pattern = 'if v.is and v:is(Object) then' position = "at" payload = 'elseif v.is and v:is(Object) then' match_indent = true -overwrite = true [[patches]] [patches.pattern] @@ -300,7 +287,6 @@ pattern = "{n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.GAME. position = "at" payload = "{n=G.UIT.O, config={object = DynaText({string = {{ref_table = G.GAME.round_resets, ref_value = 'ante_disp'}}, colours = {G.C.IMPORTANT},shadow = true, font = G.LANGUAGES['en-us'].font, scale = scale_number(G.GAME.round_resets.ante, 2*scale, 100)}),id = 'ante_UI_count'}},--{n=G.UIT.T, config={text = number_format(G.GAME.round_resets.ante), lang = G.LANGUAGES['en-us'], scale = scale_number(G.GAME.round_resets.ante, 2*scale, 100), colour = G.C.IMPORTANT, shadow = true,id = 'ante_UI_count'}}," match_indent = true -overwrite = true [[patches]] [patches.pattern] @@ -309,7 +295,6 @@ pattern = "ante = 1," position = "after" payload = "ante_disp = number_format(1)," match_indent = true -overwrite = false [[patches]] [patches.pattern] @@ -318,7 +303,6 @@ pattern = "G.GAME.round_resets.ante = G.GAME.round_resets.ante + mod" position = "after" payload = "G.GAME.round_resets.ante_disp = number_format(G.GAME.round_resets.ante)" match_indent = true -overwrite = false [[patches]] [patches.pattern] @@ -327,27 +311,24 @@ pattern = "if not G.ARGS.hand_chip_total_UI_set or G.ARGS.hand_chip_total_UI_set position = "at" payload = "if not G.ARGS.hand_chip_total_UI_set or to_big(G.ARGS.hand_chip_total_UI_set) < to_big(G.GAME.current_round.current_hand.chip_total) then" match_indent = true -overwrite = true - # For some reason Big leaks into the text engine, this mitigates it [[patches]] -[patches.pattern] +[patches.regex] target = "engine/text.lua" -pattern = "if self.strings[k].W > self.config.W then self.config.W = self.strings[k].W; self.strings[k].W_offset = 0 end" +pattern = '''(?[\t ]*)if self\.strings\[k\]\.W > self\.config\.W then''' position = "before" +line_prepend = "$indent" payload = ''' if Big then if type(self.strings[k].W) == 'table' then - self.strings[k].W = self.strings[k].W:to_number() + self.strings[k].W = to_number(self.strings[k].W) end if type(self.strings[k].H) == 'table' then - self.strings[k].H = self.strings[k].H:to_number() + self.strings[k].H = to_number(self.strings[k].H) end end ''' -match_indent = true -overwrite = false [[patches]] [patches.pattern] @@ -356,28 +337,41 @@ pattern = "function DynaText:draw()" position = "after" payload = ''' if Big then - self.scale = to_big(self.scale):to_number() - if self.shadow_parallax then self.shadow_parallax.x = to_big(self.shadow_parallax.x):to_number() end + self.scale = to_number(self.scale) + if self.shadow_parallax then self.shadow_parallax.x = to_number(self.shadow_parallax.x) end end ''' match_indent = true -overwrite = false [[patches]] [patches.pattern] target = "engine/text.lua" pattern = "for k, letter in ipairs(self.strings[self.focused_string].letters) do" -position = "after" +position = "after" # old DynaText backward compat payload = ''' if Big then - letter.dims.x = to_big(letter.dims.x):to_number() - letter.dims.y = to_big(letter.dims.y):to_number() - letter.offset.x = to_big(letter.offset.x):to_number() - letter.offset.y = to_big(letter.offset.y):to_number() + letter.dims.x = to_number(letter.dims.x) + letter.dims.y = to_number(letter.dims.y) + letter.offset.x = to_number(letter.offset.x) + letter.offset.y = to_number(letter.offset.y) +end +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = "engine/text.lua" +pattern = "local letter = self.strings[self.focused_string].letters[k]" +position = "after" # This is for Aiko's new mod menu interference with DynaText +payload = ''' +if Big then + letter.dims.x = to_number(letter.dims.x) + letter.dims.y = to_number(letter.dims.y) + letter.offset.x = to_number(letter.offset.x) + letter.offset.y = to_number(letter.offset.y) end ''' match_indent = true -overwrite = false [[patches]] [patches.pattern] @@ -386,12 +380,11 @@ pattern = "if _th and _tw then" position = "after" payload = ''' if Big then - _th = to_big(_th):to_number() - _tw = to_big(_tw):to_number() + _th = to_number(_th) + _tw = to_number(_tw) end ''' match_indent = true -overwrite = false #these last few are causing lag, so they'll only be applied in the main menu [[patches]] @@ -399,7 +392,7 @@ overwrite = false target = "engine/ui.lua" pattern = "local _cw, _ch = w:set_wh()" position = "after" -payload = "if Big and G.STATE == G.STATES.MENU then _cw = to_big(_cw):to_number(); _ch = to_big(_ch):to_number() end" +payload = "if Big and G.STATE == G.STATES.MENU then _cw = to_number(_cw); _ch = to_number(_ch) end" match_indent = true [[patches]] @@ -408,10 +401,10 @@ target = "engine/moveable.lua" pattern = "function Moveable:move_wh(dt)" position = "after" payload = ''' -if Big and G.STATE == G.STATES.MENU then self.T.w = to_big(self.T.w):to_number() -self.T.h = to_big(self.T.h):to_number() -self.VT.w = to_big(self.VT.w):to_number() -self.VT.h = to_big(self.VT.h):to_number() end +if Big and G.STATE == G.STATES.MENU then self.T.w = to_number(self.T.w) +self.T.h = to_number(self.T.h) +self.VT.w = to_number(self.VT.w) +self.VT.h = to_number(self.VT.h) end ''' match_indent = true @@ -421,10 +414,10 @@ target = "functions/misc_functions.lua" pattern = "function prep_draw(moveable, scale, rotate, offset)" position = "after" payload = ''' -if Big and G.STATE == G.STATES.MENU then moveable.VT.x = to_big(moveable.VT.x):to_number() -moveable.VT.y = to_big(moveable.VT.y):to_number() -moveable.VT.w = to_big(moveable.VT.w):to_number() -moveable.VT.h = to_big(moveable.VT.h):to_number() end +if Big and G.STATE == G.STATES.MENU then moveable.VT.x = to_number(moveable.VT.x) +moveable.VT.y = to_number(moveable.VT.y) +moveable.VT.w = to_number(moveable.VT.w) +moveable.VT.h = to_number(moveable.VT.h) end ''' match_indent = true @@ -434,7 +427,7 @@ target = "engine/ui.lua" pattern = "if self.config.vert then love.graphics.translate(0,self.VT.h); love.graphics.rotate(-math.pi/2) end" position = "before" payload = ''' -if Big and G.STATE == G.STATES.MENU then self.config.scale = to_big(self.config.scale):to_number() end +if Big and G.STATE == G.STATES.MENU then self.config.scale = to_number(self.config.scale) end ''' match_indent = true @@ -468,7 +461,7 @@ match_indent = true target = "functions/common_events.lua" pattern = "G.hand_text_area.hand_level.config.colour = G.C.HAND_LEVELS[math.min(vals.level, 7)]" position = "at" -payload = "G.hand_text_area.hand_level.config.colour = G.C.HAND_LEVELS[to_number(to_big(math.min(vals.level, 7)))]" +payload = "G.hand_text_area.hand_level.config.colour = G.C.HAND_LEVELS[math.floor(to_number(math.min(vals.level, 7)))]" match_indent = true [[patches]] @@ -476,7 +469,7 @@ match_indent = true target = "functions/common_events.lua" pattern = "colours = {(G.GAME.hands[cfg.hand_type].level==1 and G.C.UI.TEXT_DARK or G.C.HAND_LEVELS[math.min(7, G.GAME.hands[cfg.hand_type].level)])}" position = "at" -payload = "colours = {(to_big(G.GAME.hands[cfg.hand_type].level)==to_big(1) and G.C.UI.TEXT_DARK or G.C.HAND_LEVELS[to_number(to_big(math.min(7, G.GAME.hands[cfg.hand_type].level)))])}" +payload = "colours = {(to_big(G.GAME.hands[cfg.hand_type].level)==to_big(1) and G.C.UI.TEXT_DARK or G.C.HAND_LEVELS[math.floor(to_number(math.min(7, G.GAME.hands[cfg.hand_type].level)))])}" match_indent = true [[patches]] @@ -484,7 +477,7 @@ match_indent = true target = "functions/UI_definitions.lua" pattern = '{n=G.UIT.C, config={align = "cm", padding = 0.01, r = 0.1, colour = G.C.HAND_LEVELS[math.min(7, G.GAME.hands[handname].level)], minw = 1.5, outline = 0.8, outline_colour = G.C.WHITE}, nodes={' position = "at" -payload = '{n=G.UIT.C, config={align = "cm", padding = 0.01, r = 0.1, colour = G.C.HAND_LEVELS[to_number(to_big(math.min(7, G.GAME.hands[handname].level)))], minw = 1.5, outline = 0.8, outline_colour = G.C.WHITE}, nodes={' +payload = '{n=G.UIT.C, config={align = "cm", padding = 0.01, r = 0.1, colour = G.C.HAND_LEVELS[math.floor(to_number(math.min(7, G.GAME.hands[handname].level)))], minw = 1.5, outline = 0.8, outline_colour = G.C.WHITE}, nodes={' match_indent = true # money fixes @@ -494,7 +487,6 @@ target = "functions/state_events.lua" pattern = '''G\.GAME\.dollars >= 5''' position = "at" payload = "to_big(G.GAME.dollars) >= to_big(5)" -match_indent = true [[patches]] [patches.pattern] @@ -518,7 +510,6 @@ target = "functions/button_callbacks.lua" pattern = '''e\.config\.ref_table\.cost > G\.GAME\.dollars - G\.GAME\.bankrupt_at''' position = "at" payload = '''to_big(e.config.ref_table.cost) > to_big(G.GAME.dollars) - to_big(G.GAME.bankrupt_at)''' -match_indent = true [[patches]] [patches.pattern] @@ -570,7 +561,7 @@ match_indent = true target = "cardarea.lua" pattern = '''self:change_size(self.config.last_poll_size - math.floor(G.GAME.dollars/G.GAME.modifiers.minus_hand_size_per_X_dollar))''' position = "at" -payload = '''self:change_size(to_big(self.config.last_poll_size - math.floor(G.GAME.dollars/G.GAME.modifiers.minus_hand_size_per_X_dollar)):to_number())''' +payload = '''self:change_size(to_number(self.config.last_poll_size - math.floor(G.GAME.dollars/G.GAME.modifiers.minus_hand_size_per_X_dollar)))''' match_indent = true # for now, I'm letting dollar eval ignore bignum, I'll patch it later @@ -615,7 +606,6 @@ pattern = "if new_game_obj then self.GAME = self:init_game_object() end" position = "after" payload = "if Talisman and Talisman.igo then self.GAME = Talisman.igo(self.GAME) end" match_indent = true -overwrite = false # call init game object appendum after init game object [[patches]] @@ -625,7 +615,6 @@ pattern = "self.GAME = saveTable and saveTable.GAME or self:init_game_object()" position = "after" payload = "if Talisman and Talisman.igo then self.GAME = Talisman.igo(self.GAME) end" match_indent = true -overwrite = false # remove more animations from event queue [[patches]] @@ -635,7 +624,6 @@ pattern = "if effects[ii].card then" position = "at" payload = "if effects[ii].card and not Talisman.config_file.disable_anims then" match_indent = true -overwrite = false #enhancement animation removing [[patches]] @@ -645,7 +633,6 @@ pattern = "if self.edition and not silent then" position = "at" payload = "if self.edition and (not Talisman.config_file.disable_anims or (not Talisman.calculating_joker and not Talisman.calculating_score and not Talisman.calculating_card)) and not silent then" match_indent = true -overwrite = false # dollar buffer thingy [[patches]] @@ -655,7 +642,6 @@ pattern = "G.E_MANAGER:add_event(Event({func = (function() G.GAME.dollar_buffer position = "at" payload = "if not Talisman.config_file.disable_anims then G.E_MANAGER:add_event(Event({func = (function() G.GAME.dollar_buffer = 0; return true end)})) else G.GAME.dollar_buffer = 0 end" match_indent = true -overwrite = false # add card [[patches]] @@ -665,7 +651,6 @@ pattern = "if G.GAME.blind then G.E_MANAGER:add_event(Event({ func = function() position = "at" payload = "if G.GAME.blind and (not SMODS or G.GAME.blind.in_blind) and not (Talisman.config_file.disable_anims and (Talisman.calculating_joker or Talisman.calculating_score or Talisman.calculating_card)) then G.E_MANAGER:add_event(Event({ func = function() G.GAME.blind:set_blind(nil, true, nil); return true end })) end" match_indent = true -overwrite = false # hand level ups [[patches]] @@ -675,7 +660,6 @@ pattern = "if not instant then" position = "at" payload = "if not instant and not Talisman.config_file.disable_anims then" match_indent = true -overwrite = false # Juice Issues [[patches]] @@ -879,27 +863,27 @@ elseif eval_type == 'hyper_chips' then elseif eval_type == 'e_mult' then sound = 'talisman_emult' amt = amt - text = '^' .. amt .. ' Mult' + text = '^' .. amt .. ' ' .. localize('k_mult') colour = G.C.MULT config.type = 'fade' config.scale = 0.7 elseif eval_type == 'ee_mult' then sound = 'talisman_eemult' amt = amt - text = '^^' .. amt .. ' Mult' + text = '^^' .. amt .. ' ' .. localize('k_mult') colour = G.C.MULT config.type = 'fade' config.scale = 0.7 elseif eval_type == 'eee_mult' then sound = 'talisman_eeemult' amt = amt - text = '^^^' .. amt .. ' Mult' + text = '^^^' .. amt .. ' ' .. localize('k_mult') colour = G.C.MULT config.type = 'fade' config.scale = 0.7 elseif eval_type == 'hyper_mult' then sound = 'talisman_eeemult' - text = (amt[1] > 5 and ('{' .. tostring(amt[1]) .. '}') or string.rep('^', amt[1])) .. tostring(amt[2]) .. ' Mult' + text = (amt[1] > 5 and ('{' .. tostring(amt[1]) .. '}') or string.rep('^', amt[1])) .. tostring(amt[2]) .. ' ' .. localize('k_mult') amt = amt[2] colour = G.C.MULT config.type = 'fade' @@ -1108,7 +1092,7 @@ if scoring_hand and scoring_hand[i] and scoring_hand[i].edition then mult = mod_mult(mult ^ edi.e_mult) update_hand_text({delay = 0}, {mult = mult}) card_eval_status_text(trg, 'extra', nil, percent, nil, - {message = '^'.. edi.e_mult ..' Mult', + {message = '^'.. edi.e_mult ..' ' .. localize('k_mult'), edition = true, e_mult = true}) end @@ -1116,7 +1100,7 @@ if scoring_hand and scoring_hand[i] and scoring_hand[i].edition then mult = mod_mult(mult:arrow(2, edi.ee_mult)) update_hand_text({delay = 0}, {mult = mult}) card_eval_status_text(trg, 'extra', nil, percent, nil, - {message = '^^'.. edi.ee_mult ..' Mult', + {message = '^^'.. edi.ee_mult ..' ' .. localize('k_mult'), edition = true, ee_mult = true}) end @@ -1124,7 +1108,7 @@ if scoring_hand and scoring_hand[i] and scoring_hand[i].edition then mult = mod_mult(mult:arrow(3, edi.eee_mult)) update_hand_text({delay = 0}, {mult = mult}) card_eval_status_text(trg, 'extra', nil, percent, nil, - {message = '^^^'.. edi.eee_mult ..' Mult', + {message = '^^^'.. edi.eee_mult ..' ' .. localize('k_mult'), edition = true, eee_mult = true}) end @@ -1132,7 +1116,7 @@ if scoring_hand and scoring_hand[i] and scoring_hand[i].edition then mult = mod_mult(mult:arrow(edi.hyper_mult[1], edi.hyper_mult[2])) update_hand_text({delay = 0}, {mult = mult}) card_eval_status_text(trg, 'extra', nil, percent, nil, - {message = (edi.hyper_mult[1] > 5 and ('{' .. edi.hyper_mult[1] .. '}') or string.rep('^', edi.hyper_mult[1])) .. edi.hyper_mult[2] ..' Mult', + {message = (edi.hyper_mult[1] > 5 and ('{' .. edi.hyper_mult[1] .. '}') or string.rep('^', edi.hyper_mult[1])) .. edi.hyper_mult[2] ..' ' .. localize('k_mult'), edition = true, hyper_mult = true}) end @@ -1203,7 +1187,7 @@ if G.jokers.cards and G.jokers.cards[i] and G.jokers.cards[i].edition then mult = mod_mult(mult ^ edi.e_mult) update_hand_text({delay = 0}, {mult = mult}) card_eval_status_text(trg, 'extra', nil, percent, nil, - {message = '^'.. edi.e_mult ..' Mult', + {message = '^'.. edi.e_mult ..' ' .. localize('k_mult'), edition = true, e_mult = true}) end @@ -1211,7 +1195,7 @@ if G.jokers.cards and G.jokers.cards[i] and G.jokers.cards[i].edition then mult = mod_mult(mult:arrow(2, edi.ee_mult)) update_hand_text({delay = 0}, {mult = mult}) card_eval_status_text(trg, 'extra', nil, percent, nil, - {message = '^^'.. edi.ee_mult ..' Mult', + {message = '^^'.. edi.ee_mult ..' ' .. localize('k_mult'), edition = true, ee_mult = true}) end @@ -1219,7 +1203,7 @@ if G.jokers.cards and G.jokers.cards[i] and G.jokers.cards[i].edition then mult = mod_mult(mult:arrow(3, edi.eee_mult)) update_hand_text({delay = 0}, {mult = mult}) card_eval_status_text(trg, 'extra', nil, percent, nil, - {message = '^^^'.. edi.eee_mult ..' Mult', + {message = '^^^'.. edi.eee_mult ..' ' .. localize('k_mult'), edition = true, eee_mult = true}) end @@ -1227,7 +1211,7 @@ if G.jokers.cards and G.jokers.cards[i] and G.jokers.cards[i].edition then mult = mod_mult(mult:arrow(edi.hyper_mult[1], edi.hyper_mult[2])) update_hand_text({delay = 0}, {mult = mult}) card_eval_status_text(trg, 'extra', nil, percent, nil, - {message = (edi.hyper_mult[1] > 5 and ('{' .. edi.hyper_mult[1] .. '}') or string.rep('^', edi.hyper_mult[1])) .. edi.hyper_mult[2] ..' Mult', + {message = (edi.hyper_mult[1] > 5 and ('{' .. edi.hyper_mult[1] .. '}') or string.rep('^', edi.hyper_mult[1])) .. edi.hyper_mult[2] ..' ' .. localize('k_mult'), edition = true, hyper_mult = true}) end @@ -1337,26 +1321,24 @@ match_indent = true [[patches]] [patches.pattern] target = 'functions/common_events.lua' -pattern = "text = localize{type='variable',key='a_chips'..(amt<0 and '_minus' or ''),vars={math.abs(amt)}}" +pattern = "if amt > 0 or amt < 0 then" position = 'at' -payload = "text = localize{type='variable',key='a_chips'..(to_big(amt) to_big(1e300) then AC[k].vol = 1e300 else - AC[k].vol = AC[k].vol:to_number() + AC[k].vol = to_number(AC[k].vol) end end if type(AC[k].per) == "table" then if AC[k].per > to_big(1e300) then AC[k].per = 1e300 else - AC[k].per = AC[k].per:to_number() + AC[k].per = to_number(AC[k].per) end end ''' @@ -1482,7 +1464,7 @@ payload = '''if type(_F.intensity) == "table" then if _F.intensity > to_big(1e300) then _F.intensity = 1e300 else - _F.intensity = _F.intensity:to_number() + _F.intensity = to_number(_F.intensity) end end ''' @@ -1511,4 +1493,53 @@ G.E_MANAGER:add_event(Event({ return true end })) -''' \ No newline at end of file +''' + +[[patches]] +[patches.pattern] +target = 'functions/misc_functions.lua' +position = 'at' +match_indent = true +pattern = ''' +G.ARGS.score_intensity.earned_score = G.GAME.current_round.current_hand.chips*G.GAME.current_round.current_hand.mult +''' +payload = ''' +G.ARGS.score_intensity.earned_score = math.min(to_number(G.GAME.current_round.current_hand.chips*G.GAME.current_round.current_hand.mult), 1e300) +''' + +[[patches]] +[patches.pattern] +target = 'functions/misc_functions.lua' +position = 'at' +match_indent = true +pattern = ''' +G.ARGS.score_intensity.earned_score = SMODS.calculate_round_score(true) +''' +payload = ''' +G.ARGS.score_intensity.earned_score = math.min(to_number(SMODS.calculate_round_score(true)), 1e300) +''' + +# evaluate_play_final_scoring comparison +[[patches]] +[patches.pattern] +target = 'functions/state_events.lua' +pattern = ''' +if SMODS.calculate_round_score() > 0 then +''' +position = '''at''' +payload = ''' +if to_big(SMODS.calculate_round_score()) > to_big(0) then +''' +match_indent = true + +[[patches]] +[patches.pattern] +target = 'functions/state_events.lua' +pattern = ''' +SMODS.last_hand_oneshot = SMODS.calculate_round_score() > G.GAME.blind.chips +''' +position = '''at''' +payload = ''' +SMODS.last_hand_oneshot = to_big(SMODS.calculate_round_score()) > to_big(G.GAME.blind.chips) +''' +match_indent = true \ No newline at end of file diff --git a/Talisman/steamodded_metadata.lua b/Talisman/steamodded_metadata.lua index 35cbffa..8fc4cc1 100644 --- a/Talisman/steamodded_metadata.lua +++ b/Talisman/steamodded_metadata.lua @@ -1,10 +1,10 @@ --- STEAMODDED HEADER --- MOD_NAME: Talisman --- MOD_ID: Talisman ---- MOD_AUTHOR: [MathIsFun_, Mathguy24, jenwalter666, cg-223] +--- MOD_AUTHOR: [MathIsFun_, Mathguy24, jenwalter666, cg-223, lord.ruby] --- MOD_DESCRIPTION: A mod that increases Balatro's score limit and skips scoring animations. --- PREFIX: talisman ---- VERSION: 2.2.0~dev +--- VERSION: 2.5 ---------------------------------------------- ------------MOD CODE ------------------------- @@ -57,6 +57,9 @@ if SMODS.current_mod then SMODS.current_mod.debug_info = { ["Break Infinity"] = Talisman.config_file.break_infinity } + SMODS.current_mod.description_loc_vars = function() + return { background_colour = G.C.CLEAR, text_colour = G.C.WHITE, scale = 1.2 } + end end --[[SMODS.Joker{ key = "test", @@ -94,5 +97,59 @@ end end, }--]] +if SMODS and SMODS.Scoring_Calculation then + local ref = SMODS.set_scoring_calculation + function SMODS.set_scoring_calculation(key, ...) + G.GAME.current_scoring_calculation_key = key + if key == "talisman_hyper" then + G.GAME.hyper_operator = G.GAME.hyper_operator or 2 + end + return ref(key, ...) + end + + SMODS.Scoring_Calculation:take_ownership("add", {order = -1}, true) + SMODS.Scoring_Calculation:take_ownership("multiply", {order = 0}, true) + SMODS.Scoring_Calculation:take_ownership("exponent", {order = 1}, true) + function change_operator(amount) + local order = SMODS.Scoring_Calculations[G.GAME.current_scoring_calculation_key or "multiply"].order + amount + if not order then return end + if G.GAME.current_scoring_calculation_key == "talisman_hyper" then + G.GAME.hyper_operator = (G.GAME.hyper_operator or 2) + amount + order = G.GAME.hyper_operator + end + local next = "add" + local keys = {} + for i, v in pairs(SMODS.Scoring_Calculations) do + if v.order then + keys[#keys+1] = i + end + end + table.sort(keys, function(a, b) return SMODS.Scoring_Calculations[a].order < SMODS.Scoring_Calculations[b].order end) + for i, v in pairs(keys) do + if SMODS.Scoring_Calculations[v].order <= order then + next = v + end + end + if next then + SMODS.set_scoring_calculation(next) + end + end + + SMODS.Scoring_Calculation { + key = "hyper", + func = function(self, chips, mult, flames) return to_big(chips):arrow(G.GAME.hyper_operator or 2, mult) end, + text = function() + if G.GAME.hyper_operator < 6 then + local str = "" + for i = 1, G.GAME.hyper_operator do str = str.."^" end + return str + else + return "{"..G.GAME.hyper_operator.."}" + end + end, + order = 2 + } +end + ---------------------------------------------- ------------MOD CODE END---------------------- diff --git a/Talisman/talisman.lua b/Talisman/talisman.lua index 0a82582..0d4ed52 100644 --- a/Talisman/talisman.lua +++ b/Talisman/talisman.lua @@ -1,15 +1,53 @@ local lovely = require("lovely") local nativefs = require("nativefs") -if not nativefs.getInfo(lovely.mod_dir .. "/Talisman") then - error( - 'Could not find proper Talisman folder.\nPlease make sure the folder for Talisman is named exactly "Talisman" and not "Talisman-main" or anything else.') +local info = nativefs.getDirectoryItemsInfo(lovely.mod_dir) +local talisman_path = "" +for i, v in pairs(info) do + if v.type == "directory" and nativefs.getInfo(lovely.mod_dir .. "/" .. v.name .. "/talisman.lua") then talisman_path = lovely.mod_dir .. "/" .. v.name end end -Talisman = {config_file = {disable_anims = true, break_infinity = "omeganum", score_opt_id = 2}} -if nativefs.read(lovely.mod_dir.."/Talisman/config.lua") then - Talisman.config_file = STR_UNPACK(nativefs.read(lovely.mod_dir.."/Talisman/config.lua")) +if not nativefs.getInfo(talisman_path) then + error( + 'Could not find proper Talisman folder.\nPlease make sure that Talisman is installed correctly and the folders arent nested.') +end +-- "Borrowed" from Trance +function load_file_with_fallback2(a, aa) + local success, result = pcall(function() return assert(load(nativefs.read(a)))() end) + if success then + return result + end + local fallback_success, fallback_result = pcall(function() return assert(load(nativefs.read(aa)))() end) + if fallback_success then + return fallback_result + end +end + +local talismanloc = init_localization +function init_localization() + local abc = load_file_with_fallback2( + talisman_path.."/localization/" .. (G.SETTINGS.language or "en-us") .. ".lua", + talisman_path .. "/localization/en-us.lua" + ) + for k, v in pairs(abc) do + if k ~= "descriptions" then + G.localization.misc.dictionary[k] = v + end + -- todo error messages(?) + G.localization.misc.dictionary[k] = v + end + talismanloc() +end + +Talisman = {config_file = {disable_anims = false, break_infinity = "omeganum", score_opt_id = 3}, mod_path = talisman_path} +if nativefs.read(talisman_path.."/config.lua") then + Talisman.config_file = STR_UNPACK(nativefs.read(talisman_path.."/config.lua")) + if Talisman.config_file.break_infinity == "bignumber" then + Talisman.config_file.break_infinity = "omeganum" + Talisman.config_file.score_opt_id = 2 + end + if Talisman.config_file.score_opt_id == 3 then Talisman.config_file.score_opt_id = 2 end if Talisman.config_file.break_infinity and type(Talisman.config_file.break_infinity) ~= 'string' then Talisman.config_file.break_infinity = "omeganum" end @@ -22,7 +60,7 @@ if not SMODS or not JSON then minw = 5, button = "talismanMenu", label = { - "Talisman" + localize({ type = "name_text", set = "Spectral", key = "c_talisman" }) }, colour = G.C.GOLD }) @@ -33,16 +71,16 @@ end Talisman.config_tab = function() tal_nodes = {{n=G.UIT.R, config={align = "cm"}, nodes={ - {n=G.UIT.O, config={object = DynaText({string = "Select features to enable:", colours = {G.C.WHITE}, shadow = true, scale = 0.4})}}, - }},create_toggle({label = "Disable Scoring Animations", ref_table = Talisman.config_file, ref_value = "disable_anims", + {n=G.UIT.O, config={object = DynaText({string = localize("talisman_string_A"), colours = {G.C.WHITE}, shadow = true, scale = 0.4})}}, + }},create_toggle({label = localize("talisman_string_B"), ref_table = Talisman.config_file, ref_value = "disable_anims", callback = function(_set_toggle) - nativefs.write(lovely.mod_dir .. "/Talisman/config.lua", STR_PACK(Talisman.config_file)) + nativefs.write(talisman_path .. "/config.lua", STR_PACK(Talisman.config_file)) end}), create_option_cycle({ - label = "Score Limit (requires game restart)", + label = localize("talisman_string_C"), scale = 0.8, w = 6, - options = {"Vanilla (e308)", "BigNum (ee308)", "OmegaNum (e10##1000)"}, + options = {localize("talisman_vanilla"), localize("talisman_omeganum") .. "(e10##1000)"}, opt_callback = 'talisman_upd_score_opt', current_option = Talisman.config_file.score_opt_id, })} @@ -65,7 +103,7 @@ G.FUNCS.talismanMenu = function(e) snap_to_nav = true, tabs = { { - label = "Talisman", + label = localize({ type = "name_text", set = "Spectral", key = "c_talisman" }), chosen = true, tab_definition_function = Talisman.config_tab }, @@ -80,14 +118,14 @@ G.FUNCS.talismanMenu = function(e) end G.FUNCS.talisman_upd_score_opt = function(e) Talisman.config_file.score_opt_id = e.to_key - local score_opts = {"", "bignumber", "omeganum"} + local score_opts = {"", "omeganum"} Talisman.config_file.break_infinity = score_opts[e.to_key] - nativefs.write(lovely.mod_dir .. "/Talisman/config.lua", STR_PACK(Talisman.config_file)) + nativefs.write(talisman_path .. "/config.lua", STR_PACK(Talisman.config_file)) end if Talisman.config_file.break_infinity then - Big, err = nativefs.load(lovely.mod_dir.."/Talisman/big-num/"..Talisman.config_file.break_infinity..".lua") + Big, err = nativefs.load(talisman_path.."/big-num/"..Talisman.config_file.break_infinity..".lua") if not err then Big = Big() else Big = nil end - Notations = nativefs.load(lovely.mod_dir.."/Talisman/big-num/notations.lua")() + Notations = nativefs.load(talisman_path.."/big-num/notations.lua")() -- We call this after init_game_object to leave room for mods that add more poker hands Talisman.igo = function(obj) for _, v in pairs(obj.hands) do @@ -106,9 +144,15 @@ if Talisman.config_file.break_infinity then local nf = number_format function number_format(num, e_switch_point) if type(num) == 'table' then - num = to_big(num) + --num = to_big(num) + if num.str then return num.str end + if num:arraySize() > 2 then + local str = Notations.Balatro:format(num, 3) + num.str = str + return str + end G.E_SWITCH_POINT = G.E_SWITCH_POINT or 100000000000 - if num < to_big(e_switch_point or G.E_SWITCH_POINT) then + if (num or 0) < (to_big(G.E_SWITCH_POINT) or 0) then return nf(num:to_number(), e_switch_point) else return Notations.Balatro:format(num, 3) @@ -118,7 +162,7 @@ if Talisman.config_file.break_infinity then local mf = math.floor function math.floor(x) - if type(x) == 'table' then return x:floor() end + if type(x) == 'table' then return x.floor and x:floor() or x end return mf(x) end local mc = math.ceil @@ -181,7 +225,11 @@ function lenient_bignum(x) function math.exp(x) local big_e = to_big(2.718281828459045) - return lenient_bignum(big_e:pow(x)) + if type(big_e) == "number" then + return lenient_bignum(big_e ^ x) + else + return lenient_bignum(big_e:pow(x)) + end end if SMODS then @@ -223,7 +271,7 @@ function lenient_bignum(x) -- Note that any ante scaling tweaks will need to manually changed... local gba = get_blind_amount function get_blind_amount(ante) - if G.GAME.modifiers.scaling and G.GAME.modifiers.scaling > 3 then return SMODS.get_blind_amount(ante) end + if G.GAME.modifiers.scaling and (G.GAME.modifiers.scaling ~= 1 and G.GAME.modifiers.scaling ~= 2 and G.GAME.modifiers.scaling ~= 3) then return SMODS.get_blind_amount(ante) end if type(to_big(1)) == 'number' then return gba(ante) end local k = to_big(0.75) if not G.GAME.modifiers.scaling or G.GAME.modifiers.scaling == 1 then @@ -307,24 +355,35 @@ function lenient_bignum(x) local sn = scale_number function scale_number(number, scale, max, e_switch_point) if not Big then return sn(number, scale, max, e_switch_point) end - scale = to_big(scale) + if type(scale) ~= "table" then scale = to_big(scale) end + if type(number) ~= "table" then number = Big:ensureBig(number) end + if number.scale then return number.scale end G.E_SWITCH_POINT = G.E_SWITCH_POINT or 100000000000 if not number or not is_number(number) then return scale end if not max then max = 10000 end - if to_big(number).e and to_big(number).e == 10^1000 then + if type(number) ~= "table" then math.min(3, scale:to_number()) end + if number.e and number.e == 10^1000 then scale = scale*math.floor(math.log(max*10, 10))/7 end - if to_big(number) >= to_big(e_switch_point or G.E_SWITCH_POINT) then - if (to_big(to_big(number):log10()) <= to_big(999)) then - scale = scale*math.floor(math.log(max*10, 10))/math.floor(math.log(1000000*10, 10)) + if not e_switch_point and number:arraySize() > 2 then --this is noticable faster than >= on the raw number for some reason + if number:arraySize() <= 2 and (number.array[1] or 0) <= 999 then --gross hack + scale = scale*math.floor(math.log(max*10, 10))/7 --this divisor is a constant so im precalcualting it + else + scale = scale*math.floor(math.log(max*10, 10))/math.floor(math.max(7,string.len(number.str or number_format(number))-1)) + end + elseif to_big(number) >= to_big(e_switch_point or G.E_SWITCH_POINT) then + if number:arraySize() <= 2 and (number.array[1] or 0) <= 999 then --gross hack + scale = scale*math.floor(math.log(max*10, 10))/7 --this divisor is a constant so im precalcualting it else scale = scale*math.floor(math.log(max*10, 10))/math.floor(math.max(7,string.len(number_format(number))-1)) end elseif to_big(number) >= to_big(max) then scale = scale*math.floor(math.log(max*10, 10))/math.floor(math.log(number*10, 10)) end - return math.min(3, scale:to_number()) - end + local scale = math.min(3, scale:to_number()) + number.scale = scale + return scale + end local tsj = G.FUNCS.text_super_juice function G.FUNCS.text_super_juice(e, _amount) @@ -397,7 +456,8 @@ function to_big(x, y) if type(x) == 'string' and x == "0" then --hack for when 0 is asked to be a bignumber need to really figure out the fix return 0 elseif Big and Big.m then - return Big:new(x,y) + local x = Big:new(x,y) + return x elseif Big and Big.array then local result = Big:create(x) result.sign = y or result.sign or x.sign or 1 @@ -425,6 +485,18 @@ function to_number(x) end end +function uncompress_big(str, sign) + local curr = 1 + local array = {} + for i, v in pairs(str) do + for i2 = 1, v[2] do + array[curr] = v[1] + curr = curr + 1 + end + end + return to_big(array, y) +end + --patch to remove animations local cest = card_eval_status_text function card_eval_status_text(a,b,c,d,e,f) @@ -474,7 +546,7 @@ function tal_uht(config, vals) else G.GAME.current_round.current_hand.hand_level = ' '..localize('k_lvl')..tostring(vals.level) if is_number(vals.level) then - G.hand_text_area.hand_level.config.colour = G.C.HAND_LEVELS[type(vals.level) == "number" and math.floor(math.min(vals.level, 7)) or math.floor(to_big(math.min(vals.level, 7))):to_number()] + G.hand_text_area.hand_level.config.colour = G.C.HAND_LEVELS[type(vals.level) == "number" and math.floor(math.min(vals.level, 7)) or math.floor(to_number(math.min(vals.level, 7)))] else G.hand_text_area.hand_level.config.colour = G.C.HAND_LEVELS[1] end @@ -572,7 +644,7 @@ if not Talisman.F_NO_COROUTINE then else G.SCORING_TEXT = nil if not G.OVERLAY_MENU then - G.scoring_text = {"Calculating...", "", "", ""} + G.scoring_text = {localize("talisman_string_D"), "", "", ""} G.SCORING_TEXT = { {n = G.UIT.C, nodes = { {n = G.UIT.R, config = {padding = 0.1, align = "cm"}, nodes = { @@ -587,7 +659,7 @@ if not Talisman.F_NO_COROUTINE then UIBox_button({ colour = G.C.BLUE, button = "tal_abort", - label = { "Abort" }, + label = { localize("talisman_string_E") }, minw = 4.5, focus_args = { snap_to = true }, })}}, @@ -606,10 +678,10 @@ if not Talisman.F_NO_COROUTINE then end local jokersYetToScore = #G.jokers.cards + #G.play.cards - #G.CARD_CALC_COUNTS G.CURRENT_CALC_TIME = (G.CURRENT_CALC_TIME or 0) + dt - G.scoring_text[1] = "Calculating..." - G.scoring_text[2] = "Elapsed calculations: "..tostring(totalCalcs).." ("..tostring(number_format(G.CURRENT_CALC_TIME)).."s)" - G.scoring_text[3] = "Cards yet to score: "..tostring(jokersYetToScore) - G.scoring_text[4] = "Calculations last played hand: " .. tostring(G.GAME.LAST_CALCS or "Unknown") .." ("..tostring(G.GAME.LAST_CALC_TIME and number_format(G.GAME.LAST_CALC_TIME) or "???").."s)" + G.scoring_text[1] = localize("talisman_string_D") + G.scoring_text[2] = localize("talisman_string_F")..tostring(totalCalcs).." ("..tostring(number_format(G.CURRENT_CALC_TIME)).."s)" + G.scoring_text[3] = localize("talisman_string_G")..tostring(jokersYetToScore) + G.scoring_text[4] = localize("talisman_string_H") .. tostring(G.GAME.LAST_CALCS or localize("talisman_string_I")) .." ("..tostring(G.GAME.LAST_CALC_TIME and number_format(G.GAME.LAST_CALC_TIME) or "???").."s)" end end @@ -710,8 +782,8 @@ end function Card:get_chip_x_bonus() if self.debuff then return 0 end if self.ability.set == 'Joker' then return 0 end - if (self.ability.x_chips or 0) <= 1 then return 0 end - return self.ability.x_chips + if (SMODS.multiplicative_stacking(self.ability.x_chips or 1, self.ability.perma_x_chips or 0) or 0) <= 1 then return 0 end + return SMODS.multiplicative_stacking(self.ability.x_chips or 1, self.ability.perma_x_chips or 0) end function Card:get_chip_e_bonus() @@ -788,7 +860,7 @@ local su = G.start_up function safe_str_unpack(str) local chunk, err = loadstring(str) if chunk then - setfenv(chunk, {Big = Big, BigMeta = BigMeta, OmegaMeta = OmegaMeta, to_big = to_big, inf = 1.79769e308}) -- Use an empty environment to prevent access to potentially harmful functions + setfenv(chunk, {Big = Big, BigMeta = BigMeta, OmegaMeta = OmegaMeta, to_big = to_big, inf = 1.79769e308, uncompress_big=uncompress_big}) -- Use an empty environment to prevent access to potentially harmful functions local success, result = pcall(chunk) if success then return result @@ -837,13 +909,6 @@ end -- Steamodded calculation API: add extra operations if SMODS and SMODS.calculate_individual_effect then - local smods_xchips = false - for _, v in pairs(SMODS.calculation_keys) do - if v == 'x_chips' then - smods_xchips = true - break - end - end local scie = SMODS.calculate_individual_effect function SMODS.calculate_individual_effect(effect, scored_card, key, amount, from_edition) -- For some reason, some keys' animations are completely removed @@ -855,28 +920,16 @@ if SMODS and SMODS.calculate_individual_effect then if ret then return ret end - if not smods_xchips and (key == 'x_chips' or key == 'xchips' or key == 'Xchip_mod') and amount ~= 1 then - if effect.card then juice_card(effect.card) end - hand_chips = mod_chips(hand_chips * amount) - update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) - if not effect.remove_default_message then - if from_edition then - card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = "X"..amount, colour = G.C.EDITION, edition = true}) - elseif key ~= 'Xchip_mod' then - if effect.xchip_message then - card_eval_status_text(scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.xchip_message) - else - card_eval_status_text(scored_card or effect.card or effect.focus, 'x_chips', amount, percent) - end - end - end - return true - end - if (key == 'e_chips' or key == 'echips' or key == 'Echip_mod') and amount ~= 1 then + if (key == 'e_chips' or key == 'echips' or key == 'Echip_mod') and amount ~= 1 then if effect.card then juice_card(effect.card) end - hand_chips = mod_chips(hand_chips ^ amount) - update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + if SMODS.Scoring_Parameters then + local chips = SMODS.Scoring_Parameters["chips"] + chips:modify(chips.current ^ amount - chips.current) + else + hand_chips = mod_chips(hand_chips ^ amount) + update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + end if not effect.remove_default_message then if from_edition then card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = "^"..amount, colour = G.C.EDITION, edition = true}) @@ -891,10 +944,15 @@ if SMODS and SMODS.calculate_individual_effect then return true end - if (key == 'ee_chips' or key == 'eechips' or key == 'EEchip_mod') and amount ~= 1 then + if (key == 'ee_chips' or key == 'eechips' or key == 'EEchip_mod') and amount ~= 1 then if effect.card then juice_card(effect.card) end - hand_chips = mod_chips(hand_chips:arrow(2, amount)) - update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + if SMODS.Scoring_Parameters then + local chips = SMODS.Scoring_Parameters["chips"] + chips:modify(to_big(chips.current):tetrate(amount) - chips.current) + else + hand_chips = mod_chips(hand_chips:tetrate(amount)) + update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + end if not effect.remove_default_message then if from_edition then card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = "^^"..amount, colour = G.C.EDITION, edition = true}) @@ -909,10 +967,15 @@ if SMODS and SMODS.calculate_individual_effect then return true end - if (key == 'eee_chips' or key == 'eeechips' or key == 'EEEchip_mod') and amount ~= 1 then + if (key == 'eee_chips' or key == 'eeechips' or key == 'EEEchip_mod') and amount ~= 1 then if effect.card then juice_card(effect.card) end - hand_chips = mod_chips(hand_chips:arrow(3, amount)) - update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + if SMODS.Scoring_Parameters then + local chips = SMODS.Scoring_Parameters["chips"] + chips:modify(to_big(chips.current):arrow(3, amount) - chips.current) + else + hand_chips = mod_chips(hand_chips:arrow(3, amount)) + update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + end if not effect.remove_default_message then if from_edition then card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = "^^^"..amount, colour = G.C.EDITION, edition = true}) @@ -927,10 +990,15 @@ if SMODS and SMODS.calculate_individual_effect then return true end - if (key == 'hyper_chips' or key == 'hyperchips' or key == 'hyperchip_mod') and type(amount) == 'table' then + if (key == 'hyper_chips' or key == 'hyperchips' or key == 'hyperchip_mod') and type(amount) == 'table' then if effect.card then juice_card(effect.card) end - hand_chips = mod_chips(hand_chips:arrow(amount[1], amount[2])) - update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + if SMODS.Scoring_Parameters then + local chips = SMODS.Scoring_Parameters["chips"] + chips:modify(to_big(chips.current):arrow(amount[1], amount[2]) - chips.current) + else + hand_chips = mod_chips(hand_chips:arrow(amount[1], amount[2])) + update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + end if not effect.remove_default_message then if from_edition then card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = (amount[1] > 5 and ('{' .. amount[1] .. '}') or string.rep('^', amount[1])) .. amount[2], colour = G.C.EDITION, edition = true}) @@ -945,13 +1013,18 @@ if SMODS and SMODS.calculate_individual_effect then return true end - if (key == 'e_mult' or key == 'emult' or key == 'Emult_mod') and amount ~= 1 then + if (key == 'e_mult' or key == 'emult' or key == 'Emult_mod') and amount ~= 1 then if effect.card then juice_card(effect.card) end - mult = mod_mult(mult ^ amount) - update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + if SMODS.Scoring_Parameters then + local mult = SMODS.Scoring_Parameters["mult"] + mult:modify(mult.current ^ amount - mult.current) + else + mult = mod_mult(mult ^ amount) + update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + end if not effect.remove_default_message then if from_edition then - card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = "^"..amount.." Mult", colour = G.C.EDITION, edition = true}) + card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = "^"..amount.." "..localize("k_mult"), colour = G.C.EDITION, edition = true}) elseif key ~= 'Emult_mod' then if effect.emult_message then card_eval_status_text(scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.emult_message) @@ -963,13 +1036,18 @@ if SMODS and SMODS.calculate_individual_effect then return true end - if (key == 'ee_mult' or key == 'eemult' or key == 'EEmult_mod') and amount ~= 1 then + if (key == 'ee_mult' or key == 'eemult' or key == 'EEmult_mod') and amount ~= 1 then if effect.card then juice_card(effect.card) end - mult = mod_mult(mult:arrow(2, amount)) - update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + if SMODS.Scoring_Parameters then + local mult = SMODS.Scoring_Parameters["mult"] + mult:modify(to_big(mult.current):arrow(2, amount) - mult.current) + else + mult = mod_mult(mult:arrow(2, amount)) + update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + end if not effect.remove_default_message then if from_edition then - card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = "^^"..amount.." Mult", colour = G.C.EDITION, edition = true}) + card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = "^^"..amount.." "..localize("k_mult"), colour = G.C.EDITION, edition = true}) elseif key ~= 'EEmult_mod' then if effect.eemult_message then card_eval_status_text(scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.eemult_message) @@ -981,13 +1059,18 @@ if SMODS and SMODS.calculate_individual_effect then return true end - if (key == 'eee_mult' or key == 'eeemult' or key == 'EEEmult_mod') and amount ~= 1 then + if (key == 'eee_mult' or key == 'eeemult' or key == 'EEEmult_mod') and amount ~= 1 then if effect.card then juice_card(effect.card) end - mult = mod_mult(mult:arrow(3, amount)) - update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + if SMODS.Scoring_Parameters then + local mult = SMODS.Scoring_Parameters["mult"] + mult:modify(to_big(mult.current):arrow(3, amount) - mult.current) + else + mult = mod_mult(mult:arrow(3, amount)) + update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + end if not effect.remove_default_message then if from_edition then - card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = "^^^"..amount.." Mult", colour = G.C.EDITION, edition = true}) + card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = "^^^"..amount.." "..localize("k_mult"), colour = G.C.EDITION, edition = true}) elseif key ~= 'EEEmult_mod' then if effect.eeemult_message then card_eval_status_text(scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.eeemult_message) @@ -999,13 +1082,18 @@ if SMODS and SMODS.calculate_individual_effect then return true end - if (key == 'hyper_mult' or key == 'hypermult' or key == 'hypermult_mod') and type(amount) == 'table' then + if (key == 'hyper_mult' or key == 'hypermult' or key == 'hypermult_mod') and type(amount) == 'table' then if effect.card then juice_card(effect.card) end - mult = mod_mult(mult:arrow(amount[1], amount[2])) - update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + if SMODS.Scoring_Parameters then + local mult = SMODS.Scoring_Parameters["mult"] + mult:modify(to_big(mult.current):arrow(amount[1], amount[2]) - mult.current) + else + mult = mod_mult(mult:arrow(amount[1], amount[2])) + update_hand_text({delay = 0}, {chips = hand_chips, mult = mult}) + end if not effect.remove_default_message then if from_edition then - card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = ((amount[1] > 5 and ('{' .. amount[1] .. '}') or string.rep('^', amount[1])) .. amount[2]).." Mult", colour = G.C.EDITION, edition = true}) + card_eval_status_text(scored_card, 'jokers', nil, percent, nil, {message = ((amount[1] > 5 and ('{' .. amount[1] .. '}') or string.rep('^', amount[1])) .. amount[2]).." "..localize("k_mult"), colour = G.C.EDITION, edition = true}) elseif key ~= 'hypermult_mod' then if effect.hypermult_message then card_eval_status_text(scored_card or effect.card or effect.focus, 'extra', nil, percent, nil, effect.hypermult_message) @@ -1020,12 +1108,7 @@ if SMODS and SMODS.calculate_individual_effect then for _, v in ipairs({'e_mult', 'e_chips', 'ee_mult', 'ee_chips', 'eee_mult', 'eee_chips', 'hyper_mult', 'hyper_chips', 'emult', 'echips', 'eemult', 'eechips', 'eeemult', 'eeechips', 'hypermult', 'hyperchips', 'Emult_mod', 'Echip_mod', 'EEmult_mod', 'EEchip_mod', 'EEEmult_mod', 'EEEchip_mod', 'hypermult_mod', 'hyperchip_mod'}) do - table.insert(SMODS.calculation_keys, v) - end - if not smods_xchips then - for _, v in ipairs({'x_chips', 'xchips', 'Xchip_mod'}) do - table.insert(SMODS.calculation_keys, v) - end + table.insert(SMODS.scoring_parameter_keys or SMODS.calculation_keys, v) end -- prvent juice animations @@ -1052,4 +1135,4 @@ local emae = EventManager.add_event function EventManager:add_event(x,y,z) printCallerInfo() return emae(self,x,y,z) -end--]] \ No newline at end of file +end--]]