Compare commits
No commits in common. "main" and "rewrite" have entirely different histories.
5
.gitignore
vendored
|
|
@ -39,8 +39,3 @@ luac.out
|
|||
*.x86_64
|
||||
*.hex
|
||||
|
||||
# Syncthing
|
||||
.stfolder
|
||||
|
||||
# Autogenerated
|
||||
assets/1x/jokers
|
||||
|
|
|
|||
12
.vscode/settings.json
vendored
|
|
@ -1,8 +1,4 @@
|
|||
{
|
||||
"Lua.diagnostics.disable": [
|
||||
"duplicate-set-field",
|
||||
"lowercase-global",
|
||||
],
|
||||
"Lua.diagnostics.severity": {
|
||||
"ambiguity-1": "Error",
|
||||
"assign-type-mismatch": "Error",
|
||||
|
|
@ -22,12 +18,14 @@
|
|||
"duplicate-doc-field": "Error",
|
||||
"duplicate-doc-param": "Error",
|
||||
"duplicate-index": "Error",
|
||||
"duplicate-set-field": "Error",
|
||||
"empty-block": "Error",
|
||||
"global-element": "Error",
|
||||
"global-in-nil-env": "Error",
|
||||
"incomplete-signature-doc": "Error",
|
||||
"inject-field": "Error",
|
||||
"invisible": "Error",
|
||||
"lowercase-global": "Error",
|
||||
"missing-fields": "Error",
|
||||
"missing-global-doc": "Error",
|
||||
"missing-local-export-doc": "Error",
|
||||
|
|
@ -64,9 +62,5 @@
|
|||
"unused-label": "Error",
|
||||
"unused-local": "Error",
|
||||
"unused-vararg": "Error",
|
||||
},
|
||||
"Lua.runtime.version": "LuaJIT",
|
||||
"Lua.workspace.library": [
|
||||
"${3rd}/love2d/library"
|
||||
],
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 170 KiB After Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 897 B After Width: | Height: | Size: 904 B |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 9 KiB |
|
Before Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 242 KiB After Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
|
@ -1,10 +0,0 @@
|
|||
#!/bin/sh
|
||||
directory=$(dirname $(readlink -f "$0"))
|
||||
mkdir -p "$directory/1x/jokers"
|
||||
|
||||
for i in $(seq 0 $(cd "$directory/1x/jokers/" && find *.png | tail -n +2 | wc -l)); do
|
||||
files="$files $directory/1x/jokers/$i.png";
|
||||
done
|
||||
|
||||
magick montage -background '#00000000' $files -geometry +0+0 "$directory/1x/joker.png"
|
||||
"$directory/upscale.sh"
|
||||
|
|
@ -1,199 +0,0 @@
|
|||
#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 frozen;
|
||||
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;
|
||||
|
||||
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.,6.,0.) : tex.xyz, res > adjusted_dissolve ? (shadow ? tex.a*0.3: tex.a) : .0);
|
||||
}
|
||||
|
||||
#define DEPTH 21
|
||||
#define PHI ((1. + sqrt(5.)) / 2.)
|
||||
#define PI 3.141592653589
|
||||
#define S(M, O) (0.5 + 0.5 * sin(O + M * pos.x)) / 6.
|
||||
#define C(M, O) (0.5 + 0.5 * cos(O + M * pos.y)) / 6.
|
||||
|
||||
vec2 rotate(vec2 v, float a)
|
||||
{
|
||||
float s = sin(a);
|
||||
float c = cos(a);
|
||||
mat2 m = mat2(c, -s, s, c);
|
||||
return m * v;
|
||||
}
|
||||
|
||||
float cr(vec2 a, vec2 b)
|
||||
{
|
||||
return a.x * b.y - b.x * a.y;
|
||||
}
|
||||
|
||||
float cr(vec2 a, vec2 b, vec2 c)
|
||||
{
|
||||
return cr(b - a, c - b);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (uv.x > uv.x * 2.) {
|
||||
uv = frozen;
|
||||
}
|
||||
|
||||
// Slightly adapted from 'snowflake lattice' by pali6.
|
||||
// https://www.shadertoy.com/view/7sG3zd
|
||||
// https://www.shadertoy.com/user/pali6
|
||||
float iTime = 0.0;
|
||||
vec2 pos = (((texture_coords)*(image_details)) - texture_details.xx*texture_details.ba)/texture_details.ba;
|
||||
|
||||
float scale = 72. + 18. * sin(iTime / 10.) + 20. * sin(4. + iTime / 15.) + 30. * sin(iTime / 6.);
|
||||
vec2 camPos = vec2(0.5, 0.5);
|
||||
float SF = 1. / pow(scale, 0.3);
|
||||
camPos += vec2(0.02 * sin(iTime / 15.), -0.07 * cos(iTime / 19.)) * SF;
|
||||
camPos += vec2(-0.1 * sin(3. + iTime / 37.), -0.1 * cos(4. + iTime / 27.)) * SF;
|
||||
camPos += vec2(0.07 * sin(9. + iTime / 47.), -0.08 * cos(20. + iTime / 31.)) * SF;
|
||||
camPos += vec2(0.04 * sin(19. + iTime / 7.), 0.06 * cos(25. + iTime / 5.)) * SF;
|
||||
pos -= vec2(0.5, 0.5);
|
||||
pos = rotate(pos, iTime / 30. + PI * cos(iTime / 37.) + 2. * PI * sin(iTime / 87. + 10.));
|
||||
pos /= scale;
|
||||
pos += camPos;
|
||||
vec2 ota = vec2(-1., 0.);
|
||||
vec2 otb = vec2(2., 0.);
|
||||
vec2 ta = ota;
|
||||
vec2 tb = otb;
|
||||
vec2 tc;
|
||||
bool gn = true;
|
||||
float fl = -1.;
|
||||
float f = 0.;
|
||||
float nDark = 0.;
|
||||
|
||||
for (int i = 0; i < DEPTH; i++)
|
||||
{
|
||||
vec2 next;
|
||||
|
||||
if (gn)
|
||||
tc = ta + rotate(tb - ta, fl * PI / 5.) / PHI;
|
||||
else
|
||||
tc = ta + rotate(tb - ta, fl * 2. * PI / 5.) * PHI;
|
||||
|
||||
if(!(gn && min(length(pos - ta), length(pos - tb)) > length(ta - tb) / 3. || !gn && length(pos - tb) <= length(tc - tb) * PHI / 3.5))
|
||||
{
|
||||
nDark += 1.;
|
||||
}
|
||||
|
||||
if (gn)
|
||||
{
|
||||
next = tb + (ta - tb) / PHI;
|
||||
|
||||
if (abs(cr(next, tc, pos)) * float(i + 1) < 0.000001)
|
||||
f = 1.;
|
||||
|
||||
if (cr(next, tc, pos) * cr(next, tc, tb) > 0.)
|
||||
{
|
||||
gn = false;
|
||||
ta = next;
|
||||
tb = tc;
|
||||
fl *= -1.;
|
||||
i--;
|
||||
}
|
||||
else
|
||||
{
|
||||
gn = true;
|
||||
tb = ta;
|
||||
ta = tc;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
next = tc + (tb - tc) / PHI;
|
||||
|
||||
if (abs(cr(ta, next, pos)) * float(i + 1) < 0.000001)
|
||||
f = 1.;
|
||||
|
||||
if (cr(ta, next, pos) * cr(ta, next, tb) > 0.)
|
||||
{
|
||||
gn = false;
|
||||
ta = tb;
|
||||
tb = next;
|
||||
}
|
||||
else
|
||||
{
|
||||
gn = true;
|
||||
tb = ta;
|
||||
ta = tc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
colour = (nDark / float(DEPTH)) * vec4(
|
||||
0.1 + S(30., 10.) + C(10., 11.) + S(50., 16.) + S(99., 15.) + S(1., 42.) + C(1.5, 73.),
|
||||
0.1 + C(20., 10.) + S(70., 12.) + C(23., 18.) + C(67., 119.) + S(1.2, 49.) + C(0.9, 79.),
|
||||
0.15 + S(70., 10.5) + C(31., 17.) + S(55., 135.) + C(123., 15.) + S(0.7, 13.) + C(0.11, 31.),
|
||||
1.
|
||||
) * 1.5;
|
||||
|
||||
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
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
#!/bin/sh
|
||||
directory=$(dirname $(readlink -f "$0"))
|
||||
mkdir -p "$directory/1x/jokers"
|
||||
magick "$directory/1x/joker.png" -crop 71x95 +repage +adjoin "$directory/1x/jokers/%01d.png"
|
||||
|
|
@ -1,18 +1 @@
|
|||
@echo off
|
||||
for /F %%x in ('dir /B/D 2x') do (
|
||||
if %%~xx == .png (
|
||||
if not exist 1x\%%x (
|
||||
echo Removing deleted file 1x\%%x from 2x\
|
||||
del 2x\%%x
|
||||
)
|
||||
)
|
||||
)
|
||||
for /F %%x in ('dir /B/D 1x') do (
|
||||
if %%~xx == .png (
|
||||
REM https://stackoverflow.com/questions/1687014/how-do-i-compare-timestamps-of-files-in-a-batch-script/58323817#58323817
|
||||
xcopy /LDY /-I 1x\%%x 2x\%%x | findstr /B /C:"1 " > nul 2>&1 && (
|
||||
echo Updating changed file 1x\%%x in 2x\
|
||||
magick 1x\%%x -filter point -resize 200%% 2x\%%x
|
||||
)
|
||||
)
|
||||
)
|
||||
for /F %%x in ('dir /B/D 1x') do magick 1x\%%x -scale 200%% 2x\%%x
|
||||
|
|
|
|||
13
config.lua
|
|
@ -1,12 +1 @@
|
|||
return {
|
||||
animated_icon = true,
|
||||
cool_phones = true,
|
||||
equinox_assist = false,
|
||||
faster_planets = false,
|
||||
harsh_ante_scaling = false,
|
||||
illusion_seal = true,
|
||||
import_funky = false,
|
||||
no_wild_debuff = true,
|
||||
scribable_basket = false,
|
||||
vitriol = true,
|
||||
}
|
||||
return {escapey_debugger = false, equinox_assist = false}
|
||||
|
|
|
|||
|
|
@ -6,9 +6,15 @@ return {
|
|||
text = {
|
||||
"{C:attention}Small{} and {C:attention}Big Blinds{} are",
|
||||
"replaced with {C:attention}Boss Blinds",
|
||||
"that are {C:dark_edition}debuffed twice",
|
||||
"",
|
||||
"{C:Bakery_credit_fg_Roland_bakersdozenbagels,s:0.75}Art: BakersDozenBagels",
|
||||
"that are {C:dark_edition}debuffed #1# times",
|
||||
},
|
||||
},
|
||||
b_Roland_go = {
|
||||
name = "Pass GO Deck",
|
||||
text = {
|
||||
"Start with a {C:attention}Credit Card",
|
||||
"Set money to {C:money}$0",
|
||||
"when entering the shop",
|
||||
},
|
||||
},
|
||||
b_Roland_swapper = {
|
||||
|
|
@ -16,39 +22,32 @@ return {
|
|||
text = {
|
||||
"{C:tarot}Tarot {}and {C:spectral}Spectral",
|
||||
"cards swap places",
|
||||
"",
|
||||
"{C:Bakery_credit_fg_Roland_bakersdozenbagels,s:0.75}Art: BakersDozenBagels",
|
||||
},
|
||||
},
|
||||
},
|
||||
BakeryCharm = {
|
||||
BakeryCharm_Roland_cocacola = {
|
||||
name = SMODS.Mods.Roland.config.cool_phones and "coca cola phone" or "Pentagram",
|
||||
text = {
|
||||
"{C:attention}Discard 0 cards {}to",
|
||||
"gain {C:red}#1# {}discards and",
|
||||
"lose {C:attention}#2# {}hand size",
|
||||
"this round",
|
||||
},
|
||||
name = "coca cola phone",
|
||||
text = {"Values on consumables", "increase by {C:attention}1"},
|
||||
},
|
||||
BakeryCharm_Roland_fat = {
|
||||
name = SMODS.Mods.Roland.config.cool_phones and "fat i phone" or "Product",
|
||||
name = "fat i phone",
|
||||
text = {
|
||||
"{C:attention}+#1# Booster Pack {}slots",
|
||||
-- "{C:attention}+#1# Booster Pack {}slots",
|
||||
"All {C:attention}Booster Packs {}are {C:attention}Mega",
|
||||
"{C:inactive}(Whenever applicable)",
|
||||
},
|
||||
},
|
||||
BakeryCharm_Roland_flexible = {
|
||||
name = SMODS.Mods.Roland.config.cool_phones and "flexi ble phone" or "Ring",
|
||||
name = "flexi ble phone",
|
||||
text = {unpack(G.localization.descriptions.Joker.j_ring_master.text)},
|
||||
},
|
||||
BakeryCharm_Roland_hand = {
|
||||
name = SMODS.Mods.Roland.config.cool_phones and "hand phone" or "Shell",
|
||||
name = "hand phone",
|
||||
text = {"{C:attention}+#1# {}hand size", "{C:blue}#2# {}hands"},
|
||||
},
|
||||
BakeryCharm_Roland_wii = {
|
||||
name = SMODS.Mods.Roland.config.cool_phones and "wii phone" or "Tire",
|
||||
name = "wii phone",
|
||||
text = {
|
||||
"Enter the shop",
|
||||
"when any {C:attention}Blind",
|
||||
|
|
@ -57,49 +56,37 @@ return {
|
|||
},
|
||||
},
|
||||
Blind = {
|
||||
bl_Roland_blizzard = {
|
||||
name = "The Blizzard",
|
||||
text = {"All cards", "are {C:dark_edition}Frozen"},
|
||||
},
|
||||
bl_Roland_divide = {
|
||||
name = "The Great Divide",
|
||||
text = {"Half of the deck", "is {C:red}discarded"},
|
||||
text = {"Half of the deck", "is discarded"},
|
||||
},
|
||||
bl_Roland_equinox = {
|
||||
name = "The Equinox",
|
||||
text = {"{C:inactive}No UI"},
|
||||
text = {"No UI"},
|
||||
},
|
||||
bl_Roland_falseshuffle = {
|
||||
name = "The False Shuffle",
|
||||
text = {"{C:enhanced}Enhanced {}cards", "are drawn {C:attention}last"},
|
||||
text = {"Enhanced cards", "are drawn last"},
|
||||
},
|
||||
bl_Roland_improbable = {
|
||||
name = "The Improbable",
|
||||
text = {"All {C:green}probabilities", "cannot happen"},
|
||||
text = {"All probabilities", "cannot happen"},
|
||||
},
|
||||
bl_Roland_mitotic = {
|
||||
name = "The Mitotic",
|
||||
text = {"{C:red}Discarded {}cards", "are {C:attention}copied"},
|
||||
text = {"Discarded cards", "are copied"},
|
||||
},
|
||||
bl_Roland_nimble = {
|
||||
name = "The Nimble",
|
||||
text = {"The {C:attention}first 5 {}cards", "drawn are {C:blue}played"},
|
||||
text = {"The first 5 cards", "drawn are played"},
|
||||
},
|
||||
bl_Roland_tranquilizer = {
|
||||
name = "The Tranquilizer",
|
||||
text = {
|
||||
"{C:attention}#1#s {}are {C:red}debuffed",
|
||||
"Changes based on",
|
||||
"most common rank",
|
||||
},
|
||||
text = {"#1#s are debuffed", "Changes based on", "most common rank"},
|
||||
},
|
||||
bl_Roland_venerable_visage = {
|
||||
name = "Venerable Visage",
|
||||
text = {
|
||||
"Infinite {C:red}discards",
|
||||
"Lose if {C:attention}any {}card was",
|
||||
"not {C:blue}played {}or {C:red}discarded",
|
||||
},
|
||||
text = {"Infinite discards", "Lose if any card was", "not played or discarded"},
|
||||
fail = {
|
||||
"Blasphemy.",
|
||||
"Blunder.",
|
||||
|
|
@ -118,12 +105,6 @@ return {
|
|||
},
|
||||
},
|
||||
},
|
||||
Edition = {
|
||||
e_Roland_frozen = {
|
||||
name = "Frozen",
|
||||
text = {"Values on", "this card do", "not change"},
|
||||
},
|
||||
},
|
||||
Enhanced = {
|
||||
m_wild = {
|
||||
name = "Wild Card",
|
||||
|
|
@ -131,36 +112,6 @@ return {
|
|||
},
|
||||
},
|
||||
Joker = {
|
||||
j_Roland_amber = {
|
||||
name = "Amber Acorn",
|
||||
text = {
|
||||
"{X:mult,C:white}X#1#{} Mult",
|
||||
"Moves before",
|
||||
"hand is played",
|
||||
},
|
||||
},
|
||||
j_Roland_arctic = {
|
||||
name = "Arctic Circle",
|
||||
text = {"Retrigger {C:attention}all", "{C:dark_edition}Frozen {}cards"},
|
||||
},
|
||||
j_Roland_artemis = {
|
||||
name = "Artemis X",
|
||||
text = {
|
||||
"Earn {C:money}$#1# {}at end of round",
|
||||
"Payout increases by {C:money}$#2#",
|
||||
"when these {C:planet}Planet {}cards",
|
||||
"are used in order:",
|
||||
"{V:1}Earth{C:inactive} - {V:2}Mars{C:inactive} - {V:3}Earth",
|
||||
},
|
||||
},
|
||||
j_Roland_basket = {
|
||||
name = "Basket",
|
||||
text = {
|
||||
"Sell this Joker to",
|
||||
"create {C:dark_edition}Negative {}copies",
|
||||
"of every consumable",
|
||||
},
|
||||
},
|
||||
j_Roland_bulldozer = {
|
||||
name = "Bulldozer",
|
||||
text = {
|
||||
|
|
@ -169,28 +120,43 @@ return {
|
|||
"{C:inactive}(Currently {X:red,C:white}X#1#{C:inactive})",
|
||||
},
|
||||
},
|
||||
j_Roland_cold = {
|
||||
name = "Cold Turkey",
|
||||
j_Roland_escapey = {
|
||||
name = "Escapey",
|
||||
text = {
|
||||
"Third scored card",
|
||||
"gives {X:red,C:white}X#1#{} Mult",
|
||||
"if it is {C:dark_edition}Frozen",
|
||||
"Use to {C:attention}destroy tags{} or {C:attention}unselected consumables",
|
||||
"in exchange for {C:planet}leveling up {X:planet,C:white}#1#{C:planet} random hands",
|
||||
"{C:inactive,s:0.75,E:1}#2#{C:red,s:1.5,E:1}#3#{s:0.9}#4#{C:blue,E:1,s:0.9}#5#{s:0.9}#6#",
|
||||
},
|
||||
merge = {"Since none apply, fuse with other ", " jokers"},
|
||||
quotes = {
|
||||
marble = {"there is no escape..."},
|
||||
normal = {
|
||||
"I can't wait to work with you!",
|
||||
"Did you need something from me?",
|
||||
"Oh! I'm just so happy to see you!",
|
||||
"Can I say something irrelevant? I promise it won't be long.",
|
||||
"Tell me about your buddies! Assuming you have them, anyway.",
|
||||
},
|
||||
scared = {
|
||||
"What am I going to do?!",
|
||||
"I'm not scared, you are!",
|
||||
"Tell me when this is over...",
|
||||
"I can't keep looking at this!",
|
||||
"Let me go hide in this corner... Okay?",
|
||||
},
|
||||
},
|
||||
j_Roland_cerulean = {
|
||||
name = "Cerulean Bell",
|
||||
},
|
||||
j_Roland_phytoestrogens = {
|
||||
name = "Phytoestrogens",
|
||||
text = {"{C:mult}+Chips{} Mult", "{X:mult,C:white}X#1#{} Mult"},
|
||||
},
|
||||
j_Roland_monomino = {
|
||||
name = "Monomino",
|
||||
text = {
|
||||
"{X:mult,C:white}X#1#{} Mult",
|
||||
"All other {C:attention}Jokers {}cannot",
|
||||
"be selected or dragged",
|
||||
},
|
||||
},
|
||||
j_Roland_crimson = {
|
||||
name = "Crimson Heart",
|
||||
text = {
|
||||
"{X:mult,C:white}X#1#{} Mult",
|
||||
"{C:red}Debuffs {C:attention}Joker",
|
||||
"to the left",
|
||||
"Gains {C:money}$#1#{} of",
|
||||
"{C:attention}sell value{} if",
|
||||
"played hand is a",
|
||||
"{C:attention}#2#",
|
||||
},
|
||||
},
|
||||
j_Roland_domino = {
|
||||
|
|
@ -202,51 +168,24 @@ return {
|
|||
"{C:inactive}(Currently {C:red}+#3#{C:inactive} Mult)",
|
||||
},
|
||||
},
|
||||
j_Roland_excalibur = {
|
||||
name = "Excalibur",
|
||||
j_Roland_trimino = {
|
||||
name = "Trimino",
|
||||
text = {
|
||||
"Score {C:attention}#1# {C:enhanced}Stone Cards",
|
||||
"to {C:attention}pull {}this {C:attention}Joker",
|
||||
"{C:inactive}(Currently {C:attention}#2#{C:inactive})",
|
||||
"Copies {C:attention}#1# {C:green}random",
|
||||
"scoring cards and",
|
||||
"{C:red,E:1}self-destructs {}if",
|
||||
"played hand is a",
|
||||
"{C:attention}#2#",
|
||||
},
|
||||
},
|
||||
j_Roland_excalibur_Back = {
|
||||
name = "Excalibur",
|
||||
j_Roland_misfortune = {
|
||||
name = "Misfortune Cookie",
|
||||
text = {
|
||||
"Scored and held in",
|
||||
"hand {C:enhanced}Stone Cards",
|
||||
"each give {X:mult,C:white}X#3#{} Mult",
|
||||
"{C:tarot}Tarot{} cards created",
|
||||
"by {C:tarot}Purple Seals",
|
||||
"become {C:dark_edition}Negative",
|
||||
},
|
||||
},
|
||||
j_Roland_hardboiled = {
|
||||
name = "Hard-Boiled",
|
||||
text = {
|
||||
"Sell this Joker to",
|
||||
"turn all cards in",
|
||||
"hand {C:dark_edition}Frozen",
|
||||
},
|
||||
},
|
||||
j_Roland_idle = {
|
||||
name = "The Idle",
|
||||
text = {
|
||||
"Use to add card's",
|
||||
"rank and suit",
|
||||
"First {C:attention}scoring {}card",
|
||||
"of each entry",
|
||||
"gives {X:mult,C:white}X#19#{} Mult",
|
||||
"{C:inactive}(Must be distinct)",
|
||||
"{V:1,s:0.75}#1#{C:inactive,s:0.75}#2#{V:2,s:0.75}#3#{C:inactive,s:0.75}, " ..
|
||||
"{V:3,s:0.75}#4#{C:inactive,s:0.75}#5#{V:4,s:0.75}#6#{C:inactive,s:0.75}",
|
||||
"{V:5,s:0.75}#7#{C:inactive,s:0.75}#8#{V:6,s:0.75}#9#, " ..
|
||||
"{V:7,s:0.75}#10#{C:inactive,s:0.75}#11#{V:8,s:0.75}#12#{C:inactive,s:0.75}",
|
||||
"{V:9,s:0.75}#13#{C:inactive,s:0.75}#14#{V:10,s:0.75}#15#{C:inactive,s:0.75}, " ..
|
||||
"{V:11,s:0.75}#16#{C:inactive,s:0.75}#17#{V:12,s:0.75}#18#",
|
||||
},
|
||||
},
|
||||
j_Roland_jokersr = {
|
||||
name = "Joker Sr.",
|
||||
text = {"{X:mult,C:white}X#1#{} Mult"},
|
||||
},
|
||||
j_Roland_martingale = {
|
||||
name = "Martingale",
|
||||
text = {
|
||||
|
|
@ -260,23 +199,6 @@ return {
|
|||
"{s:0}Otherwise, {C:green,s:0}#1# in #3#{s:0} chance to give {X:mult,C:white,s:0}X#9#{s:0} Mult",
|
||||
},
|
||||
},
|
||||
j_Roland_misfortune = {
|
||||
name = "Misfortune Cookie",
|
||||
text = {
|
||||
"{C:tarot}Tarot{} cards created",
|
||||
"by {C:tarot}Purple Seals",
|
||||
"become {C:dark_edition}Negative",
|
||||
},
|
||||
},
|
||||
j_Roland_monomino = {
|
||||
name = "Monomino",
|
||||
text = {
|
||||
"Gains {C:money}$#1#{} of",
|
||||
"{C:attention}sell value{} if",
|
||||
"played hand is a",
|
||||
"{C:attention}#2#",
|
||||
},
|
||||
},
|
||||
j_Roland_mrsbones = {
|
||||
name = "Mrs. Bones",
|
||||
text = {
|
||||
|
|
@ -291,14 +213,6 @@ return {
|
|||
name = "Ms. Joker",
|
||||
text = {"{C:chips}+#1#{} Chips"},
|
||||
},
|
||||
j_Roland_nilly = {
|
||||
name = "Nilly",
|
||||
text = {
|
||||
"Toggleable {X:mult,C:white}X0{} Mult",
|
||||
"{C:inactive}(Currently {C:attention}#1#{C:inactive})",
|
||||
"{C:inactive,s:0.75,E:1}Wait... what?",
|
||||
},
|
||||
},
|
||||
j_Roland_oops = {
|
||||
name = "Oops! All 7s",
|
||||
text = {
|
||||
|
|
@ -307,10 +221,6 @@ return {
|
|||
"{C:inactive}(Currently {X:green,C:white}X#2#{C:inactive})",
|
||||
},
|
||||
},
|
||||
j_Roland_phytoestrogens = {
|
||||
name = "Phytoestrogens",
|
||||
text = {"{C:mult}+Chips{} Mult, {X:mult,C:white}X#1#{} Mult"},
|
||||
},
|
||||
j_Roland_sapling = {
|
||||
name = "Sapling",
|
||||
text = {
|
||||
|
|
@ -320,25 +230,16 @@ return {
|
|||
"least {C:attention}#2# suits",
|
||||
},
|
||||
},
|
||||
j_Roland_snowsquall = {
|
||||
name = "Snowsquall",
|
||||
text = {
|
||||
"This Joker gains",
|
||||
"{C:mult}+#1# {}Mult for every",
|
||||
"played {C:dark_edition}Frozen {}card",
|
||||
"{C:inactive}(Currently {C:red}+#2#{C:inactive} Mult)",
|
||||
},
|
||||
},
|
||||
j_Roland_suitable = {
|
||||
name = "Suitable",
|
||||
text = {"{V:1}#1# {}are {C:attention}Wild", "Suit changes", "every round"},
|
||||
j_Roland_srjoker = {
|
||||
name = "Sr. Joker",
|
||||
text = {"{X:mult,C:white}X#1#{} Mult"},
|
||||
},
|
||||
j_Roland_sunny = {
|
||||
name = "Sunny Side Up",
|
||||
text = {
|
||||
"Sell this Joker to",
|
||||
"{C:attention}draw{} the bottom",
|
||||
"card of the deck",
|
||||
"card of the {C:hand}deck",
|
||||
"{C:inactive}(Currently {V:1}#1#{C:inactive}#2#{V:2}#3#{C:inactive})",
|
||||
},
|
||||
},
|
||||
|
|
@ -349,36 +250,6 @@ return {
|
|||
"give {X:red,C:white}X#1#{} Mult",
|
||||
},
|
||||
},
|
||||
j_Roland_trimino = {
|
||||
name = "Trimino",
|
||||
text = {
|
||||
"Copies {C:attention}#1# {C:green}random",
|
||||
"scoring cards and",
|
||||
"{C:red,E:1}self-destructs {}if",
|
||||
"played hand is a",
|
||||
"{C:attention}#2#",
|
||||
},
|
||||
},
|
||||
j_Roland_verdant = {
|
||||
name = "Verdant Leaf",
|
||||
text = {
|
||||
"{X:mult,C:white}X#1#{} Mult",
|
||||
"{C:red}Debuffs {}the {C:attention}first",
|
||||
"{C:attention}#2# {}scored cards",
|
||||
},
|
||||
},
|
||||
j_Roland_violet = {
|
||||
name = "Violet Vessel",
|
||||
text = {
|
||||
"{X:mult,C:white}X#1#{} Mult,",
|
||||
"but {X:mult,C:white}X#2#{} Mult",
|
||||
"{C:attention}before {}scoring",
|
||||
},
|
||||
},
|
||||
j_Roland_venerable = {
|
||||
name = "Venerable Visage",
|
||||
text = {"{X:red,C:white}X#1#{} discards each round"},
|
||||
},
|
||||
j_Roland_yard = {
|
||||
name = "Yard Sale",
|
||||
text = {
|
||||
|
|
@ -404,18 +275,30 @@ return {
|
|||
text = {
|
||||
"{C:attention}Small{} and {C:attention}Big Blinds{} are",
|
||||
"replaced with {C:attention}Boss Blinds",
|
||||
"that are {C:dark_edition}debuffed twice",
|
||||
"",
|
||||
"{C:Bakery_credit_fg_Roland_bakersdozenbagels,s:0.75}Art: BakersDozenBagels",
|
||||
"that are {C:dark_edition}debuffed #1# times",
|
||||
},
|
||||
},
|
||||
sleeve_Roland_blossom_alt = {
|
||||
name = "Efflorescent Sleeve",
|
||||
text = {
|
||||
"{C:dark_edition}Debuff {X:dark_edition,C:white}#1#X<ante>{C:dark_edition} times",
|
||||
"{C:inactive}(Instead of twice)",
|
||||
"",
|
||||
"{C:Bakery_credit_fg_Roland_bakersdozenbagels,s:0.75}Art: BakersDozenBagels",
|
||||
"{C:attention}Blinds{} are {C:dark_edition}debuffed",
|
||||
"{C:dark_edition}({X:dark_edition,C:white}ante{} {X:dark_edition,C:white}number{C:dark_edition}) times",
|
||||
"{C:inactive}(Instead of #1#)",
|
||||
},
|
||||
},
|
||||
sleeve_Roland_go = {
|
||||
name = "Pass GO Sleeve",
|
||||
text = {
|
||||
"Start with a {C:attention}Credit Card",
|
||||
"Set money to {C:money}$0",
|
||||
"when entering the shop",
|
||||
},
|
||||
},
|
||||
sleeve_Roland_go_alt = {
|
||||
name = "Free Parking Sleeve",
|
||||
text = {
|
||||
"Start with an additional",
|
||||
"{X:attention,C:white}#1#{C:attention} Credit Cards",
|
||||
},
|
||||
},
|
||||
sleeve_Roland_swapper = {
|
||||
|
|
@ -423,42 +306,39 @@ return {
|
|||
text = {
|
||||
"{C:tarot}Tarot {}and {C:spectral}Spectral",
|
||||
"cards swap places",
|
||||
"",
|
||||
"{C:Bakery_credit_fg_Roland_bakersdozenbagels,s:0.75}Art: BakersDozenBagels",
|
||||
},
|
||||
},
|
||||
sleeve_Roland_swapper_alt = {
|
||||
name = "Sleeve Swapper",
|
||||
text = {
|
||||
"Swap {C:attention}all {}consumables",
|
||||
"",
|
||||
"{C:Bakery_credit_fg_Roland_bakersdozenbagels,s:0.75}Art: BakersDozenBagels",
|
||||
"{C:attention}All {}consumable",
|
||||
"types swap places",
|
||||
},
|
||||
},
|
||||
},
|
||||
Spectral = {
|
||||
c_Roland_afterimage = {
|
||||
name = "Afterimage",
|
||||
text = {
|
||||
"Add {C:dark_edition}Negative {}to {C:attention}#1#",
|
||||
"selected card in hand",
|
||||
"{C:red}#2#{} hand size",
|
||||
},
|
||||
},
|
||||
c_Roland_dual = {
|
||||
name = "Dual",
|
||||
text = {
|
||||
"Add random seals",
|
||||
"to {C:attention}#1#{} random",
|
||||
"cards in hand",
|
||||
"cards in {C:hands}hand",
|
||||
},
|
||||
},
|
||||
c_Roland_primal = {
|
||||
name = "Primal Force",
|
||||
c_Roland_mirror = {
|
||||
name = "Mirror",
|
||||
text = {
|
||||
"Enhance {C:attention}all {}cards",
|
||||
"held in hand to",
|
||||
"{C:enhanced}Stone Cards",
|
||||
},
|
||||
},
|
||||
c_Roland_refract = {
|
||||
name = "Refract",
|
||||
text = {
|
||||
"Add a {C:dark_edition}Glass Seal",
|
||||
"Add a {C:dark_edition}Glass Tag",
|
||||
"to {C:attention}#1#{} selected",
|
||||
"cards in hand",
|
||||
"card in {C:hands}hand",
|
||||
},
|
||||
},
|
||||
c_Roland_void = {
|
||||
|
|
@ -470,47 +350,6 @@ return {
|
|||
},
|
||||
},
|
||||
},
|
||||
Tag = {
|
||||
tag_Roland_freeze = {
|
||||
name = "Freeze Tag",
|
||||
text = {"Apply {C:dark_edition}Frozen", "to the next {C:attention}#1#", "scored cards"},
|
||||
},
|
||||
tag_Roland_invisible = {
|
||||
name = "Invisible Tag",
|
||||
text = {
|
||||
"{C:attention}Duplicate {}a random",
|
||||
"Joker after {C:attention}#1#{} rounds",
|
||||
"{C:inactive}(Must have room)",
|
||||
"{C:inactive}(Currently {C:attention}#2#{C:inactive}/#1#)",
|
||||
},
|
||||
},
|
||||
},
|
||||
Tarot = {
|
||||
c_Roland_coolheaded = {
|
||||
name = "Coolheaded",
|
||||
text = {
|
||||
"Add {C:dark_edition}Frozen {}to {C:attention}#1#",
|
||||
"selected {C:attention}playing",
|
||||
"{C:attention}card {}or {C:attention}Joker",
|
||||
},
|
||||
},
|
||||
},
|
||||
Voucher = {
|
||||
v_Roland_ceres = {
|
||||
name = "Ceres",
|
||||
text = {
|
||||
"Level up {C:attention}Flush House",
|
||||
"by {C:attention}#1# {}when it is played",
|
||||
},
|
||||
},
|
||||
v_Roland_neptune = {
|
||||
name = "Neptune",
|
||||
text = {
|
||||
"Level up {C:attention}Straight Flush",
|
||||
"by {C:attention}#1# {}when it is played",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
misc = {
|
||||
challenge_names = {
|
||||
|
|
@ -519,39 +358,25 @@ return {
|
|||
c_Roland_Eternally_Crimson = "Eternally Crimson",
|
||||
c_Roland_Eternally_Verdant = "Eternally Verdant",
|
||||
c_Roland_Eternally_Violet = "Eternally Violet",
|
||||
c_Roland_Glass = "Glass House",
|
||||
c_Roland_Go = "Pass GO",
|
||||
c_Roland_Jokerful = "Jokerful",
|
||||
c_Roland_Ornate = "Ornate",
|
||||
c_Roland_Pastries = "Sweet Pastries",
|
||||
c_Roland_Spin_To_Win = "Spin to Win",
|
||||
c_Roland_Showdown = "Showdown",
|
||||
},
|
||||
v_dictionary = {
|
||||
b_Roland_add = "ADD",
|
||||
b_Roland_animated_icon = "Animated Icon (requires restart)",
|
||||
b_Roland_bye = "Bye!",
|
||||
b_Roland_comma = ", ",
|
||||
b_Roland_cool_phones = "cool phones (requires restart)",
|
||||
b_Roland_debuffed = "DEBUFFED",
|
||||
b_Roland_disabled = "Disabled",
|
||||
b_Roland_enabled = "Enabled",
|
||||
b_Roland_entering_shop = "Entering shop!",
|
||||
b_Roland_equinox_assist = "Assist: Only hide text (Equinox)",
|
||||
b_Roland_faster_planets = "Faster Planets",
|
||||
b_Roland_full = "FULL",
|
||||
b_Roland_scribable_basket = "Scribable Basket (overpowered)",
|
||||
b_Roland_harsh_ante_scaling = "Harsh ante scaling (Ante 40+)",
|
||||
b_Roland_illusion_seal = "Allow seals from Illusion voucher",
|
||||
b_Roland_import_funky = "Debug: Import funky.lua",
|
||||
b_Roland_most_common_card = "Rank",
|
||||
b_Roland_no_wild_debuff = "No wild card debuffs",
|
||||
b_Roland_escape = "ESCAPE",
|
||||
b_Roland_fuse = "FUSE",
|
||||
b_Roland_debug_export = "Debug: Import funky.lua to _G",
|
||||
b_Roland_equinox_assist = "Assist: Only hide text during Equinox",
|
||||
b_Roland_most_common_card = "(Rank)",
|
||||
b_Roland_na = "N/A",
|
||||
b_Roland_of = " of ",
|
||||
b_Roland_toggle = "TOGGLE",
|
||||
b_Roland_unassigned = "(Unassigned)",
|
||||
b_Roland_vitriol = "Vitriol (Venerable Visage)",
|
||||
},
|
||||
labels = {
|
||||
Roland_frozen = "Frozen",
|
||||
roland_glass_seal = "Glass Seal",
|
||||
},
|
||||
v_text = {
|
||||
|
|
@ -560,11 +385,10 @@ return {
|
|||
ch_c_Roland_Eternally_Crimson = {"{C:attention}Crimson Heart{}'s effect is active every blind"},
|
||||
ch_c_Roland_Eternally_Verdant = {"{C:attention}Verdant Leaf{}'s effect is active every blind"},
|
||||
ch_c_Roland_Eternally_Violet = {"{C:attention}Violet Vessel{}'s effect is active every blind"},
|
||||
ch_c_Roland_Glass1 = {"Played cards with no seal have a"},
|
||||
ch_c_Roland_Glass2 = {"{C:green}1 in 2{} chance to gain {C:dark_edition}Glass Seal"},
|
||||
ch_c_Roland_Go = {"Set money to {C:money}$0 {}when entering the shop"},
|
||||
ch_c_Roland_Jokerful = {"The only jokers are {C:mult}Joker{} and {C:chips}Ms. Joker"},
|
||||
ch_c_Roland_Ornate = {"Anything vanilla is banned"},
|
||||
ch_c_Roland_Pastries = {"All blinds, cards, and tags are of {C:gold}Bakery{} or {C:blue}Roland"},
|
||||
ch_c_Roland_Showdown = {"Showdown blinds are {C:attention}Venerable Visage"},
|
||||
ch_c_Roland_Showdown_Amber = {"Showdown blinds are {C:attention}Amber Acorn {}(stacks with above)"},
|
||||
ch_c_Roland_Showdown_Cerulean = {"Showdown blinds are {C:attention}Cerulean Bell {}(stacks with above)"},
|
||||
ch_c_Roland_Showdown_Crimson = {"Showdown blinds are {C:attention}Crimson Heart {}(stacks with above)"},
|
||||
|
|
|
|||
54
lovely.toml
|
|
@ -12,12 +12,12 @@ priority = -2
|
|||
target = "game.lua"
|
||||
pattern = "self.GAME.round_resets.blind_choices.Boss = get_new_boss()"
|
||||
position = "before"
|
||||
payload = """
|
||||
payload = '''
|
||||
if G.GAME.modifiers.Roland_blossom_deck then
|
||||
self.GAME.round_resets.blind_choices.Small = get_new_boss()
|
||||
self.GAME.round_resets.blind_choices.Big = get_new_boss()
|
||||
end
|
||||
"""
|
||||
'''
|
||||
match_indent = true
|
||||
|
||||
[[patches]]
|
||||
|
|
@ -25,12 +25,12 @@ match_indent = true
|
|||
target = "functions/common_events.lua"
|
||||
pattern = "G.GAME.round_resets.blind_choices.Boss = get_new_boss()"
|
||||
position = "before"
|
||||
payload = """
|
||||
payload = '''
|
||||
if G.GAME.modifiers.Roland_blossom_deck then
|
||||
G.GAME.round_resets.blind_choices.Small = get_new_boss()
|
||||
G.GAME.round_resets.blind_choices.Big = get_new_boss()
|
||||
end
|
||||
"""
|
||||
'''
|
||||
match_indent = true
|
||||
|
||||
[[patches]]
|
||||
|
|
@ -85,49 +85,3 @@ payload = """if next(SMODS.find_card "j_Roland_misfortune") then
|
|||
card:set_edition "e_negative"
|
||||
end"""
|
||||
match_indent = true
|
||||
|
||||
[[patches]]
|
||||
[patches.pattern]
|
||||
target = "card.lua"
|
||||
pattern = """if self.ability.name == 'Throwback' then
|
||||
self.ability.x_mult = 1 + G.GAME.skips*self.ability.extra
|
||||
end
|
||||
if self.ability.name == "Driver's License" then"""
|
||||
position = "at"
|
||||
payload = """if self.ability.name == 'Throwback' then
|
||||
self.ability.x_mult = 1 + G.GAME.skips*self.ability.extra
|
||||
end
|
||||
if self.ability.name == "Driver's License" and not (self.edition and self.edition.Roland_frozen) then"""
|
||||
match_indent = true
|
||||
|
||||
[[patches]]
|
||||
[patches.pattern]
|
||||
target = "card.lua"
|
||||
pattern = """if self.ability.name == "Steel Joker" then"""
|
||||
position = "at"
|
||||
payload = """if self.ability.name == "Steel Joker" and not (self.edition and self.edition.Roland_frozen) then"""
|
||||
match_indent = true
|
||||
|
||||
[[patches]]
|
||||
[patches.pattern]
|
||||
target = "card.lua"
|
||||
pattern = """if self.ability.name == "Cloud 9" then"""
|
||||
position = "at"
|
||||
payload = """if self.ability.name == "Cloud 9" and not (self.edition and self.edition.Roland_frozen) then"""
|
||||
match_indent = true
|
||||
|
||||
[[patches]]
|
||||
[patches.pattern]
|
||||
target = "card.lua"
|
||||
pattern = """if self.ability.name == "Stone Joker" then"""
|
||||
position = "at"
|
||||
payload = """if self.ability.name == "Stone Joker" and not (self.edition and self.edition.Roland_frozen) then"""
|
||||
match_indent = true
|
||||
|
||||
[[patches]]
|
||||
[patches.regex]
|
||||
target = "card.lua"
|
||||
pattern = "math\\.floor\\(\\(G\\.GAME\\.dollars \\+ \\(G\\.GAME\\.dollar_buffer or 0\\)\\)/self\\.ability\\.extra\\.dollars\\)"
|
||||
position = "at"
|
||||
payload = "G.P_CENTERS.j_bootstraps:mult(self)"
|
||||
match_indent = true
|
||||
|
|
|
|||
|
|
@ -3,20 +3,20 @@
|
|||
"id": "Roland",
|
||||
"name": "Roland",
|
||||
"prefix": "Roland",
|
||||
"version": "2.9.28",
|
||||
"badge_colour": "8BE9FD",
|
||||
"display_name": "Roland",
|
||||
"main_file": "src/main.lua",
|
||||
"badge_text_colour": "44475A",
|
||||
"description": "Adds mechanics that are meant to have interesting interactions with the base game. Not meant to be balanced, but not entirely broken either.",
|
||||
"provides": [],
|
||||
"conflicts": [],
|
||||
"author": [
|
||||
"Emik"
|
||||
],
|
||||
"version": "2.0.0~dev",
|
||||
"badge_colour": "8BE9FD",
|
||||
"main_file": "src/main.lua",
|
||||
"badge_text_colour": "44475A",
|
||||
"display_name": "Roland",
|
||||
"description": "Adds several disconnected funny ideas I had in my head that I couldn't resist implementing in the game.",
|
||||
"provides": [],
|
||||
"conflicts": [],
|
||||
"dependencies": [
|
||||
"Steamodded (>=1.0.0~BETA-1606b)",
|
||||
"Steamodded (>=1.*)",
|
||||
"Lovely (>=0.6)",
|
||||
"Bakery (>=3.2.0~*)"
|
||||
"Bakery (>=1.3.2~*)"
|
||||
]
|
||||
}
|
||||
1
refs/Cryptid
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../../Cryptid/
|
||||
100
src/back.lua
|
|
@ -1,4 +1,4 @@
|
|||
local f, q = (... or require "lib.shared")[1], (... or require "lib.shared")[2]
|
||||
local f, q = unpack(... or require "lib.shared")
|
||||
|
||||
local function save(ret)
|
||||
q(save_run)
|
||||
|
|
@ -8,30 +8,45 @@ end
|
|||
local back = (function()
|
||||
local x = 0
|
||||
|
||||
---@param tbl SMODS.Back|{is_alt: (fun(self: self): boolean), alt_apply?: fun(self: SMODS.Back|table, back: Back|table), alt_calculate?: fun(self: SMODS.Back|table, back: Back|table, context: CalcContext|table): table?, boolean?}
|
||||
---@param tbl SMODS.Back|{is_alt: function, alt_apply?: fun(self: SMODS.Back|table, back: Back|table), alt_calculate?: fun(self: SMODS.Back|table, back: Back|table, context: CalcContext|table): table?, boolean?}
|
||||
return function(tbl)
|
||||
local key = tbl.key
|
||||
local apply = tbl.apply
|
||||
local calculate = tbl.calculate
|
||||
|
||||
function tbl:apply(...)
|
||||
local _ = apply and G.GAME.selected_sleeve ~= "sleeve_Roland_" .. key and save(apply(self, ...))
|
||||
---@diagnostic disable-next-line: redundant-return-value
|
||||
return apply and G.GAME.selected_sleeve ~= "sleeve_Roland_" .. key and save(apply(self, ...))
|
||||
end
|
||||
|
||||
function tbl:calculate(...)
|
||||
return (calculate and G.GAME.selected_sleeve ~= "sleeve_Roland_" .. key) and calculate(self, ...) or nil
|
||||
---@diagnostic disable-next-line: return-type-mismatch
|
||||
return calculate and G.GAME.selected_sleeve ~= "sleeve_Roland_" .. key and calculate(self, ...)
|
||||
end
|
||||
|
||||
tbl.pos = {x = x, y = 0}
|
||||
tbl.is_alt = f.fals
|
||||
tbl.atlas = "back"
|
||||
x = x + 1
|
||||
local back = q(SMODS.Back(tbl))
|
||||
|
||||
local _ = CardSleeves and CardSleeves.Sleeve {
|
||||
-- This API intends that you share the same functions for apply/calculate,
|
||||
-- meaning that this may be called to check if a deck/sleeve combo is used even
|
||||
-- when we are from the deck context. We add this to prevent accidental calls to nil.
|
||||
function tbl:is_alt()
|
||||
return false
|
||||
end
|
||||
|
||||
SMODS.Back(tbl)
|
||||
x = x + 1
|
||||
|
||||
---@diagnostic disable-next-line: undefined-global
|
||||
if not CardSleeves then
|
||||
return
|
||||
end
|
||||
|
||||
---@diagnostic disable-next-line: undefined-global
|
||||
CardSleeves.Sleeve {
|
||||
key = key,
|
||||
pos = tbl.pos,
|
||||
atlas = "sleeve",
|
||||
atlas = "back",
|
||||
config = tbl.config and f(tbl.config):table() or nil,
|
||||
loc_vars = function(self, ...)
|
||||
local ret = tbl.loc_vars and tbl.loc_vars(self, ...) or {}
|
||||
|
|
@ -48,8 +63,6 @@ local back = (function()
|
|||
return self.get_current_deck_key() == "b_Roland_" .. key
|
||||
end,
|
||||
}
|
||||
|
||||
return back
|
||||
end
|
||||
end)()
|
||||
|
||||
|
|
@ -60,20 +73,12 @@ SMODS.Atlas {
|
|||
py = 95,
|
||||
}
|
||||
|
||||
local _ = CardSleeves and SMODS.Atlas {
|
||||
key = "sleeve",
|
||||
path = "sleeve.png",
|
||||
px = 73,
|
||||
py = 95,
|
||||
}
|
||||
|
||||
back {
|
||||
key = "blossom",
|
||||
pronouns = "any_all",
|
||||
config = {extra = {alt_times = 4, times = 2}},
|
||||
attributes = {"boss_blind"},
|
||||
config = {extra = {times = 2}},
|
||||
loc_vars = function(self, _, _)
|
||||
return {vars = {self.config.extra.alt_times}}
|
||||
return {vars = {self.config.extra.times}}
|
||||
end,
|
||||
apply = function(_, _)
|
||||
G.GAME.modifiers.Roland_blossom_deck = true
|
||||
|
|
@ -89,41 +94,78 @@ back {
|
|||
return
|
||||
end
|
||||
|
||||
local count = self:is_alt() and
|
||||
G.GAME.round_resets.ante * self.config.extra.alt_times or
|
||||
self.config.extra.times
|
||||
local count = self:is_alt() and G.GAME.round_resets.ante or self.config.extra.times
|
||||
|
||||
f(count):each(function(i)
|
||||
local _ = i == 1 and G.GAME.blind:disable()
|
||||
for _ = 1, count do
|
||||
G.GAME.blind:disable()
|
||||
|
||||
q {
|
||||
delay = 0.4,
|
||||
func = function()
|
||||
local _ = i ~= 1 and G.GAME.blind:disable()
|
||||
SMODS.calculate_effect({message = localize "ph_boss_disabled"}, card)
|
||||
G.GAME.blind:wiggle()
|
||||
play_sound "timpani"
|
||||
end,
|
||||
}
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
back {
|
||||
key = "go",
|
||||
pronouns = "he_him",
|
||||
config = {extra = {times = 1, alt_times = 5}},
|
||||
loc_vars = function(self, info_queue, _)
|
||||
local _ = info_queue and table.insert(info_queue, G.P_CENTERS.j_credit_card)
|
||||
return {vars = {self.config.extra.alt_times - self.config.extra.times}}
|
||||
end,
|
||||
apply = function(self)
|
||||
q(function()
|
||||
local count = self:is_alt() and self.config.extra.alt_times or self.config.extra.times
|
||||
|
||||
for _ = 1, count do
|
||||
local c = create_card("Joker", G.jokers, nil, nil, nil, nil, "j_credit_card", "Roland_go")
|
||||
c:add_to_deck()
|
||||
c:start_materialize()
|
||||
G.jokers:emplace(c)
|
||||
end
|
||||
end)
|
||||
end,
|
||||
calculate = function(_, card, context)
|
||||
if not context.starting_shop then
|
||||
return
|
||||
end
|
||||
|
||||
ease_dollars(-G.GAME.dollars)
|
||||
|
||||
attention_text {
|
||||
text = localize "k_nope_ex",
|
||||
backdrop_colour = G.C.MONEY,
|
||||
offset = {x = 0, y = 0},
|
||||
silent = true,
|
||||
major = card,
|
||||
align = "cm",
|
||||
scale = 1.3,
|
||||
hold = 1.4,
|
||||
}
|
||||
end,
|
||||
}
|
||||
|
||||
back {
|
||||
key = "swapper",
|
||||
pronouns = "he_him",
|
||||
attributes = {"spectral", "tarot"},
|
||||
apply = function(self)
|
||||
local modifiers = G.GAME.modifiers
|
||||
modifiers.Roland_swapper_deck = true
|
||||
modifiers.Roland_alt_swapper_deck = modifiers.Roland_alt_swapper_deck or self:is_alt()
|
||||
end,
|
||||
calculate = f.noop,
|
||||
calculate = function() end,
|
||||
}
|
||||
|
||||
local swapper = {Spectral = "Tarot", Tarot = "Spectral"}
|
||||
local orig_create_card = create_card
|
||||
|
||||
---@diagnostic disable-next-line: lowercase-global
|
||||
function create_card(_type, ...)
|
||||
if not G.GAME.modifiers.Roland_swapper_deck then
|
||||
return orig_create_card(_type, ...)
|
||||
|
|
|
|||
276
src/blind.lua
|
|
@ -1,16 +1,16 @@
|
|||
local f, q = (... or require "lib.shared")[1], (... or require "lib.shared")[2]
|
||||
local f, q = unpack(... or require "lib.shared")
|
||||
|
||||
local blind = (function()
|
||||
local y = 0
|
||||
|
||||
---@param tbl SMODS.Blind|{idea?: string}
|
||||
---@param tbl SMODS.Blind
|
||||
---@return SMODS.Blind
|
||||
return function(tbl)
|
||||
tbl.idea = tbl.idea and "Roland_" .. tbl.idea or nil
|
||||
tbl.pos = {x = 0, y = y}
|
||||
tbl.atlas = "blind"
|
||||
local ret = SMODS.Blind(tbl)
|
||||
y = y + 1
|
||||
return q(SMODS.Blind(tbl))
|
||||
return ret
|
||||
end
|
||||
end)()
|
||||
|
||||
|
|
@ -23,19 +23,37 @@ SMODS.Atlas {
|
|||
atlas_table = "ANIMATION_ATLAS",
|
||||
}
|
||||
|
||||
SMODS.Sound {key = "kick", path = "kick.ogg"}
|
||||
SMODS.Sound {
|
||||
key = "kick",
|
||||
path = "kick.ogg",
|
||||
}
|
||||
|
||||
local function common_rank()
|
||||
local tally, to_name = {}, {}
|
||||
local tally = {}
|
||||
local to_name = {}
|
||||
|
||||
f(G.playing_cards):where(SMODS.has_no_rank, false):each(function(v)
|
||||
--- Tallies up a card area's cards.
|
||||
---@param card_area CardArea
|
||||
local function tally_up(card_area)
|
||||
f(card_area.cards):where(function(v)
|
||||
return not SMODS.has_no_rank(v)
|
||||
end):each(function(v)
|
||||
local id = v:get_id()
|
||||
to_name[id] = v.base.value
|
||||
tally[id] = (tally[id] or 0) + 1
|
||||
end)
|
||||
end
|
||||
|
||||
local max_key = f(tally, pairs):fold({-1 / 0, -1 / 0}, function(a, v, k)
|
||||
return (v > a[1] or v == a[1] and k > a[2]) and {v, k} or a
|
||||
tally_up(G.deck)
|
||||
tally_up(G.hand)
|
||||
tally_up(G.discard)
|
||||
|
||||
local max_key = f(tally):fold({-1 / 0, -1 / 0}, function(a, v, k)
|
||||
if v > a[1] or k > a[2] and v == a[1] then
|
||||
return {v, k}
|
||||
end
|
||||
|
||||
return a
|
||||
end)[2]
|
||||
|
||||
return max_key, to_name[max_key]
|
||||
|
|
@ -52,35 +70,7 @@ end
|
|||
|
||||
local function has_enhancement(card)
|
||||
local e = SMODS.get_enhancements(card)
|
||||
return e and next(e)
|
||||
end
|
||||
|
||||
local function set_freeze(state)
|
||||
local function copy(x)
|
||||
return type(x) == "table" and f(x):map(copy):table() or x
|
||||
end
|
||||
|
||||
---@param card Card|{ Roland_blizzard: true|nil }
|
||||
return function(card)
|
||||
if not card.Roland_blizzard and card.edition and card.edition.Roland_frozen then
|
||||
return
|
||||
end
|
||||
|
||||
local last_edition = card.Roland_blizzard
|
||||
card.Roland_blizzard = state and (copy(card.edition) or true) or nil
|
||||
|
||||
q {
|
||||
delay = 0.1,
|
||||
func = function()
|
||||
local edition = state and {Roland_frozen = true} or last_edition or card.Roland_blizzard
|
||||
card:set_edition(edition ~= true and edition or nil)
|
||||
end,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
local function sort_by_enhancement(v1, v2)
|
||||
return has_enhancement(v1) and not has_enhancement(v2)
|
||||
return not not (e and next(e))
|
||||
end
|
||||
|
||||
local function hsv_to_rgb(h, s, v)
|
||||
|
|
@ -122,23 +112,28 @@ blind {
|
|||
boss_colour = HEX "0291fbff",
|
||||
pronouns = "she_her",
|
||||
config = {draw = 5},
|
||||
defeat = function()
|
||||
G.GAME.Roland_nimble_disabled = nil
|
||||
end,
|
||||
disable = function()
|
||||
G.GAME.Roland_nimble_disabled = true
|
||||
end,
|
||||
drawn_to_hand = function(self)
|
||||
local function force_hand()
|
||||
if is_locked() then
|
||||
return false
|
||||
end
|
||||
|
||||
f(G.hand.cards):take(self.config.draw):each(function(v)
|
||||
f(G.hand.cards, ipairs):take(self.config.draw):each(function(v)
|
||||
G.hand:add_to_highlighted(v, true)
|
||||
end)
|
||||
|
||||
G.FUNCS.play_cards_from_highlighted()
|
||||
G.FUNCS.play_cards_from_highlighted(nil)
|
||||
self:disable()
|
||||
end
|
||||
|
||||
local g = G.GAME
|
||||
|
||||
if not g.blind.disabled and not g.Roland_nimble_disabled then
|
||||
g.Roland_nimble_disabled = true
|
||||
if not G.GAME.Roland_nimble_disabled then
|
||||
G.GAME.Roland_nimble_disabled = true
|
||||
q {func = force_hand, blocking = false}
|
||||
end
|
||||
end,
|
||||
|
|
@ -153,14 +148,29 @@ blind {
|
|||
boss_colour = HEX "ff7f3dff",
|
||||
pronouns = "any_all",
|
||||
disable = function()
|
||||
G.FUNCS.draw_from_hand_to_deck()
|
||||
q(function()
|
||||
f(G.hand.cards):each(function(v, i)
|
||||
draw_card(G.hand, G.deck, i / #G.hand.cards * 100, "up", false, v)
|
||||
end)
|
||||
end)
|
||||
|
||||
q(function()
|
||||
pseudoshuffle(G.deck.cards, pseudoseed "RolandFalseShuffle")
|
||||
end)
|
||||
end,
|
||||
calculate = function(_, b, context)
|
||||
local _ = not b.disabled and context.drawing_cards and table.sort(G.deck.cards, sort_by_enhancement)
|
||||
if b.disabled or not context.drawing_cards then
|
||||
return
|
||||
end
|
||||
|
||||
b:wiggle()
|
||||
|
||||
table.sort(
|
||||
G.deck.cards,
|
||||
function(v1, v2)
|
||||
return has_enhancement(v1) and not has_enhancement(v2)
|
||||
end
|
||||
)
|
||||
end,
|
||||
in_pool = function()
|
||||
return G.playing_cards and f(G.playing_cards):any(has_enhancement)
|
||||
|
|
@ -174,7 +184,13 @@ blind {
|
|||
pronouns = "he_they",
|
||||
disable = function()
|
||||
-- Ensures that this runs after 'set_blind' since it also gets added to queue.
|
||||
q {delay = 0.8, trigger = "after", func = G.FUNCS.draw_from_discard_to_deck}
|
||||
q {
|
||||
delay = 0.8,
|
||||
trigger = "after",
|
||||
func = function()
|
||||
G.FUNCS.draw_from_discard_to_deck()
|
||||
end,
|
||||
}
|
||||
end,
|
||||
set_blind = function()
|
||||
-- Allows the background to ease in first before drawing cards.
|
||||
|
|
@ -207,7 +223,7 @@ blind {
|
|||
local cards_added = {}
|
||||
local count = #G.hand.highlighted
|
||||
|
||||
f(G.hand.highlighted):take(count):each(function(v, i)
|
||||
f(G.hand.highlighted, ipairs):take(count):each(function(v, i)
|
||||
local copy = copy_card(v)
|
||||
copy:add_to_deck()
|
||||
table.insert(G.hand, copy)
|
||||
|
|
@ -216,42 +232,12 @@ blind {
|
|||
draw_card(G.hand, G.discard, i / count * 100, "down", false, copy, nil, nil, true)
|
||||
end)
|
||||
|
||||
if not next(cards_added) then
|
||||
return
|
||||
end
|
||||
|
||||
b:wiggle()
|
||||
b.triggered = true
|
||||
playing_card_joker_effects(cards_added)
|
||||
end,
|
||||
}
|
||||
|
||||
blind {
|
||||
key = "blizzard",
|
||||
idea = "redstoad",
|
||||
boss = {min = 3},
|
||||
boss_colour = HEX "102a41ff",
|
||||
pronouns = "it_its",
|
||||
defeat = function(self)
|
||||
self.cards():where "Roland_blizzard":each(set_freeze())
|
||||
G.GAME.blind.disabled = true
|
||||
end,
|
||||
disable = function(self)
|
||||
self:defeat()
|
||||
end,
|
||||
calculate = function(self, b, context)
|
||||
return not b.disabled and
|
||||
context.hand_drawn and
|
||||
self.cards()
|
||||
:where("Roland_blizzard", false)
|
||||
:where("facing", "front")
|
||||
:each(set_freeze(true)) or nil
|
||||
end,
|
||||
cards = function()
|
||||
return f(G):where(getmetatable, CardArea):flatmap("cards", ipairs)
|
||||
end,
|
||||
}
|
||||
|
||||
blind {
|
||||
key = "tranquilizer",
|
||||
boss = {min = 6},
|
||||
|
|
@ -269,6 +255,9 @@ blind {
|
|||
local _, name = common_rank()
|
||||
return {vars = {localize(name or "Ace", "ranks")}}
|
||||
end,
|
||||
disable = function(self)
|
||||
self.disabled = true
|
||||
end,
|
||||
calculate = function(self, b, context)
|
||||
if not context.card_added and
|
||||
not context.drawing_cards and
|
||||
|
|
@ -299,12 +288,9 @@ blind {
|
|||
b:set_text()
|
||||
end
|
||||
end,
|
||||
disable = function()
|
||||
G.GAME.blind.disabled = true
|
||||
end,
|
||||
recalc_debuff = function(self, card)
|
||||
local id, _ = common_rank()
|
||||
local ret = not G.GAME.blind.disabled and id == card:get_id()
|
||||
local ret = not self.disabled and id == card:get_id()
|
||||
self.triggered = ret
|
||||
return ret
|
||||
end,
|
||||
|
|
@ -312,7 +298,7 @@ blind {
|
|||
|
||||
blind {
|
||||
key = "improbable",
|
||||
boss = {min = 3},
|
||||
boss = {min = 4},
|
||||
boss_colour = HEX "009966ff",
|
||||
pronouns = "it_its",
|
||||
mult = 2,
|
||||
|
|
@ -327,46 +313,21 @@ blind {
|
|||
if cry_prob then
|
||||
local orig_cry_prob = cry_prob
|
||||
|
||||
---@diagnostic disable-next-line: lowercase-global
|
||||
function cry_prob(...)
|
||||
return G.GAME.modifiers.Roland_improbable and 0 or orig_cry_prob(...)
|
||||
end
|
||||
end
|
||||
|
||||
function SMODS.current_mod:calculate(context)
|
||||
local _ = type(G.calccontext) == "function" and G.calccontext(context)
|
||||
|
||||
if type(G.calc) == "function" then
|
||||
G.calc = {G.calc}
|
||||
if context.setting_blind and G.GAME.blind.name == "bl_mp_nemesis" then
|
||||
local modifiers = G.GAME.modifiers
|
||||
modifiers.Roland_martingale_seed = (modifiers.Roland_martingale_seed or 0) + 1
|
||||
end
|
||||
|
||||
if type(G.calc) == "table" then
|
||||
local str
|
||||
|
||||
f(context):keys():map(f.index_into(G.calc)):where(type, "function"):each(function(v)
|
||||
str = str or f(context):keys():string()
|
||||
v(str)
|
||||
end)
|
||||
|
||||
local _ = not str and type(G.calc[1]) == "function" and G.calc[1](f(context):keys():string())
|
||||
end
|
||||
|
||||
local _ = context.before and
|
||||
f {"v_Roland_ceres", "v_Roland_neptune"}
|
||||
:where(f.index_into(G.GAME.used_vouchers))
|
||||
:map(f.index_into(G.P_CENTERS))
|
||||
:where("config.extra.hand_type", context.scoring_name)
|
||||
:pun "SMODS.Voucher"
|
||||
:each(function(v, _)
|
||||
SMODS.smart_level_up_hand(nil, v.config.extra.hand_type, nil, v.config.extra.amount)
|
||||
end)
|
||||
|
||||
local _ = type(G.calc) == "function" and G.calc(f(context):keys():string())
|
||||
local improbable, orig = G.GAME.modifiers.Roland_improbable, G.GAME.probabilities
|
||||
|
||||
local _ = context.end_of_round and
|
||||
context.main_eval and
|
||||
not context.blueprint and
|
||||
G.P_TAGS.tag_Roland_invisible.increment()
|
||||
|
||||
-- Normally unreachable since we set it to nil ourselves,
|
||||
-- but other mods may want to use this modifier.
|
||||
if improbable == false then
|
||||
|
|
@ -421,6 +382,7 @@ end
|
|||
|
||||
local orig_draw = Card.draw
|
||||
|
||||
---@diagnostic disable-next-line: duplicate-set-field
|
||||
function Card:draw(...)
|
||||
if equinox() and
|
||||
not SMODS.Mods.Roland.config.equinox_assist and
|
||||
|
|
@ -434,6 +396,7 @@ end
|
|||
|
||||
local orig_draw_self = UIElement.draw_self
|
||||
|
||||
---@diagnostic disable-next-line: duplicate-set-field
|
||||
function UIElement:draw_self(...)
|
||||
if equinox() and
|
||||
not self.config.button and
|
||||
|
|
@ -449,7 +412,6 @@ local venerable_visage = blind {
|
|||
boss = {showdown = true},
|
||||
boss_colour = HEX "f6f6f2ff",
|
||||
pronouns = "any_all",
|
||||
dollars = 8,
|
||||
calculate = function(self, b, context)
|
||||
if b.disabled then
|
||||
return
|
||||
|
|
@ -462,10 +424,7 @@ local venerable_visage = blind {
|
|||
end)
|
||||
end
|
||||
|
||||
if b.Roland_vitriol or
|
||||
not context.end_of_round or
|
||||
G.GAME.chips == G.GAME.blind.chips or
|
||||
not (next(G.deck.cards) or next(G.hand.cards)) then
|
||||
if b.Roland_vitriol or not context.end_of_round or not next(G.deck.cards) or not next(G.hand.cards) then
|
||||
return
|
||||
end
|
||||
|
||||
|
|
@ -481,31 +440,15 @@ local venerable_visage = blind {
|
|||
}
|
||||
end,
|
||||
vitriol = function(b)
|
||||
local vitriol = SMODS.Mods.Roland.config.vitriol
|
||||
local resize_to_w, resize_to_h = 320, 200
|
||||
local is_fullscreen = love.window.getFullscreen()
|
||||
|
||||
if vitriol then
|
||||
love.window.setFullscreen(false)
|
||||
delay(1.5)
|
||||
end
|
||||
|
||||
local function jitter()
|
||||
local x, y = love.window.getDesktopDimensions()
|
||||
|
||||
return pseudorandom(pseudoseed "RolandVenerableVisageX", 0, x) - x / 2,
|
||||
pseudorandom(pseudoseed "RolandVenerableVisageY", 0, y) - y / 2
|
||||
end
|
||||
|
||||
if type(b) == "table" and type(b.wiggle) == "function" then
|
||||
b:wiggle()
|
||||
end
|
||||
|
||||
f(G.playing_cards):each(function(v, k)
|
||||
return v.area ~= G.hand and draw_card(v.area, G.hand, k * 100 / #G.playing_cards, "up", true, v)
|
||||
end)
|
||||
|
||||
local fail = G.localization.descriptions.Blind.bl_Roland_venerable_visage.fail
|
||||
local speed = 0.1
|
||||
|
||||
SMODS.draw_cards(#G.deck.cards)
|
||||
play_sound("gong", 0.6)
|
||||
|
||||
attention_text {
|
||||
text = pseudorandom_element(fail, pseudoseed "RolandVenerableVisage"),
|
||||
|
|
@ -515,55 +458,52 @@ local venerable_visage = blind {
|
|||
hold = 2,
|
||||
}
|
||||
|
||||
f {0.15, 0.3, 0.45, 0.6}:each(function(v)
|
||||
play_sound("gong", v)
|
||||
end)
|
||||
delay(1)
|
||||
|
||||
---@type number, number, table
|
||||
local w, h, flags = love.window.getMode()
|
||||
local len = #G.playing_cards
|
||||
|
||||
if vitriol then
|
||||
love.window.setMode(resize_to_w, resize_to_h)
|
||||
love.resize(resize_to_w, resize_to_h)
|
||||
end
|
||||
|
||||
local x, y = love.window.getPosition()
|
||||
|
||||
f(G.playing_cards):each(function(v, i)
|
||||
f(G.playing_cards):each(function(v)
|
||||
q {
|
||||
trigger = "before",
|
||||
delay = 6 / len,
|
||||
delay = speed,
|
||||
func = function()
|
||||
if vitriol then
|
||||
local x_random, y_random = jitter()
|
||||
love.window.setPosition(x + x_random * i / len, y + y_random * i / len)
|
||||
end
|
||||
|
||||
v:start_dissolve()
|
||||
v:shatter()
|
||||
b:wiggle()
|
||||
end,
|
||||
}
|
||||
end)
|
||||
|
||||
local _ = vitriol and q {
|
||||
trigger = "before",
|
||||
delay = 1.5,
|
||||
delay(1)
|
||||
|
||||
f(G.P_CARDS):each(function(v)
|
||||
q {
|
||||
delay = speed,
|
||||
func = function()
|
||||
love.window.setPosition(x, y)
|
||||
love.window.setMode(w, h, flags)
|
||||
love.resize(w, h)
|
||||
love.window.setFullscreen(is_fullscreen)
|
||||
G.playing_card = (G.playing_card and G.playing_card + 1) or 1
|
||||
|
||||
local card = Card(
|
||||
b and b.T.x or 0,
|
||||
b and b.T.y or 0,
|
||||
G.CARD_W,
|
||||
G.CARD_H,
|
||||
v,
|
||||
G.P_CENTERS.m_Bakery_Curse or G.P_CENTERS.c_base,
|
||||
{playing_card = G.playing_card}
|
||||
)
|
||||
|
||||
table.insert(G.playing_cards, card)
|
||||
G.deck:emplace(card)
|
||||
play_sound "card1"
|
||||
card:add_to_deck()
|
||||
end,
|
||||
}
|
||||
end)
|
||||
|
||||
delay(1.5)
|
||||
delay(1)
|
||||
end,
|
||||
}
|
||||
|
||||
local orig_game_draw = Game.draw
|
||||
|
||||
---@diagnostic disable-next-line: duplicate-set-field
|
||||
function Game.draw(...)
|
||||
orig_game_draw(...)
|
||||
local boss_colour = venerable_visage.boss_colour
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
local f, q = (... or require "lib.shared")[1], (... or require "lib.shared")[2]
|
||||
local f, q = unpack(... or require "lib.shared")
|
||||
|
||||
local function bans()
|
||||
return {banned_cards = {}, banned_tags = {}, banned_other = {}}
|
||||
|
|
@ -30,6 +30,10 @@ local function is_center_banned_from_pastry(v)
|
|||
return arcana_boosters[v.key] or pastries_targets[v.set] and is_banned_from_pastry(v)
|
||||
end
|
||||
|
||||
local function is_joker(v)
|
||||
return v.set == "Joker" and not ({j_joker = true, j_Roland_msjoker = true})[v.key]
|
||||
end
|
||||
|
||||
local function is_showdown_except(key)
|
||||
---@param v SMODS.Blind
|
||||
---@param k string
|
||||
|
|
@ -39,68 +43,27 @@ local function is_showdown_except(key)
|
|||
end
|
||||
end
|
||||
|
||||
local pastries, amber, cerulean, crimson, verdant, violet =
|
||||
bans(), bans(), bans(), bans(), bans(), bans()
|
||||
|
||||
SMODS.Challenge {
|
||||
key = "Glass",
|
||||
rules = {custom = {{id = "Roland_Glass1"}, {id = "Roland_Glass2"}}},
|
||||
pronouns = "they_them",
|
||||
config = {extra = {odds = 2}},
|
||||
calculate = function(self, context)
|
||||
if not context.after or context.blueprint_card then
|
||||
return
|
||||
end
|
||||
|
||||
f(G.play.cards):where(function(v)
|
||||
return not v:get_seal(true) and
|
||||
SMODS.pseudorandom_probability(self, self.key, 1, self.config.extra.odds, self.key)
|
||||
end):each(function(v)
|
||||
v:set_seal "Roland_glass"
|
||||
local function is_vanilla(v)
|
||||
return v.set and not v.mod and f(G.P_CENTERS):concat(G.P_CARDS, G.P_TAGS):any(function(c)
|
||||
return c.mod and not c.in_pool and c.set == v.set
|
||||
end)
|
||||
end,
|
||||
end
|
||||
|
||||
local jokerful, vanillas, pastries, amber, cerulean, crimson, verdant, violet, final
|
||||
= bans(), bans(), bans(), bans(), bans(), bans(), bans(), bans(), bans()
|
||||
|
||||
SMODS.Challenge {
|
||||
key = "Jokerful",
|
||||
rules = {custom = {{id = "Roland_Jokerful"}}},
|
||||
restrictions = jokerful,
|
||||
pronouns = "he_him",
|
||||
}
|
||||
|
||||
SMODS.Challenge {
|
||||
key = "Go",
|
||||
rules = {custom = {{id = "Roland_Go"}}},
|
||||
jokers = {{id = "j_credit_card"}},
|
||||
pronouns = "he_him",
|
||||
calculate = function(self, context)
|
||||
if context.starting_shop then
|
||||
ease_dollars(-G.GAME.dollars)
|
||||
|
||||
attention_text {
|
||||
text = localize "k_nope_ex",
|
||||
backdrop_colour = G.C.MONEY,
|
||||
offset = {x = 0, y = 0},
|
||||
silent = true,
|
||||
major = self,
|
||||
align = "cm",
|
||||
scale = 1.3,
|
||||
hold = 1.4,
|
||||
}
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local spin_to_win = SMODS.Challenge {
|
||||
key = "Spin_To_Win",
|
||||
jokers = f(4):map(f.const {id = "j_joker", eternal = true}):table(),
|
||||
restrictions = {banned_cards = {{id = "c_Roland_coolheaded"}}},
|
||||
pronouns = "they_them",
|
||||
apply = function(self)
|
||||
self.rotation = 0
|
||||
end,
|
||||
calculate = function(self, context)
|
||||
if not context.card_added or context.card.config.center.key ~= "j_Bakery_Spinner" then
|
||||
return
|
||||
end
|
||||
|
||||
context.card.ability.extra.rotation = self.rotation
|
||||
self.rotation = self.rotation + 1
|
||||
end,
|
||||
rotation = 0,
|
||||
key = "Ornate",
|
||||
rules = {custom = {{id = "Roland_Ornate"}}},
|
||||
restrictions = vanillas,
|
||||
pronouns = "any_all",
|
||||
}
|
||||
|
||||
SMODS.Challenge {
|
||||
|
|
@ -110,12 +73,12 @@ SMODS.Challenge {
|
|||
pronouns = "she_them",
|
||||
}
|
||||
|
||||
local finalizers = {
|
||||
|
||||
SMODS.Challenge {
|
||||
key = "Eternally_Amber",
|
||||
rules = {custom = {{id = "Roland_Eternally_Amber"}, {id = "Roland_Showdown_Amber"}}},
|
||||
jokers = {{id = "j_Roland_amber"}},
|
||||
restrictions = amber,
|
||||
pronouns = "they_them",
|
||||
calculate = function(_, context)
|
||||
local function slide(pitch)
|
||||
q(function()
|
||||
|
|
@ -147,14 +110,11 @@ SMODS.Challenge {
|
|||
end,
|
||||
}
|
||||
end,
|
||||
}
|
||||
|
||||
},
|
||||
SMODS.Challenge {
|
||||
key = "Eternally_Cerulean",
|
||||
rules = {custom = {{id = "Roland_Eternally_Cerulean"}, {id = "Roland_Showdown_Cerulean"}}},
|
||||
jokers = {{id = "j_Roland_cerulean"}},
|
||||
restrictions = cerulean,
|
||||
pronouns = "she_her",
|
||||
calculate = function(_, context)
|
||||
if not context.hand_drawn then
|
||||
return
|
||||
|
|
@ -174,22 +134,20 @@ SMODS.Challenge {
|
|||
G.hand:add_to_highlighted(v)
|
||||
end)
|
||||
end,
|
||||
}
|
||||
|
||||
},
|
||||
SMODS.Challenge {
|
||||
key = "Eternally_Crimson",
|
||||
rules = {custom = {{id = "Roland_Eternally_Crimson"}, {id = "Roland_Showdown_Crimson"}}},
|
||||
jokers = {{id = "j_Roland_crimson"}},
|
||||
restrictions = crimson,
|
||||
pronouns = "she_her",
|
||||
calculate = function(_, context)
|
||||
local _ = context.blind_defeated and f(G.jokers.cards):each(function(v)
|
||||
v.ability.Roland_crimson_heart_chosen = nil
|
||||
end)
|
||||
|
||||
local mod = G.GAME.modifiers
|
||||
mod.Roland_Eternally_Crimson = context.setting_blind and true or mod.Roland_Eternally_Crimson
|
||||
mod.Roland_Eternally_Crimson = not context.setting_blind and mod.Roland_Eternally_Crimson or nil
|
||||
local debuff = context.debuff_card
|
||||
---@type (SMODS.Joker|{ability?: {Roland_crimson_heart_chosen: boolean?}, debuff: boolean?})[]
|
||||
local cards = G.jokers.cards
|
||||
|
||||
if debuff and
|
||||
|
|
@ -217,7 +175,9 @@ SMODS.Challenge {
|
|||
local _ = v.debuff and SMODS.recalc_debuff(v)
|
||||
end)
|
||||
|
||||
jokers = next(jokers) and jokers or f(cards):where("debuff", false):map(function(v)
|
||||
jokers = next(jokers) and jokers or f(cards):where(function(v)
|
||||
return not v.debuff
|
||||
end):map(function(v)
|
||||
local _ = not prev[v] and table.insert(jokers, v)
|
||||
return v
|
||||
end):table()
|
||||
|
|
@ -234,14 +194,11 @@ SMODS.Challenge {
|
|||
mod.Roland_Eternally_Crimson = not context.hand_drawn and
|
||||
mod.Roland_Eternally_Crimson or nil
|
||||
end,
|
||||
}
|
||||
|
||||
},
|
||||
SMODS.Challenge {
|
||||
key = "Eternally_Verdant",
|
||||
rules = {custom = {{id = "Roland_Eternally_Verdant"}, {id = "Roland_Showdown_Verdant"}}},
|
||||
jokers = {{id = "j_Roland_verdant"}},
|
||||
restrictions = verdant,
|
||||
pronouns = "she_her",
|
||||
calculate = function(_, context)
|
||||
if context.setting_blind then
|
||||
G.GAME.modifiers.Roland_Eternally_Verdant = true
|
||||
|
|
@ -257,27 +214,44 @@ SMODS.Challenge {
|
|||
end)
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
},
|
||||
SMODS.Challenge {
|
||||
key = "Eternally_Violet",
|
||||
rules = {custom = {{id = "Roland_Eternally_Violet"}, {id = "Roland_Showdown_Violet"}}},
|
||||
jokers = {{id = "j_joker"}, {id = "j_Roland_violet"}},
|
||||
restrictions = violet,
|
||||
pronouns = "she_they",
|
||||
calculate = function(_, context)
|
||||
if not context.setting_blind then
|
||||
return
|
||||
end
|
||||
|
||||
local mult = G.GAME.blind.mult < 6 and G.GAME.blind.mult or 1
|
||||
G.GAME.blind.chips = G.GAME.blind.chips * 6 / mult
|
||||
if context.setting_blind then
|
||||
G.GAME.blind.chips = G.GAME.blind.chips * (6 / G.GAME.blind.mult)
|
||||
G.GAME.blind.chip_text = number_format(G.GAME.blind.chips)
|
||||
end
|
||||
end,
|
||||
},
|
||||
}
|
||||
|
||||
SMODS.Challenge {
|
||||
key = "Showdown",
|
||||
rules = {custom = {
|
||||
{id = "Roland_Eternally_Amber"},
|
||||
{id = "Roland_Eternally_Cerulean"},
|
||||
{id = "Roland_Eternally_Crimson"},
|
||||
{id = "Roland_Eternally_Verdant"},
|
||||
{id = "Roland_Eternally_Violet"},
|
||||
{id = "Roland_Showdown"},
|
||||
}},
|
||||
restrictions = final,
|
||||
calculate = function(_, context)
|
||||
f(finalizers):each(function(v)
|
||||
v:calculate(context)
|
||||
end)
|
||||
end,
|
||||
}
|
||||
|
||||
q(function()
|
||||
f {
|
||||
{G.P_CENTERS, is_joker, jokerful.banned_cards},
|
||||
{G.P_TAGS, is_vanilla, vanillas.banned_tags},
|
||||
{G.P_BLINDS, is_vanilla, vanillas.banned_other},
|
||||
{G.P_CENTERS, is_vanilla, vanillas.banned_cards},
|
||||
{G.P_TAGS, is_banned_from_pastry, pastries.banned_tags},
|
||||
{G.P_BLINDS, is_banned_from_pastry, pastries.banned_other},
|
||||
{G.P_CENTERS, is_center_banned_from_pastry, pastries.banned_cards},
|
||||
|
|
@ -286,17 +260,8 @@ q(function()
|
|||
{G.P_BLINDS, is_showdown_except "bl_final_heart", crimson.banned_other},
|
||||
{G.P_BLINDS, is_showdown_except "bl_final_leaf", verdant.banned_other},
|
||||
{G.P_BLINDS, is_showdown_except "bl_final_vessel", violet.banned_other},
|
||||
{G.P_BLINDS, is_showdown_except "bl_Roland_venerable_visage", final.banned_other},
|
||||
}:each(function(v)
|
||||
f(v[1]):where(v[2]):each(adder(v[3]))
|
||||
end)
|
||||
end)
|
||||
|
||||
q(function()
|
||||
if not G.P_CENTERS.j_Bakery_Spinner then
|
||||
return true
|
||||
end
|
||||
|
||||
f(spin_to_win.jokers):each(function(v)
|
||||
v.id = "j_Bakery_Spinner"
|
||||
end)
|
||||
end)
|
||||
|
|
|
|||
303
src/charm.lua
|
|
@ -1,32 +1,19 @@
|
|||
local f, q = (... or require "lib.shared")[1], (... or require "lib.shared")[2]
|
||||
local f, q = unpack(... or require "lib.shared")
|
||||
local mod = SMODS.current_mod
|
||||
local cool_phones = SMODS.Mods.Roland.config.cool_phones
|
||||
|
||||
SMODS.Atlas {
|
||||
key = "charm",
|
||||
path = cool_phones and "phorm.png" or "charm.png",
|
||||
path = "charm.png",
|
||||
px = 68,
|
||||
py = 68,
|
||||
}
|
||||
|
||||
local _ = cool_phones and SMODS.Sound {
|
||||
key = "phone",
|
||||
path = "phone.ogg",
|
||||
}
|
||||
|
||||
local charm = (function()
|
||||
local x = 0
|
||||
|
||||
---@param tbl SMODS.Joker|{alerted?: boolean, artist?: string, equip?: fun(self: self, card: Card)}
|
||||
---@param tbl SMODS.Joker|{alerted?: boolean}
|
||||
return function(tbl)
|
||||
q {
|
||||
blocking = false,
|
||||
no_delete = true,
|
||||
func = function()
|
||||
if not Bakery_API or not Bakery_API.Charm then
|
||||
return false
|
||||
end
|
||||
|
||||
q(function()
|
||||
local current_mod = SMODS.current_mod
|
||||
SMODS.current_mod = mod
|
||||
|
||||
|
|
@ -35,155 +22,122 @@ local charm = (function()
|
|||
tbl.unlocked = true
|
||||
tbl.discovered = true
|
||||
tbl.pos = {x = x, y = 0}
|
||||
tbl.atlas = "charm"
|
||||
tbl.artist = not cool_phones and "Roland_bakersdozenbagels" or nil
|
||||
x = x + 1
|
||||
tbl.atlas = "charm"
|
||||
|
||||
local orig_equip = tbl.equip
|
||||
|
||||
function tbl.equip(...)
|
||||
local _ = cool_phones and play_sound("Roland_phone", 1, 0.5)
|
||||
|
||||
if orig_equip then
|
||||
return orig_equip(...)
|
||||
end
|
||||
end
|
||||
|
||||
local charm = Bakery_API.credit(Bakery_API.Charm(tbl))
|
||||
local charm = Bakery_API.Charm(tbl)
|
||||
charm:inject()
|
||||
charm:process_loc_text()
|
||||
SMODS.current_mod = current_mod
|
||||
end,
|
||||
}
|
||||
end, true)
|
||||
end
|
||||
end)()
|
||||
|
||||
local function can_discard_zero()
|
||||
return G.GAME.current_round.discards_left > 0 and
|
||||
not next(G.hand.highlighted) and
|
||||
G.hand.config.card_limit > 0 and
|
||||
G.GAME.Bakery_charm == "BakeryCharm_Roland_cocacola"
|
||||
local function add_to_consumable_ability_by(n)
|
||||
local function new(v)
|
||||
return type(v) == "number" and v + n or type(v) == "table" and f(v):map(new):table() or v
|
||||
end
|
||||
|
||||
charm {
|
||||
key = "hand",
|
||||
pronouns = "he_him",
|
||||
config = {extra = {hands = -2, hand_size = 5}},
|
||||
attributes = {"hands", "hand_size", "passive"},
|
||||
loc_vars = function(_, _, card)
|
||||
local extra = card.ability.extra
|
||||
return {vars = {extra.hand_size, extra.hands}}
|
||||
end,
|
||||
equip = function(_, card)
|
||||
local extra = card.ability.extra
|
||||
local round = G.GAME.round_resets
|
||||
ease_hands_played(extra.hands)
|
||||
G.hand:change_size(extra.hand_size)
|
||||
round.hands = round.hands + extra.hands
|
||||
end,
|
||||
unequip = function(_, card)
|
||||
local extra = card.ability.extra
|
||||
local round = G.GAME.round_resets
|
||||
ease_hands_played(-extra.hands)
|
||||
G.hand:change_size(-extra.hand_size)
|
||||
round.hands = round.hands - extra.hands
|
||||
end,
|
||||
}
|
||||
---@param card Card
|
||||
return function(card)
|
||||
local ability = card.ability or {}
|
||||
|
||||
charm {
|
||||
key = "cocacola",
|
||||
pronouns = "he_they",
|
||||
attributes = {"passive", "tarot", "spectral"},
|
||||
config = {extra = {discard = 2, hand_size = 1, refund = 0}},
|
||||
loc_vars = function(_, _, card)
|
||||
local extra = card.ability.extra
|
||||
return {vars = {extra.discard, extra.hand_size}}
|
||||
end,
|
||||
calculate = function(_, card, context)
|
||||
if not context.end_of_round then
|
||||
local function go(key)
|
||||
---@type { [string]: number }|number
|
||||
local value = ability[key]
|
||||
--print(key)
|
||||
if not value then
|
||||
return
|
||||
end
|
||||
|
||||
local extra = card.ability.extra
|
||||
G.hand:change_size(extra.refund)
|
||||
extra.refund = 0
|
||||
end,
|
||||
}
|
||||
|
||||
local orig_can_discard = G.FUNCS.can_discard
|
||||
|
||||
function G.FUNCS.can_discard(e, ...)
|
||||
if can_discard_zero() then
|
||||
e.config.button, e.config.colour = "Roland_cocacola", G.C.RED
|
||||
else
|
||||
return orig_can_discard(e, ...)
|
||||
end
|
||||
if type(value) == "number" then
|
||||
ability[key] = value + n
|
||||
return
|
||||
end
|
||||
|
||||
G.FUNCS.Roland_cocacola = function()
|
||||
stop_use()
|
||||
G.CONTROLLER.interrupt.focus = true
|
||||
G.CONTROLLER:save_cardarea_focus "hand"
|
||||
if type(value) ~= "table" then
|
||||
return
|
||||
end
|
||||
|
||||
f(G.playing_cards):map "ability":each(function(v)
|
||||
v.forced_selection = nil
|
||||
local new_value = f(value):map(new):table()
|
||||
|
||||
f(new_value):each(function(v, k)
|
||||
ability[k] = v
|
||||
end)
|
||||
|
||||
G.card_area_focus_reset = (G.CONTROLLER.focused.target or {}).area == G.hand and
|
||||
{area = G.hand, rank = G.CONTROLLER.focused.target.rank} or G.card_area_focus_reset
|
||||
|
||||
SMODS.calculate_context {pre_discard = true, full_hand = G.hand.highlighted}
|
||||
G.GAME.current_round.discards_used = G.GAME.current_round.discards_used + 1
|
||||
|
||||
local c = G.Bakery_charm_area.cards[1]
|
||||
local extra = c.ability.extra or {}
|
||||
juice_card(c)
|
||||
ease_discard(extra.discard - 1)
|
||||
G.hand:change_size(-extra.hand_size)
|
||||
extra.refund = extra.refund + extra.hand_size
|
||||
|
||||
local _ = G.GAME.modifiers.discard_cost and ease_dollars(-G.GAME.modifiers.discard_cost)
|
||||
G.STATE = G.STATES.DRAW_TO_HAND
|
||||
|
||||
q {
|
||||
trigger = "immediate",
|
||||
func = function()
|
||||
if G.SCORING_COROUTINE then
|
||||
return false
|
||||
ability[key] = new_value
|
||||
end
|
||||
|
||||
local center_key = (card.config or {}).center_key
|
||||
|
||||
if center_key and center_key:sub(1, 2) == "c_" then
|
||||
f {"extra", "consumeable"}:each(go)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
charm {
|
||||
key = "wii",
|
||||
pronouns = "they_them",
|
||||
calculate = function(_, card, context)
|
||||
if not context.skip_blind then
|
||||
return
|
||||
end
|
||||
|
||||
local message = localize {type = "variable", key = "b_Roland_entering_shop"}
|
||||
SMODS.calculate_effect({card = card, message = message, sound = "whoosh1"}, card)
|
||||
|
||||
q(function()
|
||||
G.blind_prompt_box = G.blind_prompt_box and G.blind_prompt_box:remove()
|
||||
G.blind_select = G.blind_select and G.blind_select:remove()
|
||||
G.round_eval = G.round_eval and G.round_eval:remove()
|
||||
G.GAME.current_round.jokers_purchased = 0
|
||||
G.STATE = G.STATES.SHOP
|
||||
G.GAME.shop_free = nil
|
||||
G.GAME.shop_d6ed = nil
|
||||
G.STATE_COMPLETE = false
|
||||
return true
|
||||
play_sound("whoosh1", 1.33333, 0.8)
|
||||
play_sound("whoosh1", 0.66666, 0.8)
|
||||
end)
|
||||
end,
|
||||
}
|
||||
|
||||
charm {
|
||||
key = "flexible",
|
||||
pronouns = "any_all",
|
||||
}
|
||||
|
||||
local orig_showman = SMODS.showman
|
||||
|
||||
---@diagnostic disable-next-line: duplicate-set-field
|
||||
function SMODS.showman(...)
|
||||
return G.GAME.Bakery_charm == "BakeryCharm_Roland_flexible" or orig_showman(...)
|
||||
end
|
||||
|
||||
charm {
|
||||
key = "fat",
|
||||
pronouns = "he_they",
|
||||
attributes = {"passive"},
|
||||
config = {extra = {mod = 2}},
|
||||
loc_vars = function(_, _, card)
|
||||
return {vars = {card.ability.extra.mod}}
|
||||
end,
|
||||
equip = function(_, card)
|
||||
SMODS.change_booster_limit(card.ability.extra.mod)
|
||||
end,
|
||||
unequip = function(_, card)
|
||||
SMODS.change_booster_limit(-card.ability.extra.mod)
|
||||
end,
|
||||
-- config = {extra = {mod = 1}},
|
||||
-- loc_vars = function(_, _, card)
|
||||
-- return {vars = {card.ability.extra.mod}}
|
||||
-- end,
|
||||
-- equip = function(_, card)
|
||||
-- SMODS.change_booster_limit(card.ability.extra.mod)
|
||||
-- end,
|
||||
-- unequip = function(card)
|
||||
-- SMODS.change_booster_limit(-card.ability.extra.mod)
|
||||
-- end,
|
||||
}
|
||||
|
||||
local orig_init = Card.init
|
||||
|
||||
---@diagnostic disable-next-line: duplicate-set-field
|
||||
function Card:init(X, Y, W, H, card, center, params, ...)
|
||||
if G.GAME.Bakery_charm ~= "BakeryCharm_Roland_fat" or center.set ~= "Booster" then
|
||||
return orig_init(self, X, Y, W, H, card, center, params, ...)
|
||||
end
|
||||
|
||||
local key = f {"mini", "jumbo", "normal"}:fold(center.key, function(a, v)
|
||||
return a:gsub(v, "mega")
|
||||
end)
|
||||
local key = center.key:gsub("normal", "mega"):gsub("jumbo", "mega"):gsub("mini", "mega")
|
||||
|
||||
if G.P_CENTERS[key] then
|
||||
return orig_init(self, X, Y, W, H, card, G.P_CENTERS[key], params, ...)
|
||||
|
|
@ -206,64 +160,49 @@ function Card:init(X, Y, W, H, card, center, params, ...)
|
|||
end
|
||||
|
||||
charm {
|
||||
key = "flexible",
|
||||
pronouns = "any_all",
|
||||
}
|
||||
|
||||
local orig_showman = SMODS.showman
|
||||
|
||||
function SMODS.showman(...)
|
||||
return G.GAME.Bakery_charm == "BakeryCharm_Roland_flexible" or orig_showman(...)
|
||||
end
|
||||
|
||||
charm {
|
||||
key = "wii",
|
||||
pronouns = "they_them",
|
||||
attributes = {"skip"},
|
||||
config = {extra = {active = true}},
|
||||
calculate = function(_, card, context)
|
||||
if context.prevent_tag_trigger and card.ability.extra.active then
|
||||
return {prevent_trigger = true}
|
||||
end
|
||||
|
||||
if not context.skip_blind then
|
||||
return
|
||||
end
|
||||
|
||||
card.ability.extra.active = true
|
||||
local message = localize {type = "variable", key = "b_Roland_entering_shop"}
|
||||
SMODS.calculate_effect({card = card, message = message, sound = "whoosh1"}, card)
|
||||
|
||||
q(function()
|
||||
G.blind_prompt_box = G.blind_prompt_box and G.blind_prompt_box:remove()
|
||||
G.blind_select = G.blind_select and G.blind_select:remove()
|
||||
G.round_eval = G.round_eval and G.round_eval:remove()
|
||||
G.GAME.current_round.jokers_purchased = 0
|
||||
G.GAME.shop_free = nil
|
||||
G.GAME.shop_d6ed = nil
|
||||
play_sound("whoosh1", 1.33333, 0.8)
|
||||
play_sound("whoosh1", 0.66666, 0.8)
|
||||
|
||||
q(function()
|
||||
G.STATE = G.STATES.SHOP
|
||||
G.STATE_COMPLETE = false
|
||||
delay(1)
|
||||
|
||||
q(function()
|
||||
card.ability.extra.active = false
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
key = "cocacola",
|
||||
pronouns = "he_they",
|
||||
equip = function()
|
||||
f(G.consumeables.cards):each(add_to_consumable_ability_by(1))
|
||||
end,
|
||||
unequip = function()
|
||||
f(G.consumeables.cards):each(add_to_consumable_ability_by(-1))
|
||||
end,
|
||||
}
|
||||
|
||||
local orig_apply_to_run = Tag.apply_to_run
|
||||
local orig_set_ability = Card.set_ability
|
||||
|
||||
function Tag:apply_to_run(...)
|
||||
if G.GAME.Bakery_charm == "BakeryCharm_Roland_wii" and
|
||||
G.Bakery_charm_area.cards[1].ability.extra.active then
|
||||
return
|
||||
---@diagnostic disable-next-line: duplicate-set-field
|
||||
function Card:set_ability(center, initial, delay_sprites, ...)
|
||||
local ret = orig_set_ability(self, center, initial, delay_sprites, ...)
|
||||
|
||||
if G.GAME.Bakery_charm == "BakeryCharm_Roland_cocacola" then
|
||||
add_to_consumable_ability_by(1)(self)
|
||||
end
|
||||
|
||||
return orig_apply_to_run(self, ...)
|
||||
return ret
|
||||
end
|
||||
|
||||
charm {
|
||||
key = "hand",
|
||||
pronouns = "he_him",
|
||||
config = {extra = {hands = -2, hand_size = 5}},
|
||||
loc_vars = function(_, _, card)
|
||||
local extra = card.ability.extra
|
||||
return {vars = {extra.hand_size, extra.hands}}
|
||||
end,
|
||||
equip = function(_, card)
|
||||
local extra = card.ability.extra
|
||||
local round = G.GAME.round_resets
|
||||
ease_hands_played(extra.hands)
|
||||
G.hand:change_size(extra.hand_size)
|
||||
round.hands = round.hands + extra.hands
|
||||
end,
|
||||
unequip = function(_, card)
|
||||
local extra = card.ability.extra
|
||||
local round = G.GAME.round_resets
|
||||
ease_hands_played(-extra.hands)
|
||||
G.hand:change_size(-extra.hand_size)
|
||||
round.hands = round.hands - extra.hands
|
||||
end,
|
||||
}
|
||||
|
|
|
|||
327
src/edition.lua
|
|
@ -1,327 +0,0 @@
|
|||
local f, q = (... or require "lib.shared")[1], (... or require "lib.shared")[2]
|
||||
|
||||
SMODS.Shader {
|
||||
key = "frozen",
|
||||
path = "frozen.fs",
|
||||
}
|
||||
|
||||
---@param suffix string
|
||||
local function frozen_sound(suffix)
|
||||
local key = "frozen" .. suffix
|
||||
return SMODS.Sound {key = key, path = key .. ".ogg"}
|
||||
end
|
||||
|
||||
frozen_sound "_click"
|
||||
local frozen_blocklist = {CardSleeve = true}
|
||||
local frozen_sounds = f(4):map(frozen_sound):map "key":table()
|
||||
|
||||
local needs_chip_mult_override = {
|
||||
Bull = true,
|
||||
Erosion = true,
|
||||
Misprint = true,
|
||||
TierList = true,
|
||||
["Blue Joker"] = true,
|
||||
["Abstract Joker"] = true,
|
||||
["Fortune Teller"] = true,
|
||||
}
|
||||
|
||||
local current_round_overrides = {
|
||||
Castle = "castle_card",
|
||||
Farmer = "farmer_card",
|
||||
Tuxedo = "tuxedo_card",
|
||||
["Go Fish"] = "fish_rank",
|
||||
["The Idol"] = "idol_card",
|
||||
["Mail-In Rebate"] = "mail_card",
|
||||
Obelisk = "most_played_poker_hand",
|
||||
["Ancient Joker"] = "ancient_card",
|
||||
Wherewolf = "Bakery_Wherewolf_card",
|
||||
j_Roland_suitable = "Roland_suitable",
|
||||
}
|
||||
|
||||
SMODS.current_mod.frozen_chip_mult = needs_chip_mult_override
|
||||
SMODS.current_mod.frozen_current_round = current_round_overrides
|
||||
|
||||
local function freeze(card)
|
||||
---@generic T
|
||||
---@param x T
|
||||
---@return T
|
||||
local function copy(x)
|
||||
return type(x) == "table" and f(x):map(copy):table() or x
|
||||
end
|
||||
|
||||
if frozen_blocklist[(card.ability or {}).name] then
|
||||
return card.ability
|
||||
end
|
||||
|
||||
(card.ability or {}).Roland_crimson = not not (card.ability or {}).Roland_crimson
|
||||
card.Roland_frozen_ability = card.Roland_frozen_ability or copy(card.ability)
|
||||
card.ability = card.Roland_frozen_ability and copy(card.Roland_frozen_ability) or card.ability
|
||||
card.Roland_frozen = card.Roland_frozen or {probability = SMODS.get_probability_vars(card, 1, 1)}
|
||||
local ability, ret = card.ability, card.Roland_frozen_ability
|
||||
ability.extra = ability.extra == nil and {} or ability.extra
|
||||
|
||||
if type(ability) ~= "table" then
|
||||
return ret
|
||||
end
|
||||
|
||||
ability.seal = ability.seal or {}
|
||||
|
||||
if not ability.name or not G.GAME.current_round then
|
||||
return ret
|
||||
end
|
||||
|
||||
local key = current_round_overrides[ability.name]
|
||||
|
||||
if not key then
|
||||
return ret
|
||||
end
|
||||
|
||||
card.Roland_frozen_current_round = card.Roland_frozen_current_round or copy(G.GAME.current_round[key])
|
||||
G.GAME.current_round[key] = copy(card.Roland_frozen_current_round)
|
||||
return ret
|
||||
end
|
||||
|
||||
local function hook_estate()
|
||||
---@param card Card|{ Roland_frozen: {estate: integer} }
|
||||
local function estate_pos(card)
|
||||
if card.area ~= G.jokers and card.area.config.type ~= "title" then
|
||||
return 1
|
||||
end
|
||||
|
||||
card.Roland_frozen.estate = card.Roland_frozen.estate or card.rank or 1
|
||||
return card.Roland_frozen.estate
|
||||
end
|
||||
|
||||
local estate = G.P_CENTERS.j_Bakery_Estate
|
||||
local orig_calculate = estate.calculate
|
||||
|
||||
function estate:calculate(card, context, ...)
|
||||
if not (card or {}).Roland_frozen or not (card.edition or {}).Roland_frozen then
|
||||
return orig_calculate(self, card, context, ...)
|
||||
end
|
||||
|
||||
if not context.joker_main then
|
||||
return
|
||||
end
|
||||
|
||||
local joker_count = estate_pos(card)
|
||||
local extra = card.ability.extra
|
||||
return {chips = extra.chips * joker_count, mult = extra.mult * joker_count}
|
||||
end
|
||||
|
||||
local orig_loc_vars = estate.loc_vars
|
||||
|
||||
function estate:loc_vars(info_queue, card, ...)
|
||||
if not (card or {}).Roland_frozen or not (card.edition or {}).Roland_frozen then
|
||||
return orig_loc_vars(self, info_queue, card, ...)
|
||||
end
|
||||
|
||||
local joker_count = estate_pos(card)
|
||||
local extra = card.ability.extra or {}
|
||||
return {vars = {extra.chips * joker_count, extra.mult * joker_count}}
|
||||
end
|
||||
end
|
||||
|
||||
local function hook_proxy()
|
||||
---@param card Card|{ Roland_frozen: {proxy: string} }
|
||||
local function get_proxied_joker(card)
|
||||
if not G.jokers or not G.jokers.cards then
|
||||
return
|
||||
end
|
||||
|
||||
card.Roland_frozen.proxy = card.Roland_frozen.proxy or
|
||||
(Bakery_API.get_proxied_joker() or card).config.center.key
|
||||
|
||||
---@param v Card
|
||||
local function eq(v)
|
||||
return v.config.center.key == card.Roland_frozen.proxy
|
||||
end
|
||||
|
||||
return f(G.jokers.cards):any(eq)
|
||||
end
|
||||
|
||||
local proxy = G.P_CENTERS.j_Bakery_Proxy
|
||||
local orig_calculate = proxy.calculate
|
||||
|
||||
function proxy:calculate(card, context, ...)
|
||||
if not (card or {}).Roland_frozen or not (card.edition or {}).Roland_frozen then
|
||||
return orig_calculate(self, card, context, ...)
|
||||
else
|
||||
return SMODS.blueprint_effect(card, get_proxied_joker(card), context)
|
||||
end
|
||||
end
|
||||
|
||||
local orig_loc_vars = proxy.loc_vars
|
||||
|
||||
function proxy:loc_vars(info_queue, card, ...)
|
||||
if not (card or {}).Roland_frozen or not (card.edition or {}).Roland_frozen then
|
||||
return orig_loc_vars(self, info_queue, card, ...)
|
||||
end
|
||||
|
||||
local other = get_proxied_joker(card)
|
||||
|
||||
local var = (other and other ~= card) and localize {
|
||||
type = "name_text",
|
||||
set = other.config.center.set,
|
||||
key = other.config.center.key,
|
||||
} or localize "k_none"
|
||||
|
||||
return {vars = {var}}
|
||||
end
|
||||
end
|
||||
|
||||
local function hook_scribe()
|
||||
local scribe = G.P_CENTERS.c_Bakery_Scribe
|
||||
local orig_can_use = scribe.can_use
|
||||
|
||||
function scribe.can_use(...)
|
||||
return orig_can_use(...) and
|
||||
(SMODS.Mods.Roland.config.scribable_basket or f(G.jokers.highlighted):all(function(v)
|
||||
return v.config.center.key ~= "j_Roland_basket"
|
||||
end))
|
||||
end
|
||||
end
|
||||
|
||||
SMODS.Edition {
|
||||
key = "frozen",
|
||||
shader = "frozen",
|
||||
sound = {sound = "Roland_frozen", per = 1, vol = 0.8},
|
||||
attributes = {"passive", "scaling", "mod_chance"},
|
||||
pronouns = "any_all",
|
||||
weight = 8,
|
||||
extra_cost = 4,
|
||||
in_shop = true,
|
||||
apply_to_float = false,
|
||||
calculate = function(_, card, context)
|
||||
local _ = not context.fix_probability and not context.mod_probability and freeze(card)
|
||||
end,
|
||||
on_remove = function(card)
|
||||
card.Roland_frozen, card.Roland_frozen_ability, card.Roland_frozen_current_round = nil, nil, nil
|
||||
end,
|
||||
get_weight = function(self)
|
||||
return G.GAME.edition_rate * self.weight
|
||||
end,
|
||||
}
|
||||
|
||||
local orig_play_sound = play_sound
|
||||
|
||||
function play_sound(sound, pitch, ...)
|
||||
if sound ~= "Roland_frozen" and sound ~= "Roland_frozen_click" then
|
||||
return orig_play_sound(sound, pitch, ...)
|
||||
end
|
||||
|
||||
local overriden_sound = sound == "Roland_frozen" and
|
||||
pseudorandom_element(frozen_sounds, pseudoseed "Roland_frozen") or
|
||||
sound
|
||||
|
||||
local added_pitch = pseudorandom(pseudoseed "Roland_frozen_pitch") / 4 + 0.8
|
||||
return orig_play_sound(overriden_sound, pitch + added_pitch, ...)
|
||||
end
|
||||
|
||||
local orig_click = Card.click
|
||||
|
||||
function Card:click(...)
|
||||
local highlight = self.highlighted
|
||||
local ret = orig_click(self, ...)
|
||||
|
||||
if self.edition and self.edition.Roland_frozen and highlight ~= self.highlighted then
|
||||
play_sound("Roland_frozen_click", highlight and 0 or 0.5, 0.6)
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
local orig_calculate_joker = Card.calculate_joker
|
||||
|
||||
---@param self Card|{Roland_frozen_ability?: table}
|
||||
function Card:calculate_joker(context, ...)
|
||||
local is_frozen = self.edition and self.edition.Roland_frozen
|
||||
|
||||
if is_frozen and self.ability.name == "Loyalty Card" then
|
||||
return (context.joker_main and self.ability.loyalty_remaining == 0) and
|
||||
{xmult = self.ability.extra.Xmult} or nil
|
||||
end
|
||||
|
||||
if is_frozen and self.ability.name == "Turtle Bean" then
|
||||
return
|
||||
end
|
||||
|
||||
local ret = {orig_calculate_joker(self, context, ...)}
|
||||
|
||||
if not is_frozen or type(ret[1]) ~= "table" then
|
||||
return unpack(ret)
|
||||
end
|
||||
|
||||
local ability = freeze(self)
|
||||
|
||||
if not needs_chip_mult_override[ability.name] then
|
||||
return unpack(ret)
|
||||
end
|
||||
|
||||
return f {mult = "mult_mod", chips = "chip_mod", xmult = "xmult", x_mult = "x_mult"}:map(function(v)
|
||||
local key = "Roland_frozen_" .. v
|
||||
ability[key] = ability[key] or ret[1][v]
|
||||
return ability[key]
|
||||
end):where(f.id):table()
|
||||
end
|
||||
|
||||
local orig_calculate_dollar_bonus = Card.calculate_dollar_bonus
|
||||
|
||||
---@param self Card|{Roland_frozen_ability?: table}
|
||||
function Card:calculate_dollar_bonus(...)
|
||||
if not self.edition or not self.edition.Roland_frozen then
|
||||
return orig_calculate_dollar_bonus(self, ...)
|
||||
end
|
||||
|
||||
local ability = freeze(self)
|
||||
|
||||
if ability.name == "Satellite" then
|
||||
ability.Roland_frozen_planets_used = ability.Roland_frozen_planets_used or
|
||||
orig_calculate_dollar_bonus(self, ...)
|
||||
|
||||
return self.ability.extra * ability.Roland_frozen_planets_used
|
||||
end
|
||||
|
||||
return orig_calculate_dollar_bonus(self, ...)
|
||||
end
|
||||
|
||||
local orig_get_probability_vars = SMODS.get_probability_vars
|
||||
|
||||
function G.P_CENTERS.j_bootstraps:mult(card)
|
||||
local ability = card.Roland_frozen_ability
|
||||
local ret = math.floor((G.GAME.dollars + (G.GAME.dollar_buffer or 0)) / card.ability.extra.dollars)
|
||||
|
||||
if not ability then
|
||||
return ret
|
||||
end
|
||||
|
||||
ability.Roland_bootstraps_mult = ability.Roland_bootstraps_mult or ret
|
||||
return ability.Roland_bootstraps_mult
|
||||
end
|
||||
|
||||
function SMODS.get_probability_vars(trigger_obj, ...)
|
||||
local numerator, denominator = orig_get_probability_vars(trigger_obj, ...)
|
||||
return trigger_obj and (trigger_obj.Roland_frozen or {}).probability or numerator, denominator
|
||||
end
|
||||
|
||||
q {
|
||||
blocking = false,
|
||||
no_delete = true,
|
||||
func = function()
|
||||
local orig_flip_double_sided = (Bakery_API or {}).flip_double_sided
|
||||
|
||||
if not orig_flip_double_sided then
|
||||
return false
|
||||
end
|
||||
|
||||
function Bakery_API.flip_double_sided(card, ...)
|
||||
if not card.edition or not card.edition.Roland_frozen then
|
||||
return orig_flip_double_sided(card, ...)
|
||||
end
|
||||
end
|
||||
|
||||
local _ = G.P_CENTERS.j_Bakery_Estate and hook_estate()
|
||||
local _ = G.P_CENTERS.c_Bakery_Scribe and hook_scribe()
|
||||
local _ = G.P_CENTERS.j_Bakery_Proxy and hook_proxy()
|
||||
end,
|
||||
}
|
||||
1245
src/joker.lua
|
|
@ -3,101 +3,10 @@
|
|||
---@license MPL-2.0
|
||||
---@version 1.0.0
|
||||
---
|
||||
---@alias FFrom (fun<K, V>(iter: table<K, V>, fpairs?: fun(t: table<K, V>): (fun(table: table<K, V>, index?: K): K?, V?)): F | { [K]: V })|(fun(iter: number, fpairs?: number, step?: number): F | { [number]: number })|(fun<V>(iter: string): (fun(table: { [string]: V }): V))|(fun<V>(iter: string): (fun(table: { [string]: V }): V))|(fun<K, V>(iter: fun(): K, V): F | { [K]: V })|(fun(iter: false): fun(): false)|(fun(iter: true): fun(): true)|(fun(iter: nil): F)
|
||||
---@class F
|
||||
local f = {}
|
||||
|
||||
if not f then
|
||||
---@generic I, O
|
||||
---@param first string|fun(v: I): O
|
||||
---@return fun(v: I): O
|
||||
---@nodiscard
|
||||
function f.chain(first)
|
||||
error {first}
|
||||
end
|
||||
|
||||
---@generic I, T, O
|
||||
---@param first string|fun(v: I): T
|
||||
---@param second string|fun(v: T): O
|
||||
---@return fun(v: I): O
|
||||
---@nodiscard
|
||||
function f.chain(first, second)
|
||||
error {first, second}
|
||||
end
|
||||
|
||||
---@generic I, T1, T2, O
|
||||
---@param first string|fun(v: I): T1
|
||||
---@param second string|fun(v: T1): T2
|
||||
---@param third string|fun(v: T2): O
|
||||
---@return fun(v: I): O
|
||||
---@nodiscard
|
||||
function f.chain(first, second, third)
|
||||
error {first, second, third}
|
||||
end
|
||||
|
||||
---@generic I, T1, T2, T3, O
|
||||
---@param first string|fun(v: I): T1
|
||||
---@param second string|fun(v: T1): T2
|
||||
---@param third string|fun(v: T2): T3
|
||||
---@param fourth string|fun(v: T3): O
|
||||
---@return fun(v: I): O
|
||||
---@nodiscard
|
||||
function f.chain(first, second, third, fourth)
|
||||
error {first, second, third, fourth}
|
||||
end
|
||||
|
||||
---@generic I, T1, T2, T3, T4, O
|
||||
---@param first string|fun(v: I): T1
|
||||
---@param second string|fun(v: T1): T2
|
||||
---@param third string|fun(v: T2): T3
|
||||
---@param fourth string|fun(v: T3): T4
|
||||
---@param fifth string|fun(v: T4): O
|
||||
---@return fun(v: I): O
|
||||
---@nodiscard
|
||||
function f.chain(first, second, third, fourth, fifth)
|
||||
error {first, second, third, fourth, fifth}
|
||||
end
|
||||
|
||||
---@generic I, O
|
||||
---@param all { [1]: (string|fun(v: I): O) }
|
||||
---@return fun(v: I): O
|
||||
---@nodiscard
|
||||
function f.chain(all)
|
||||
error(all)
|
||||
end
|
||||
|
||||
---@generic I, T, O
|
||||
---@param all { [1]: (string|fun(v: I): T), [2]: (string|fun(v: T): O) }
|
||||
---@return fun(v: I): O
|
||||
---@nodiscard
|
||||
function f.chain(all)
|
||||
error(all)
|
||||
end
|
||||
|
||||
---@generic I, T1, T2, O
|
||||
---@param all { [1]: (string|fun(v: I): T1), [2]: (string|fun(v: T1): T2), [3]: (string|fun(v: T2): O) }
|
||||
---@return fun(v: I): O
|
||||
---@nodiscard
|
||||
function f.chain(all)
|
||||
error(all)
|
||||
end
|
||||
|
||||
---@generic I, T1, T2, T3, O
|
||||
---@param all { [1]: (string|fun(v: I): T1), [2]: (string|fun(v: T1): T2), [3]: (string|fun(v: T2): T3), [4]: (string|fun(v: T3): O) }
|
||||
---@return fun(v: I): O
|
||||
---@nodiscard
|
||||
function f.chain(all)
|
||||
error(all)
|
||||
end
|
||||
|
||||
---@generic I, T1, T2, T3, T4, O
|
||||
---@param all { [1]: (string|fun(v: I): T1), [2]: (string|fun(v: T1): T2), [3]: (string|fun(v: T2): T3), [4]: (string|fun(v: T3): T4), [4]: (string|fun(v: T4): O) }
|
||||
---@return fun(v: I): O
|
||||
---@nodiscard
|
||||
function f.chain(all)
|
||||
error(all)
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param self F | { [K]: V }
|
||||
---@return K?, V?
|
||||
|
|
@ -109,74 +18,39 @@ end
|
|||
---@type F
|
||||
local none
|
||||
|
||||
---@generic T: F|function|string|nil
|
||||
---@param func T
|
||||
---@return T
|
||||
---@nodiscard
|
||||
local function autofunc(func)
|
||||
return type(func) == "string" and f.indices(func) or func or f.id
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param tbl table<K, V>
|
||||
---@param fpairs? fun(t: table<K, V>): (fun(table: table<K, V>, index?: K): K, V)
|
||||
---@return fun(tbl: table<K, V>, key: K): K, V
|
||||
---@return table<K, V>
|
||||
---@return K
|
||||
---@return V
|
||||
---@nodiscard
|
||||
local function autopairs(tbl, fpairs)
|
||||
return (fpairs or (tbl[#tbl] and ipairs or pairs))(tbl)
|
||||
return (fpairs or tbl[#tbl] and ipairs or pairs)(tbl)
|
||||
end
|
||||
|
||||
---@param any any
|
||||
---@return boolean
|
||||
local function is_f(any)
|
||||
return type(any) == "table" and any.from == f.from and any.new == f.new
|
||||
end
|
||||
|
||||
--- Always returns nil.
|
||||
---@return nil
|
||||
---@nodiscard
|
||||
function f.noop()
|
||||
end
|
||||
|
||||
--- Always returns false.
|
||||
---@return false
|
||||
---@nodiscard
|
||||
function f.fals()
|
||||
return false
|
||||
end
|
||||
|
||||
--- Always returns true.
|
||||
---@return true
|
||||
---@nodiscard
|
||||
function f.tru()
|
||||
return true
|
||||
end
|
||||
|
||||
--- Returns the arguments.
|
||||
---@generic T
|
||||
---@param ... T
|
||||
---@return T
|
||||
---@nodiscard
|
||||
function f.id(...)
|
||||
return ...
|
||||
end
|
||||
|
||||
---@generic T
|
||||
---@param value T
|
||||
---@return fun(T): boolean
|
||||
---@nodiscard
|
||||
function f.eq(value)
|
||||
return function(v)
|
||||
return value == v
|
||||
end
|
||||
end
|
||||
|
||||
---@generic T
|
||||
---@param value T
|
||||
---@return fun(T): boolean
|
||||
---@nodiscard
|
||||
function f.nq(value)
|
||||
return function(v)
|
||||
return value ~= v
|
||||
end
|
||||
end
|
||||
|
||||
---@generic T
|
||||
---@param v T
|
||||
---@return fun(): T
|
||||
|
|
@ -195,158 +69,67 @@ function f.const(v)
|
|||
end
|
||||
end
|
||||
|
||||
---@param i integer
|
||||
---@return fun(...: any): any
|
||||
---@nodiscard
|
||||
function f.arg(i)
|
||||
return function(...)
|
||||
return ({...})[i]
|
||||
end
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param v K
|
||||
---@return fun(x: { [K]: V }): V
|
||||
---@nodiscard
|
||||
function f.index(v)
|
||||
return function(x)
|
||||
return type(x) == "table" and x[v] or x
|
||||
return x[v]
|
||||
end
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param v { [K]: V }
|
||||
---@return fun(x: K): V
|
||||
---@nodiscard
|
||||
function f.index_into(v)
|
||||
return type(v) == "table" and function(x)
|
||||
return v[x]
|
||||
end or f.const(v)
|
||||
end
|
||||
|
||||
---@generic V
|
||||
---@param v string
|
||||
---@return fun(x: { [string]: V }): V
|
||||
---@nodiscard
|
||||
function f.indices(v)
|
||||
return function(x)
|
||||
if type(x) ~= "table" then
|
||||
return x
|
||||
end
|
||||
|
||||
for i in v:gmatch "[^.]+" do
|
||||
x = x[i]
|
||||
end
|
||||
|
||||
return x
|
||||
end
|
||||
end
|
||||
|
||||
---@param any any
|
||||
---@return boolean
|
||||
---@nodiscard
|
||||
function f.isf(any)
|
||||
return type(any) == "table" and any.from == f.from and any.new == f.new
|
||||
end
|
||||
|
||||
f[true and "chain"] = function(...)
|
||||
local ret
|
||||
|
||||
for _, v in ipairs {...} do
|
||||
if type(v) == "table" then
|
||||
for _, vv in ipairs(v) do
|
||||
local copy = ret
|
||||
vv = autofunc(vv)
|
||||
|
||||
ret = ret and function(...)
|
||||
return vv(copy(...))
|
||||
end or vv
|
||||
end
|
||||
else
|
||||
local copy = ret
|
||||
v = autofunc(v)
|
||||
|
||||
ret = ret and function(...)
|
||||
return v(copy(...))
|
||||
end or v
|
||||
end
|
||||
end
|
||||
|
||||
return ret or f.noop
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param fnext? fun(): K?, V?
|
||||
---@return F|{ [K]: V }
|
||||
---@nodiscard
|
||||
function f.new(fnext)
|
||||
-- Iterating over `f` is far easier, but we do this for performance sake.
|
||||
return {
|
||||
all = f.all,
|
||||
any = f.any,
|
||||
arg = f.arg,
|
||||
chain = f.chain,
|
||||
concat = f.concat,
|
||||
const = f.const,
|
||||
count = f.count,
|
||||
each = f.each,
|
||||
eq = f.eq,
|
||||
fals = f.fals,
|
||||
flatmap = f.flatmap,
|
||||
fold = f.fold,
|
||||
from = f.from,
|
||||
id = f.id,
|
||||
index = f.index,
|
||||
index_into = f.index_into,
|
||||
indices = f.indices,
|
||||
isf = f.isf,
|
||||
keys = f.keys,
|
||||
map = f.map,
|
||||
new = f.new,
|
||||
next = fnext or f.noop,
|
||||
noop = f.noop,
|
||||
nq = f.nq,
|
||||
peek = f.peek,
|
||||
pun = f.pun,
|
||||
skip = f.skip,
|
||||
slice = f.slice,
|
||||
string = f.string,
|
||||
swap = f.swap,
|
||||
table = f.table,
|
||||
take = f.take,
|
||||
tru = f.tru,
|
||||
values = f.values,
|
||||
where = f.where,
|
||||
}
|
||||
local ret = {next = fnext or f.noop}
|
||||
|
||||
for k, v in pairs(f) do
|
||||
ret[k] = v
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
--- Creates an enumeration.
|
||||
---@type FFrom
|
||||
function f.from(iter, fpairs, step)
|
||||
if iter == nil then
|
||||
return none
|
||||
elseif iter == true then
|
||||
---@generic K, V
|
||||
---@param tbl table<K, V>
|
||||
---@param fpairs? fun(t: table<K, V>): (fun(table: table<K, V>, index?: K): K?, V?)
|
||||
---@param step? nil
|
||||
---@return F | { [K]: V }
|
||||
---@overload fun(tbl: number, fpairs?: number, step?: number): F | { [number]: number }
|
||||
---@overload fun(tbl: string): (fun(table: { [string]: V }): V)
|
||||
---@overload fun(tbl: false): fun(): false
|
||||
---@overload fun(tbl: true): fun(): true
|
||||
---@overload fun(tbl: nil): F
|
||||
function f.from(tbl, fpairs, step)
|
||||
if tbl == true then
|
||||
return f.tru
|
||||
elseif iter == false then
|
||||
elseif tbl == false then
|
||||
return f.fals
|
||||
elseif tbl == nil then
|
||||
return none
|
||||
end
|
||||
|
||||
local t = type(iter)
|
||||
local tbl_type = type(tbl)
|
||||
|
||||
if t == "string" then
|
||||
return f.indices(iter)
|
||||
elseif t == "number" then
|
||||
local ik, is, start = 0, step or 1, fpairs and iter or 1
|
||||
if tbl_type == "string" then
|
||||
return f.index(tbl)
|
||||
elseif tbl_type == "number" then
|
||||
local ik = 0
|
||||
local start = fpairs and tbl or 1
|
||||
|
||||
local stop = not fpairs and iter or
|
||||
local stop = not fpairs and tbl or
|
||||
(type(fpairs) == "number") and fpairs or error("Invalid argument type for 'fpairs': " .. type(fpairs))
|
||||
|
||||
if start ~= stop and (is == 0 or ((is < 0) == (start < stop))) then
|
||||
if step and step ~= 0 and ((step < 0) == (start < stop)) then
|
||||
return none
|
||||
end
|
||||
|
||||
return f.new(function()
|
||||
local iv = start + ik * is
|
||||
local iv = tbl + ik * (step or 1)
|
||||
ik = ik + 1
|
||||
|
||||
if start > stop and iv >= stop or
|
||||
|
|
@ -355,25 +138,17 @@ function f.from(iter, fpairs, step)
|
|||
return ik, iv
|
||||
end
|
||||
end)
|
||||
elseif t == "function" then
|
||||
return f.new(iter)
|
||||
elseif t == "thread" then
|
||||
return f.new(function()
|
||||
local s, k, v = coroutine.resume(iter)
|
||||
|
||||
if s then
|
||||
return k, v
|
||||
elseif tbl_type ~= "table" then
|
||||
error("Invalid argument type for 'tbl': " .. type(tbl))
|
||||
end
|
||||
end)
|
||||
else
|
||||
local next, context, k, v = autopairs(iter, type(fpairs) == "function" and fpairs or nil)
|
||||
|
||||
local next, context, k, v = autopairs(tbl, fpairs)
|
||||
|
||||
return f.new(function()
|
||||
k, v = next(context, k)
|
||||
return k, v
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
|
|
@ -383,63 +158,44 @@ end
|
|||
function f:concat(...)
|
||||
local fsi = 0
|
||||
local fs = {...}
|
||||
local sum, last = 0, 0
|
||||
|
||||
for i = 1, #fs do
|
||||
fs[i] = f.isf(fs[i]) and fs[i] or f.from(fs[i])
|
||||
if not is_f(fs[i]) then ---@diagnostic disable-next-line: assign-type-mismatch
|
||||
fs[i] = f.from(fs[i])
|
||||
end
|
||||
end
|
||||
|
||||
return f.new(function()
|
||||
if fsi == 0 then
|
||||
local k, v = self:next()
|
||||
last = type(k) == "number" and math.max(k, last) or last
|
||||
|
||||
if k ~= nil then
|
||||
return k, v
|
||||
end
|
||||
|
||||
fsi, sum, last = 1, last, 0
|
||||
fsi = 1
|
||||
end
|
||||
|
||||
while fsi <= #fs do
|
||||
local k, v = fs[fsi]:next()
|
||||
last = type(k) == "number" and math.max(k, last) or last
|
||||
|
||||
if k ~= nil then
|
||||
return type(k) == "number" and k + sum or k, v
|
||||
end
|
||||
|
||||
fsi, sum, last = fsi + 1, sum + last, 0
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
---@param func fun(v: V, k: K): any
|
||||
---@return F|{ [K]: V }
|
||||
---@nodiscard
|
||||
function f:peek(func)
|
||||
func = autofunc(func)
|
||||
|
||||
return f.new(function()
|
||||
local k, v = self:next()
|
||||
|
||||
if k ~= nil then
|
||||
func(v, k)
|
||||
return k, v
|
||||
end
|
||||
|
||||
fsi = fsi + 1
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
---@generic K, V, U
|
||||
---@param self F|{ [K]: V }
|
||||
---@param func fun(v: V, k: K): U
|
||||
---@param func F|fun(v: V, k: K): U
|
||||
---@return F|{ [K]: U }
|
||||
---@overload fun(self: F|{ [K]: V }, func: string): F|{ [K]: U }
|
||||
---@nodiscard
|
||||
---@overload fun(self: F|{ [K]: V }, func: string): F|{ [K]: U }
|
||||
function f:map(func)
|
||||
func = autofunc(func)
|
||||
func = type(func) == "string" and f.index(func) or func
|
||||
|
||||
return f.new(function()
|
||||
local k, v = self:next()
|
||||
|
|
@ -452,15 +208,15 @@ end
|
|||
|
||||
---@generic K, V, U
|
||||
---@param self F|{ [K]: V }
|
||||
---@param func fun(v: V, k: K): { [any]: U }
|
||||
---@param func F|fun(v: V, k: K): { [any]: U }
|
||||
---@param fpairs? fun(t: table<K, V>): (fun(table: table<K, V>, index?: K): K, V)
|
||||
---@return F|{ [K]: U }
|
||||
---@overload fun(self: F|{ [K]: V }, func: string, fpairs?: fun(t: table<K, V>): (fun(table: table<K, V>, index?: K): K, V)): F|{ [K]: U }
|
||||
---@nodiscard
|
||||
---@overload fun(self: F|{ [K]: V }, func: string): F|{ [K]: U }
|
||||
function f:flatmap(func, fpairs)
|
||||
-- local i = 0
|
||||
local vt, vk, vv, vp
|
||||
func = autofunc(func)
|
||||
func = type(func) == "string" and f.index(func) or func
|
||||
|
||||
return f.new(function()
|
||||
if vk then
|
||||
|
|
@ -502,13 +258,12 @@ end
|
|||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
---@param func fun(v: V, k: K): boolean
|
||||
---@param is? any
|
||||
---@param func F|fun(v: V, k: K): boolean
|
||||
---@return F|{ [K]: V }
|
||||
---@nodiscard
|
||||
---@overload fun(self: F|{ [K]: V }, func: string, is?: any): F|{ [K]: V }
|
||||
function f:where(func, is)
|
||||
func = autofunc(func)
|
||||
---@overload fun(self: F|{ [K]: V }, func: string): F|{ [K]: V }
|
||||
function f:where(func)
|
||||
func = type(func) == "string" and f.index(func) or func
|
||||
|
||||
return f.new(function()
|
||||
local k, v
|
||||
|
|
@ -520,17 +275,9 @@ function f:where(func, is)
|
|||
return
|
||||
end
|
||||
|
||||
if is == nil then
|
||||
if func(v, k) then
|
||||
return k, v
|
||||
end
|
||||
elseif is == false then
|
||||
if not func(v, k) then
|
||||
return k, v
|
||||
end
|
||||
elseif is == func(v, k) then
|
||||
return k, v
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
|
@ -569,20 +316,6 @@ function f:values()
|
|||
end)
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
---@return F|{ [V]: K }
|
||||
---@nodiscard
|
||||
function f:swap()
|
||||
return f.new(function()
|
||||
local k, v = self:next()
|
||||
|
||||
if k ~= nil then
|
||||
return v, k
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
---@param skip? integer
|
||||
|
|
@ -665,12 +398,12 @@ end
|
|||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
---@param func fun(v: V, k: K): any
|
||||
---@param func F|fun(v: V, k: K): boolean
|
||||
---@return boolean|V
|
||||
---@overload fun(self: F|{ [K]: V }, func: string?): boolean|V
|
||||
---@nodiscard
|
||||
---@overload fun(self: F|{ [K]: V }, func: string): boolean
|
||||
function f:any(func)
|
||||
func = autofunc(func)
|
||||
func = type(func) == "string" and f.index(func) or func
|
||||
|
||||
for k, v in self.next do
|
||||
if not func or func(v, k) then
|
||||
|
|
@ -683,12 +416,12 @@ end
|
|||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
---@param func fun(v: V, k: K): any
|
||||
---@param func F|fun(v: V, k: K): boolean
|
||||
---@return boolean|V
|
||||
---@overload fun(self: F|{ [K]: V }, func: string?): boolean|V
|
||||
---@nodiscard
|
||||
---@overload fun(self: F|{ [K]: V }, func: string): boolean
|
||||
function f:all(func)
|
||||
func = autofunc(func)
|
||||
func = type(func) == "string" and f.index(func) or func
|
||||
|
||||
for k, v in self.next do
|
||||
if not func or not func(v, k) then
|
||||
|
|
@ -701,13 +434,13 @@ end
|
|||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
---@param func fun(v: V, k: K): any
|
||||
---@param func F|fun(v: V, k: K): boolean
|
||||
---@return integer
|
||||
---@overload fun(self: F|{ [K]: V }, func: string): integer
|
||||
---@nodiscard
|
||||
---@overload fun(self: F|{ [K]: V }, func: string): integer
|
||||
function f:count(func)
|
||||
local ret = 0
|
||||
func = autofunc(func)
|
||||
func = type(func) == "string" and f.index(func) or func
|
||||
|
||||
for k, v in self.next do
|
||||
if not func or func(v, k) then
|
||||
|
|
@ -718,15 +451,6 @@ function f:count(func)
|
|||
return ret
|
||||
end
|
||||
|
||||
---@generic K, V, T
|
||||
---@param self F|{ [K]: V }
|
||||
---@param _ `T`
|
||||
---@return F|{ [K]: `T` }
|
||||
---@nodiscard
|
||||
function f:pun(_)
|
||||
return self
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
---@return string
|
||||
|
|
@ -767,7 +491,7 @@ end
|
|||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
---@param func? fun(v: V, k: K): nil
|
||||
---@param func? fun(v: V, k: K)
|
||||
function f:each(func)
|
||||
for k, v in self.next do
|
||||
if func then
|
||||
|
|
@ -778,11 +502,4 @@ end
|
|||
|
||||
none = f.new()
|
||||
|
||||
---@type F|FFrom
|
||||
local ret = (setmetatable or f.const(f.from))(f, {
|
||||
__call = function(_, ...)
|
||||
return f.from(...)
|
||||
end,
|
||||
})
|
||||
|
||||
return ret
|
||||
return f.from
|
||||
|
|
|
|||
|
|
@ -1,76 +0,0 @@
|
|||
---@meta
|
||||
---@alias Attributes "mult"|"chips"|"xmult"|"xchips"|"score"|"xscore"|"blindsize"|"xblindsize"|"balance"|"swap"|"retrigger"|"scaling"|"reset"|"suit"|"diamonds"|"hearts"|"spades"|"clubs"|"hand_type"|"rank"|"ace"|"two"|"three"|"four"|"five"|"six"|"seven"|"eight"|"nine"|"ten"|"jack"|"queen"|"king"|"face"|"economy"|"generation"|"destroy_card"|"hands"|"discard"|"hand_size"|"chance"|"joker_slot"|"mod_chance"|"copying"|"full_deck"|"passive"|"joker"|"tarot"|"planet"|"spectral"|"enhancements"|"seals"|"editions"|"tag"|"skip"|"modify_card"|"perma_bonus"|"prevents_death"|"boss_blind"|"reroll"|"on_sell"|"sell_value"|"food"|"space"|"bakery_double_sided"|"bakery_usable"|"bakery_werewolf"
|
||||
---@type Card[]
|
||||
CardArea.cards = CardArea.cards
|
||||
|
||||
--- @overload fun(tbl: SMODS.Joker): SMODS.GameObject
|
||||
Bakery_API.Charm = Bakery_API.Charm
|
||||
|
||||
--- @generic T: SMODS.GameObject
|
||||
--- @param obj T
|
||||
--- @return T
|
||||
function Bakery_API.credit(obj)
|
||||
error(obj)
|
||||
end
|
||||
|
||||
---@type table
|
||||
Balatest = Balatest
|
||||
|
||||
--- @type { constants?: { TEN: table }, new: (fun(self: self, arr?: number[], sign?: number, noNormalize?: boolean): table), pow: (fun(x: number, y: number): number) }
|
||||
Big = Big
|
||||
|
||||
--- @type table?
|
||||
CardSleeves = CardSleeves
|
||||
|
||||
--- @type table|fun(obj: SMODS.Back): SMODS.Back
|
||||
CardSleeves.Sleeve = CardSleeves.Sleeve
|
||||
|
||||
--- @type {aliases: { [string]: [string] }}
|
||||
Cryptid = Cryptid
|
||||
|
||||
--- @type fun(area: CardArea, ...: ...): Card
|
||||
create_card_for_shop = create_card_for_shop
|
||||
|
||||
--- @type boolean|table
|
||||
G.Bakery_charm_area.cards[1].ability.extra = G.Bakery_charm_area.cards[1].ability.extra
|
||||
|
||||
SMODS.Mods.Roland.config = require "config"
|
||||
|
||||
---@type userdata|{getWidth: fun(self: self): number}
|
||||
SMODS.Atlas.image_data = SMODS.Atlas.image_data
|
||||
|
||||
--- @type table
|
||||
Talisman = Talisman
|
||||
|
||||
--- @type fun(obj: any): number
|
||||
to_number = to_number
|
||||
|
||||
-- This exists to remove the @deprecated warning.
|
||||
---Returns the elements from the given `list`. This function is equivalent to
|
||||
---```lua
|
||||
--- return list[i], list[i+1], ···, list[j]
|
||||
---```
|
||||
---
|
||||
---
|
||||
---[View documents](command:extension.lua.doc?["en-us/52/manual.html/pdf-unpack"])
|
||||
---
|
||||
---@generic T1, T2, T3, T4, T5, T6, T7, T8, T9, T10
|
||||
---@param list {
|
||||
--- [1]?: T1,
|
||||
--- [2]?: T2,
|
||||
--- [3]?: T3,
|
||||
--- [4]?: T4,
|
||||
--- [5]?: T5,
|
||||
--- [6]?: T6,
|
||||
--- [7]?: T7,
|
||||
--- [8]?: T8,
|
||||
--- [9]?: T9,
|
||||
--- [10]?: T10,
|
||||
---}
|
||||
---@param i? integer
|
||||
---@param j? integer
|
||||
---@return T1, T2, T3, T4, T5, T6, T7, T8, T9, T10
|
||||
---@nodiscard
|
||||
function unpack(list, i, j)
|
||||
error {list, i, j}
|
||||
end
|
||||
|
|
@ -1,59 +1,3 @@
|
|||
local f = assert(SMODS.load_file "src/lib/funky.lua")() or require "lib.funky"
|
||||
|
||||
---@param v string
|
||||
---@return Card|Tag
|
||||
local function add(v)
|
||||
if not G.P_TAGS[v] then
|
||||
return SMODS.add_card {no_edition = true, key = v}
|
||||
end
|
||||
|
||||
local tag = Tag(v)
|
||||
|
||||
if tag.name == "Orbital Tag" then
|
||||
local hands = f(G.GAME.hands):where "visible":keys():table()
|
||||
tag.ability.orbital_hand = pseudorandom_element(hands, pseudoseed "Roland_c_orbital_tag")
|
||||
end
|
||||
|
||||
add_tag(tag)
|
||||
return tag
|
||||
end
|
||||
|
||||
local function simplify(x)
|
||||
return type(x) == "string" and x:lower():gsub("%s", ""):gsub("_", ""):gsub("^the", "") or x
|
||||
end
|
||||
|
||||
local function flatten(v)
|
||||
return type(v) ~= "table" and {v} or (f.isf(v) and v:table() or v)
|
||||
end
|
||||
|
||||
---@param it string
|
||||
local function find(it)
|
||||
if (G.P_CENTERS[it] or {}).config then
|
||||
return it
|
||||
end
|
||||
|
||||
local match = simplify(it)
|
||||
local pool = f(G.P_CENTER_POOLS):any(f.chain(f.arg(2), simplify, f.eq(match)))
|
||||
|
||||
if type(pool) == "table" and next(pool) then
|
||||
return pseudorandom_element(pool, pseudoseed "Roland_c").key
|
||||
end
|
||||
|
||||
if Cryptid and Cryptid.aliases and Cryptid.aliases[it] then
|
||||
return Cryptid.aliases[it]
|
||||
end
|
||||
|
||||
return f(G.localization.descriptions)
|
||||
:flatmap(flatten)
|
||||
:where(type, "table")
|
||||
:where(f.chain(f.arg(2), f.index_into(G.P_CENTERS), "config"))
|
||||
:where(function(v, k)
|
||||
return match == simplify(k) or match == simplify(v.name)
|
||||
end)
|
||||
:keys()
|
||||
:any()
|
||||
end
|
||||
|
||||
local function protect(fun)
|
||||
return function()
|
||||
local res, ret = pcall(fun)
|
||||
|
|
@ -62,83 +6,73 @@ local function protect(fun)
|
|||
sendErrorMessage(tostring(ret), "Roland")
|
||||
end
|
||||
|
||||
return not res or ret ~= false and not (SMODS.current_mod and ret ~= true)
|
||||
return not res or ret ~= false
|
||||
end
|
||||
end
|
||||
|
||||
local function protect_ev(fun)
|
||||
if type(fun) == "function" then
|
||||
return Event {func = protect(fun)}
|
||||
elseif type(fun) ~= "table" then
|
||||
error("Expected a function or table, got a " .. type(fun), 3)
|
||||
elseif type(fun.is) == "function" and fun:is(SMODS.GameObject) then
|
||||
return Event {
|
||||
blocking = false,
|
||||
no_delete = true,
|
||||
func = protect(function()
|
||||
if not Bakery_API or not Bakery_API.credit then
|
||||
return false
|
||||
if type(fun) == "table" then
|
||||
fun.func = protect(fun.func)
|
||||
fun = getmetatable(fun) == Event and fun or Event(fun)
|
||||
elseif type(fun) == "function" then
|
||||
fun = Event {func = protect(fun)}
|
||||
else
|
||||
error("Expected a function or event, got a " .. type(fun), 3)
|
||||
end
|
||||
|
||||
Bakery_API.credit(fun)
|
||||
end),
|
||||
}
|
||||
else
|
||||
fun.func = protect(fun.func or fun[1])
|
||||
return getmetatable(fun) == Event and fun or Event(fun)
|
||||
return fun
|
||||
end
|
||||
|
||||
-- This exists to remove the @deprecated warning.
|
||||
if false then
|
||||
---Returns the elements from the given `list`. This function is equivalent to
|
||||
---```lua
|
||||
--- return list[i], list[i+1], ···, list[j]
|
||||
---```
|
||||
---
|
||||
---
|
||||
---[View documents](command:extension.lua.doc?["en-us/52/manual.html/pdf-unpack"])
|
||||
---
|
||||
---@generic T1, T2, T3, T4, T5, T6, T7, T8, T9, T10
|
||||
---@param list {
|
||||
--- [1]?: T1,
|
||||
--- [2]?: T2,
|
||||
--- [3]?: T3,
|
||||
--- [4]?: T4,
|
||||
--- [5]?: T5,
|
||||
--- [6]?: T6,
|
||||
--- [7]?: T7,
|
||||
--- [8]?: T8,
|
||||
--- [9]?: T9,
|
||||
--- [10]?: T10,
|
||||
---}
|
||||
---@param i? integer
|
||||
---@param j? integer
|
||||
---@return T1, T2, T3, T4, T5, T6, T7, T8, T9, T10
|
||||
---@nodiscard
|
||||
function unpack(list, i, j)
|
||||
error {list, i, j}
|
||||
end
|
||||
end
|
||||
|
||||
local f = assert(SMODS.load_file "src/lib/funky.lua")() or require "lib.funky"
|
||||
|
||||
--- Queues an event to be run.
|
||||
--- Note that events added this way implicitly `return true` unless you explicitly `return false`.
|
||||
--- For `front`; boolean `true` to add the event to the front of the queue, rather than the end.
|
||||
--- @generic T: fun():boolean?|Event
|
||||
--- @param fun T|Event|{front?: boolean} The table or function to turn into an event.
|
||||
--- @return T fun
|
||||
local function q(fun)
|
||||
local ev = protect_ev(fun)
|
||||
G.E_MANAGER:add_event(ev, nil, ev.front)
|
||||
return fun
|
||||
--- Note that events added this way implicitly `return true` unless you explicitly `return false`, unlike the vanilla ones.
|
||||
--- @param fun (fun():false|nil)|Event The event or a function to run turn into an event.
|
||||
--- @param front boolean|nil `true` to add the event to the front of the queue, rather than the end.
|
||||
local function q(fun, front)
|
||||
G.E_MANAGER:add_event(protect_ev(fun), nil, front)
|
||||
end
|
||||
|
||||
--- Determines if a center is allowed to be usable.
|
||||
---@return boolean
|
||||
local function u()
|
||||
return not ((G.play and next(G.play.cards) or G.CONTROLLER.locked or G.GAME.STOP_USE and G.GAME.STOP_USE > 0) and
|
||||
return not ((G.play and #G.play.cards > 0 or G.CONTROLLER.locked or
|
||||
(G.GAME.STOP_USE and G.GAME.STOP_USE > 0)) and
|
||||
G.STATE ~= G.STATES.HAND_PLAYED and
|
||||
G.STATE ~= G.STATES.DRAW_TO_HAND and
|
||||
G.STATE ~= G.STATES.PLAY_TAROT)
|
||||
end
|
||||
|
||||
--- Creates one or more cards.
|
||||
---@param ... any
|
||||
---@return Card|Tag|(Card|Tag[])
|
||||
local function c(...)
|
||||
local cards = f {...}
|
||||
:flatmap(flatten)
|
||||
:where(type, "string")
|
||||
:map(string.lower)
|
||||
:map(find)
|
||||
:where(f.id)
|
||||
:map(add)
|
||||
:values()
|
||||
:table()
|
||||
|
||||
return #cards > 1 and cards or cards[1]
|
||||
end
|
||||
|
||||
return {f, q, u, setmetatable({}, {
|
||||
__call = function(_, ...)
|
||||
return c(...)
|
||||
end,
|
||||
__index = function(_, k)
|
||||
return c(k)
|
||||
end,
|
||||
__newindex = function(_, k, v)
|
||||
local n = tonumber(v)
|
||||
|
||||
for _ = 1, type(n) == "number" and n or 1 do
|
||||
c(k)
|
||||
end
|
||||
end,
|
||||
})}
|
||||
return {f, q, u}
|
||||
|
|
|
|||
145
src/main.lua
|
|
@ -1,130 +1,73 @@
|
|||
local qol = assert(SMODS.load_file "src/lib/shared.lua")() or require "lib.shared"
|
||||
local f, q = qol[1], qol[2]
|
||||
|
||||
q {
|
||||
front = true,
|
||||
no_delete = true,
|
||||
blocking = false,
|
||||
func = function()
|
||||
local contributors = (Bakery_API or {}).contributors
|
||||
|
||||
if not contributors then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Special shoutout to all contributors. <3
|
||||
local credits = {
|
||||
aster = {
|
||||
name = "asterSSH",
|
||||
fg = HEX "f8f8f2ff",
|
||||
bg = HEX "bd93f9ff",
|
||||
},
|
||||
bakersdozenbagels = {
|
||||
name = "BakersDozenBagels",
|
||||
fg = HEX "362708ff",
|
||||
bg = HEX "edd198ff",
|
||||
},
|
||||
char = {
|
||||
name = "char (@irregulester)",
|
||||
fg = HEX "f8f8f2ff",
|
||||
bg = HEX "ff79c6ff",
|
||||
},
|
||||
ghostlyfield = {
|
||||
name = "ghostlyfield",
|
||||
fg = HEX "ffffffff",
|
||||
bg = HEX "b290e6ff",
|
||||
},
|
||||
hamester = {
|
||||
name = "Hamester",
|
||||
fg = HEX "ffffffff",
|
||||
bg = HEX "ffa100ff",
|
||||
},
|
||||
redstoad = {
|
||||
name = "RedsToad",
|
||||
fg = HEX "ffffffff",
|
||||
bg = HEX "da4044ff",
|
||||
},
|
||||
}
|
||||
|
||||
f(credits):each(function(v, k)
|
||||
contributors["Roland_" .. k] = v
|
||||
-- G.ARGS.LOC_COLOURS["Bakery_credit_fg_Roland_" .. k] = v.fg
|
||||
-- G.ARGS.LOC_COLOURS["Bakery_credit_bg_Roland_" .. k] = v.bg
|
||||
end)
|
||||
|
||||
if not SMODS.Mods.DebugPlus or not SMODS.Mods.Roland.config.import_funky then
|
||||
return
|
||||
end
|
||||
|
||||
_G.f, _G.q, _G.u, _G.c = unpack(qol)
|
||||
end,
|
||||
}
|
||||
|
||||
f {
|
||||
"challenge",
|
||||
"spectral",
|
||||
"edition",
|
||||
"tweaks",
|
||||
"blind",
|
||||
"charm",
|
||||
"joker",
|
||||
"tarot",
|
||||
"back",
|
||||
"seal",
|
||||
"tag",
|
||||
"voucher",
|
||||
}:each(function(v)
|
||||
qol[1] {"challenge", "spectral", "tweaks", "blind", "charm", "joker", "back", "seal"}:each(function(v)
|
||||
assert(SMODS.load_file("src/" .. v .. ".lua"))(qol)
|
||||
end)
|
||||
|
||||
if Balatest then
|
||||
f {"joker", "blind", "spectral"}:each(function(v)
|
||||
qol[1] {"joker", "blind", "spectral"}:each(function(v)
|
||||
assert(SMODS.load_file("src/tests/" .. v .. ".tests.lua"))(qol)
|
||||
end)
|
||||
end
|
||||
|
||||
local function toggle(id)
|
||||
return create_toggle {
|
||||
label = localize {type = "variable", key = "b_Roland_" .. id},
|
||||
ref_table = SMODS.Mods.Roland.config,
|
||||
ref_value = id,
|
||||
scale = 1.5,
|
||||
}
|
||||
end
|
||||
qol[2](function()
|
||||
---@type table<string, {name: string, fg: table, bg: table}>
|
||||
local contributors = Bakery_API.contributors
|
||||
|
||||
local animated = SMODS.Mods.Roland.config.animated_icon
|
||||
contributors.Roland_aster = {
|
||||
name = "asterSSH",
|
||||
fg = HEX "f8f8f2ff",
|
||||
bg = HEX "bd93f9ff",
|
||||
}
|
||||
|
||||
contributors.Roland_char = {
|
||||
name = "char (@irregulester)",
|
||||
fg = HEX "f8f8f2ff",
|
||||
bg = HEX "ff79c6ff",
|
||||
}
|
||||
end, true)
|
||||
|
||||
SMODS.Atlas {
|
||||
px = 256,
|
||||
py = 256,
|
||||
key = "modicon",
|
||||
fps = animated and 12 or nil,
|
||||
frames = animated and 12 or nil,
|
||||
path = animated and "icon.png" or "unicon.png",
|
||||
atlas_table = animated and "ANIMATION_ATLAS" or "ASSET_ATLAS",
|
||||
path = "icon.png",
|
||||
}
|
||||
|
||||
---@diagnostic disable-next-line: duplicate-set-field
|
||||
function SMODS.current_mod.config_tab()
|
||||
return {
|
||||
n = G.UIT.ROOT,
|
||||
config = {minw = 1, minh = 1, align = "tl", padding = 0.1, colour = G.C.BLACK},
|
||||
config = {r = 0.1, minw = 4, minh = 4, align = "tr", padding = 0.2, colour = G.C.BLACK},
|
||||
nodes = {{
|
||||
n = G.UIT.C,
|
||||
config = {minw = 1, minh = 1, align = "tl", padding = 0.1, colour = G.C.CLEAR},
|
||||
config = {minw = 1, minh = 1, align = "tr", padding = 0.2, colour = G.C.CLEAR},
|
||||
nodes = {
|
||||
toggle "animated_icon",
|
||||
toggle "cool_phones",
|
||||
toggle "faster_planets",
|
||||
-- toggle "illusion_seal",
|
||||
-- toggle "no_wild_debuff",
|
||||
toggle "vitriol",
|
||||
toggle "equinox_assist",
|
||||
SMODS.Mods.DebugPlus and toggle "import_funky",
|
||||
G.P_CENTERS.c_Bakery_Scribe and toggle "scribable_basket",
|
||||
Talisman and toggle "harsh_ante_scaling",
|
||||
create_toggle {
|
||||
label = localize {type = "variable", key = "b_Roland_equinox_assist"},
|
||||
ref_table = SMODS.Mods.Roland.config,
|
||||
ref_value = "equinox_assist",
|
||||
scale = 2,
|
||||
},
|
||||
SMODS.Mods.DebugPlus and UIBox_button {
|
||||
label = {localize {type = "variable", key = "b_Roland_debug_export"}},
|
||||
func = G.P_CENTERS.j_Roland_escapey.debug_export,
|
||||
button = "Roland_debug_export",
|
||||
colour = G.C.MULT,
|
||||
col = true,
|
||||
scale = 5,
|
||||
minw = 5,
|
||||
},
|
||||
},
|
||||
}},
|
||||
}
|
||||
end
|
||||
|
||||
SMODS.current_mod.qol = qol
|
||||
function SMODS.current_mod.optional_features()
|
||||
return {cardareas = {deck = true, unscored = true}}
|
||||
end
|
||||
|
||||
function G.FUNCS.Roland_debug_export(_, tbl)
|
||||
local to = tbl or _G
|
||||
to.f, to.q, to.u = unpack(qol)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
local f, q = (... or require "lib.shared")[1], (... or require "lib.shared")[2]
|
||||
local f, q = unpack(... or require "lib.shared")
|
||||
|
||||
SMODS.Atlas {
|
||||
px = 71,
|
||||
|
|
@ -11,9 +11,8 @@ SMODS.Seal {
|
|||
key = "glass",
|
||||
atlas = "seal",
|
||||
pos = {x = 0, y = 0},
|
||||
attributes = {"destroy_card", "tag"},
|
||||
badge_colour = HEX "a6a6a6ff",
|
||||
pronouns = "they_them",
|
||||
pronouns = "he_him",
|
||||
calculate = function(_, card, context)
|
||||
local function eq(v)
|
||||
return v == card
|
||||
|
|
|
|||
149
src/spectral.lua
|
|
@ -1,4 +1,6 @@
|
|||
local f, q, u = (... or require "lib.shared")[1], (... or require "lib.shared")[2], (... or require "lib.shared")[3]
|
||||
local f, q, u = unpack(... or require "lib.shared")
|
||||
|
||||
local negative = {key = "e_negative_consumable", set = "Edition", config = {extra = 1}}
|
||||
|
||||
local spectral = (function()
|
||||
local x = 0
|
||||
|
|
@ -6,13 +8,19 @@ local spectral = (function()
|
|||
---@param tbl SMODS.Consumable|{artist?: string}
|
||||
---@return SMODS.Consumable
|
||||
return function(tbl)
|
||||
tbl.artist = tbl.artist and "Roland_" .. tbl.artist or nil
|
||||
tbl.pos = {x = x, y = 0}
|
||||
tbl.atlas = "spectral"
|
||||
tbl.set = "Spectral"
|
||||
tbl.cost = 4
|
||||
tbl.set = "Spectral"
|
||||
tbl.atlas = "spectral"
|
||||
tbl.pos = {x = x, y = 0}
|
||||
tbl.artist = tbl.artist and "Roland_" .. tbl.artist or nil
|
||||
local ret = SMODS.Consumable(tbl)
|
||||
x = x + 1
|
||||
return q(SMODS.Consumable(tbl))
|
||||
|
||||
q(function()
|
||||
Bakery_API.credit(ret)
|
||||
end)
|
||||
|
||||
return ret
|
||||
end
|
||||
end)()
|
||||
|
||||
|
|
@ -30,10 +38,41 @@ SMODS.Sound {
|
|||
|
||||
spectral {
|
||||
key = "afterimage",
|
||||
pronouns = "she_they",
|
||||
pronouns = "he_they",
|
||||
artist = "aster",
|
||||
config = {extra = {amount = 1, hand = -2}},
|
||||
loc_vars = function(_, info_queue, card)
|
||||
table.insert(info_queue, negative)
|
||||
return {vars = {card.ability.extra.amount, card.ability.extra.hand}}
|
||||
end,
|
||||
can_use = function(_, card)
|
||||
return u() and card.ability.extra.amount == #Bakery_API.get_highlighted()
|
||||
end,
|
||||
use = function(_, card)
|
||||
f(Bakery_API.get_highlighted()):each(function(v)
|
||||
q {
|
||||
delay = 0.1,
|
||||
func = function()
|
||||
v:set_edition {negative = true}
|
||||
v:juice_up(0.5, 0.5)
|
||||
end,
|
||||
}
|
||||
end)
|
||||
|
||||
q {
|
||||
delay = 0.1,
|
||||
func = function()
|
||||
G.hand:change_size(card.ability.extra.hand)
|
||||
Bakery_API.unhighlight_all()
|
||||
end,
|
||||
}
|
||||
end,
|
||||
}
|
||||
|
||||
spectral {
|
||||
key = "dual",
|
||||
pronouns = "they_them",
|
||||
config = {extra = {amount = 2}},
|
||||
attributes = {"seal", "modify_card", "spectral"},
|
||||
loc_vars = function(_, _, card)
|
||||
return {vars = {card.ability.extra.amount}}
|
||||
end,
|
||||
|
|
@ -41,13 +80,13 @@ spectral {
|
|||
return u() and #G.hand.cards > 0
|
||||
end,
|
||||
use = function(_, card, _)
|
||||
local cards = f(G.hand.cards):table()
|
||||
local cards = f(G.hand.cards, ipairs):table()
|
||||
pseudoshuffle(cards, pseudoseed "RolandDual")
|
||||
|
||||
f(cards):take(card.ability.extra.amount):each(function(v)
|
||||
local seal
|
||||
|
||||
for _ = 1, 64 do
|
||||
for _ = 1, 31 do
|
||||
seal = SMODS.poll_seal {guaranteed = true}
|
||||
|
||||
if seal ~= "Roland_glass" then
|
||||
|
|
@ -61,72 +100,9 @@ spectral {
|
|||
}
|
||||
|
||||
spectral {
|
||||
key = "primal",
|
||||
key = "mirror",
|
||||
pronouns = "he_him",
|
||||
artist = "aster",
|
||||
attributes = {"enhancements", "modify_card", "spectral"},
|
||||
loc_vars = function(_, info_queue)
|
||||
table.insert(info_queue, G.P_CENTERS.m_stone)
|
||||
end,
|
||||
can_use = function()
|
||||
return next(G.hand.cards) and u()
|
||||
end,
|
||||
use = function(_, card)
|
||||
q {
|
||||
trigger = "after",
|
||||
delay = 0.4,
|
||||
func = function()
|
||||
card:juice_up(0.3, 0.5)
|
||||
play_sound("tarot1")
|
||||
end,
|
||||
}
|
||||
|
||||
f(G.hand.cards):each(function(v, k)
|
||||
local percent = 1.15 - (k - 0.999) / (#G.hand.cards - 0.998) * 0.3
|
||||
|
||||
q {
|
||||
trigger = "after",
|
||||
delay = 0.15,
|
||||
func = function()
|
||||
v:flip()
|
||||
v:juice_up(0.3, 0.3)
|
||||
play_sound("card1", percent)
|
||||
return true
|
||||
end,
|
||||
}
|
||||
end)
|
||||
|
||||
f(G.hand.cards):each(function(v)
|
||||
q(function()
|
||||
v:set_ability(G.P_CENTERS.m_stone)
|
||||
end)
|
||||
end)
|
||||
|
||||
f(G.hand.cards):each(function(v, k)
|
||||
local percent = 0.85 + (k - 0.999) / (#G.hand.cards - 0.998) * 0.3
|
||||
|
||||
q {
|
||||
trigger = "after",
|
||||
delay = 0.15,
|
||||
func = function()
|
||||
v:flip()
|
||||
v:juice_up(0.3, 0.3)
|
||||
play_sound("tarot2", percent, 0.6)
|
||||
return true
|
||||
end,
|
||||
}
|
||||
end)
|
||||
|
||||
delay(0.5)
|
||||
end,
|
||||
}
|
||||
|
||||
spectral {
|
||||
key = "refract",
|
||||
pronouns = "it_its",
|
||||
artist = "aster",
|
||||
config = {extra = {amount = 2}},
|
||||
attributes = {"seal", "modify_card", "spectral"},
|
||||
config = {extra = {amount = 1}},
|
||||
loc_vars = function(_, info_queue, card)
|
||||
table.insert(info_queue, G.P_SEALS.Roland_glass)
|
||||
return {vars = {card.ability.extra.amount}}
|
||||
|
|
@ -141,21 +117,20 @@ spectral {
|
|||
end,
|
||||
}
|
||||
|
||||
spectral {
|
||||
local void = spectral {
|
||||
key = "void",
|
||||
pronouns = "it_its",
|
||||
artist = "aster",
|
||||
soul_rate = 0.003,
|
||||
soul_set = "Spectral",
|
||||
config = {extra = {amount = 2}},
|
||||
attributes = {"destroy_card", "generation", "spectral"},
|
||||
loc_vars = function(_, info_queue, card)
|
||||
table.insert(info_queue, {key = "e_negative_consumable", set = "Edition", config = {extra = 1}})
|
||||
table.insert(info_queue, negative)
|
||||
table.insert(info_queue, G.P_CENTERS.c_cryptid)
|
||||
return {vars = {card.ability.extra.amount}}
|
||||
end,
|
||||
can_use = function()
|
||||
return next(G.playing_cards) and u()
|
||||
return #G.playing_cards > 1 and not not u()
|
||||
end,
|
||||
use = function(_, card)
|
||||
local function destructible(v)
|
||||
|
|
@ -181,15 +156,25 @@ spectral {
|
|||
f(cards):each(destroy)
|
||||
f(G.jokers.cards):each(calculate_joker)
|
||||
|
||||
f(card.ability.extra.amount):each(function()
|
||||
for _ = 1, card.ability.extra.amount do
|
||||
local cryptid = create_card(nil, G.consumeables, nil, nil, nil, nil, "c_cryptid", "void")
|
||||
cryptid:set_edition({negative = true}, true)
|
||||
cryptid:add_to_deck()
|
||||
G.consumeables:emplace(cryptid)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
play_sound("Roland_void", 1, 0.7)
|
||||
q {delay = 0.28, timer = "REAL", trigger = "after", func = void}
|
||||
|
||||
q {
|
||||
delay = 0.28,
|
||||
timer = "REAL",
|
||||
trigger = "after",
|
||||
func = void,
|
||||
}
|
||||
end,
|
||||
}
|
||||
|
||||
q(function()
|
||||
void.hidden = not SMODS.Mods.Cryptid
|
||||
end)
|
||||
|
|
|
|||
142
src/tag.lua
|
|
@ -1,142 +0,0 @@
|
|||
local f, q = (... or require "lib.shared")[1], (... or require "lib.shared")[2]
|
||||
|
||||
SMODS.Atlas {
|
||||
px = 34,
|
||||
py = 34,
|
||||
key = "tag",
|
||||
path = "tag.png",
|
||||
}
|
||||
|
||||
local function apply_frozen(tag, context)
|
||||
return function()
|
||||
q {
|
||||
delay = 0.4,
|
||||
trigger = "after",
|
||||
func = function()
|
||||
play_sound "tarot1"
|
||||
tag:juice_up(0.3, 0.5)
|
||||
end,
|
||||
}
|
||||
|
||||
q {
|
||||
delay = 0.15,
|
||||
trigger = "after",
|
||||
func = function()
|
||||
context.card:flip()
|
||||
play_sound("card1", 0.85)
|
||||
context.card:juice_up(0.3, 0.3)
|
||||
end,
|
||||
}
|
||||
|
||||
delay(0.2)
|
||||
|
||||
q {
|
||||
delay = 0.1,
|
||||
trigger = "after",
|
||||
func = function()
|
||||
context.card:set_edition {Roland_frozen = true}
|
||||
end,
|
||||
}
|
||||
|
||||
q {
|
||||
delay = 0.15,
|
||||
trigger = "after",
|
||||
func = function()
|
||||
context.card:flip()
|
||||
play_sound("tarot2", 0.85, 0.6)
|
||||
context.card:juice_up(0.3, 0.3)
|
||||
end,
|
||||
}
|
||||
|
||||
delay(0.1)
|
||||
end
|
||||
end
|
||||
|
||||
SMODS.Tag {
|
||||
key = "freeze",
|
||||
atlas = "tag",
|
||||
pronouns = "any_all",
|
||||
min_ante = 1,
|
||||
pos = {x = 0, y = 0},
|
||||
config = {amount = 5},
|
||||
loc_vars = function(self, info_queue, tag)
|
||||
info_queue[#info_queue + 1] = G.P_CENTERS.e_Roland_frozen
|
||||
tag.ability = tag.ability or {}
|
||||
return {vars = {tag.ability.amount or self.config.amount}}
|
||||
end,
|
||||
apply = function(self, tag, context)
|
||||
tag.ability = tag.ability or {}
|
||||
|
||||
if not tag.triggered and context.type == "Bakery_play_hand_late" and tag.ability.amount == 0 then
|
||||
tag.triggered = true
|
||||
tag:yep("X", G.C.RED, f.tru)
|
||||
end
|
||||
|
||||
if tag.triggered or
|
||||
(tag.ability.amount or self.config.amount) <= 0 or
|
||||
((context.card or {}).edition or {}).Roland_frozen or
|
||||
context.type ~= "Bakery_score_card" then
|
||||
return
|
||||
end
|
||||
|
||||
tag.ability.amount = (tag.ability.amount or self.config.amount) - 1
|
||||
return {func = apply_frozen(tag, context)}
|
||||
end,
|
||||
}
|
||||
|
||||
SMODS.Tag {
|
||||
key = "invisible",
|
||||
atlas = "tag",
|
||||
pronouns = "any_all",
|
||||
min_ante = 2,
|
||||
pos = {x = 1, y = 0},
|
||||
config = {invis_rounds = 0, total_rounds = 2},
|
||||
loc_vars = function(self, _, tag)
|
||||
tag.ability = tag.ability or f(self.config):table()
|
||||
local main_end = {}
|
||||
|
||||
local _ = f((G.jokers or {}).cards or {}):map "edition":any "negative" and
|
||||
localize {type = "other", key = "remove_negative", nodes = main_end, vars = {}}
|
||||
|
||||
return {
|
||||
vars = {
|
||||
tag.ability.total_rounds or self.config.total_rounds,
|
||||
tag.ability.invis_rounds or self.config.invis_rounds,
|
||||
},
|
||||
main_end = main_end[1],
|
||||
}
|
||||
end,
|
||||
increment = function(self)
|
||||
f(G.GAME.tags):where("key", "tag_Roland_invisible"):each(function(v)
|
||||
v.ability = v.ability or {}
|
||||
v.ability.invis_rounds = (v.ability.invis_rounds or self.config.invis_rounds) + 1
|
||||
v:juice_up()
|
||||
end)
|
||||
end,
|
||||
apply = function(self, tag)
|
||||
local modifiers = G.GAME.modifiers
|
||||
tag.ability = tag.ability or {}
|
||||
local ab = tag.ability
|
||||
ab.invis_rounds = ab.invis_rounds or self.config.invis_rounds
|
||||
ab.total_rounds = ab.total_rounds or self.config.total_rounds
|
||||
|
||||
if tag.triggered or
|
||||
not next(G.jokers.cards) or
|
||||
ab.invis_rounds < ab.total_rounds or
|
||||
#G.jokers.cards + (modifiers.Roland_invisible or 0) >= G.jokers.config.card_limit then
|
||||
return
|
||||
end
|
||||
|
||||
tag.triggered = true
|
||||
modifiers.Roland_invisible = (modifiers.Roland_invisible or 0) + 1
|
||||
|
||||
tag:yep("!", G.C.GREY, function()
|
||||
local copied = pseudorandom_element(G.jokers.cards, pseudoseed "Roland_invisible")
|
||||
local copy = copy_card(copied, nil, nil, nil, copied.edition and copied.edition.negative)
|
||||
G.jokers:emplace(copy)
|
||||
copy:add_to_deck()
|
||||
modifiers.Roland_invisible = (modifiers.Roland_invisible or 0) - 1
|
||||
return true
|
||||
end)
|
||||
end,
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
local f, q, u = (... or require "lib.shared")[1], (... or require "lib.shared")[2], (... or require "lib.shared")[3]
|
||||
|
||||
SMODS.Atlas {
|
||||
px = 71,
|
||||
py = 95,
|
||||
key = "tarot",
|
||||
path = "tarot.png",
|
||||
}
|
||||
|
||||
q(SMODS.Consumable {
|
||||
key = "coolheaded",
|
||||
pos = {x = 0, y = 0},
|
||||
config = {extra = {amount = 1}},
|
||||
cost = 3,
|
||||
set = "Tarot",
|
||||
atlas = "tarot",
|
||||
artist = "Roland_aster",
|
||||
attributes = {"editions", "modify_card", "spectral"},
|
||||
loc_vars = function(_, info_queue, card)
|
||||
table.insert(info_queue, G.P_CENTERS.e_Roland_frozen)
|
||||
return {vars = {card.ability.extra.amount}}
|
||||
end,
|
||||
can_use = function(_, card)
|
||||
if not u() then
|
||||
return false
|
||||
end
|
||||
|
||||
local highlighted = Bakery_API.get_highlighted()
|
||||
|
||||
return #G.jokers.highlighted + #highlighted == card.ability.extra.amount and
|
||||
f(G.jokers.highlighted):concat(highlighted):all(function(v)
|
||||
return not v.edition
|
||||
end)
|
||||
end,
|
||||
use = function()
|
||||
f(G.jokers.highlighted):concat(Bakery_API.get_highlighted()):each(function(v)
|
||||
q {
|
||||
delay = 0.1,
|
||||
func = function()
|
||||
v:set_edition {Roland_frozen = true}
|
||||
end,
|
||||
}
|
||||
end)
|
||||
end,
|
||||
})
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
local f = (... or require "lib.shared")[1]
|
||||
local f = unpack(... or require "lib.shared")
|
||||
|
||||
if not Balatest then
|
||||
return
|
||||
|
|
@ -192,9 +192,9 @@ Balatest.TestPlay {
|
|||
}
|
||||
|
||||
Balatest.TestPlay {
|
||||
category = {"blind", "mitotic"},
|
||||
name = "mitotic",
|
||||
blind = "bl_Roland_mitotic",
|
||||
category = {"blind", "xerox"},
|
||||
name = "xerox",
|
||||
blind = "bl_Roland_xerox",
|
||||
execute = function()
|
||||
Balatest.discard {"2S"}
|
||||
end,
|
||||
|
|
@ -204,9 +204,9 @@ Balatest.TestPlay {
|
|||
}
|
||||
|
||||
Balatest.TestPlay {
|
||||
category = {"blind", "mitotic"},
|
||||
name = "mitotic_disabled",
|
||||
blind = "bl_Roland_mitotic",
|
||||
category = {"blind", "xerox"},
|
||||
name = "xerox_disabled",
|
||||
blind = "bl_Roland_xerox",
|
||||
jokers = {"j_chicot"},
|
||||
execute = function()
|
||||
Balatest.discard {"2S"}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,330 @@ if not Balatest then
|
|||
return
|
||||
end
|
||||
|
||||
Balatest.TestPlay {
|
||||
category = {"joker", "escapey", "escape"},
|
||||
name = "escapey_none",
|
||||
jokers = {"j_Roland_escapey"},
|
||||
execute = function() end,
|
||||
assert = function()
|
||||
Balatest.assert(not G.jokers.cards[1].config.center:Bakery_can_use(G.jokers.cards[1]))
|
||||
end,
|
||||
}
|
||||
|
||||
Balatest.TestPlay {
|
||||
category = {"joker", "escapey", "escape"},
|
||||
name = "escapey_one_consumable",
|
||||
jokers = {"j_Roland_escapey"},
|
||||
consumeables = {"c_strength"},
|
||||
execute = function()
|
||||
Balatest.q(function()
|
||||
G.FUNCS.Bakery_use_joker {config = {ref_table = G.jokers.cards[1]}}
|
||||
end)
|
||||
|
||||
Balatest.wait()
|
||||
end,
|
||||
assert = function()
|
||||
Balatest.assert_eq(G.GAME.hands["High Card"].level, 2)
|
||||
end,
|
||||
}
|
||||
|
||||
Balatest.TestPlay {
|
||||
category = {"joker", "escapey", "escape"},
|
||||
name = "escapey_two_consumables",
|
||||
jokers = {"j_Roland_escapey"},
|
||||
consumeables = {"c_strength", "c_strength"},
|
||||
execute = function()
|
||||
Balatest.q(function()
|
||||
G.FUNCS.Bakery_use_joker {config = {ref_table = G.jokers.cards[1]}}
|
||||
end)
|
||||
|
||||
Balatest.wait()
|
||||
end,
|
||||
assert = function()
|
||||
Balatest.assert_eq(G.GAME.hands["High Card"].level, 3)
|
||||
end,
|
||||
}
|
||||
|
||||
Balatest.TestPlay {
|
||||
category = {"joker", "escapey", "escape"},
|
||||
name = "escapey_one_tag",
|
||||
jokers = {"j_Roland_escapey"},
|
||||
no_auto_start = true,
|
||||
execute = function()
|
||||
Balatest.skip_blind("tag_investment")
|
||||
|
||||
Balatest.q(function()
|
||||
G.FUNCS.Bakery_use_joker {config = {ref_table = G.jokers.cards[1]}}
|
||||
end)
|
||||
|
||||
Balatest.wait()
|
||||
end,
|
||||
assert = function()
|
||||
Balatest.assert_eq(G.GAME.hands["High Card"].level, 2)
|
||||
end,
|
||||
}
|
||||
|
||||
Balatest.TestPlay {
|
||||
category = {"joker", "escapey", "escape"},
|
||||
name = "escapey_two_tags",
|
||||
jokers = {"j_Roland_escapey"},
|
||||
no_auto_start = true,
|
||||
execute = function()
|
||||
Balatest.skip_blind("tag_investment")
|
||||
Balatest.skip_blind("tag_investment")
|
||||
|
||||
Balatest.q(function()
|
||||
G.FUNCS.Bakery_use_joker {config = {ref_table = G.jokers.cards[1]}}
|
||||
end)
|
||||
|
||||
Balatest.wait()
|
||||
end,
|
||||
assert = function()
|
||||
Balatest.assert_eq(G.GAME.hands["High Card"].level, 3)
|
||||
end,
|
||||
}
|
||||
|
||||
Balatest.TestPlay {
|
||||
category = {"joker", "escapey", "escape"},
|
||||
name = "escapey_consumables_and_tags",
|
||||
jokers = {"j_Roland_escapey"},
|
||||
consumeables = {"c_strength"},
|
||||
no_auto_start = true,
|
||||
execute = function()
|
||||
Balatest.skip_blind("tag_investment")
|
||||
Balatest.skip_blind("tag_investment")
|
||||
|
||||
Balatest.q(function()
|
||||
G.FUNCS.Bakery_use_joker {config = {ref_table = G.jokers.cards[1]}}
|
||||
end)
|
||||
|
||||
Balatest.wait()
|
||||
end,
|
||||
assert = function()
|
||||
Balatest.assert_eq(G.GAME.hands["High Card"].level, 2)
|
||||
end,
|
||||
}
|
||||
|
||||
Balatest.TestPlay {
|
||||
category = {"joker", "escapey", "escape"},
|
||||
name = "escapey_partial_selected_consumables_and_tags",
|
||||
jokers = {"j_Roland_escapey"},
|
||||
consumeables = {"c_strength", "c_strength"},
|
||||
no_auto_start = true,
|
||||
execute = function()
|
||||
Balatest.skip_blind("tag_investment")
|
||||
Balatest.skip_blind("tag_investment")
|
||||
|
||||
Balatest.q(function()
|
||||
G.consumeables:add_to_highlighted(G.consumeables.cards[1])
|
||||
end)
|
||||
|
||||
Balatest.wait()
|
||||
|
||||
Balatest.q(function()
|
||||
G.FUNCS.Bakery_use_joker {config = {ref_table = G.jokers.cards[1]}}
|
||||
end)
|
||||
|
||||
Balatest.wait()
|
||||
end,
|
||||
assert = function()
|
||||
Balatest.assert_eq(G.GAME.hands["High Card"].level, 2)
|
||||
end,
|
||||
}
|
||||
|
||||
Balatest.TestPlay {
|
||||
category = {"joker", "escapey", "escape"},
|
||||
name = "escapey_full_selected_consumables_and_tags",
|
||||
jokers = {"j_Roland_escapey"},
|
||||
consumeables = {"c_strength"},
|
||||
no_auto_start = true,
|
||||
execute = function()
|
||||
Balatest.skip_blind("tag_investment")
|
||||
Balatest.skip_blind("tag_investment")
|
||||
|
||||
Balatest.q(function()
|
||||
G.consumeables:add_to_highlighted(G.consumeables.cards[1])
|
||||
end)
|
||||
|
||||
Balatest.wait()
|
||||
|
||||
Balatest.q(function()
|
||||
G.FUNCS.Bakery_use_joker {config = {ref_table = G.jokers.cards[1]}}
|
||||
end)
|
||||
|
||||
Balatest.wait()
|
||||
end,
|
||||
assert = function()
|
||||
Balatest.assert_eq(G.GAME.hands["High Card"].level, 3)
|
||||
end,
|
||||
}
|
||||
|
||||
Balatest.TestPlay {
|
||||
category = {"joker", "escapey", "fuse"},
|
||||
name = "escapey_fusion",
|
||||
jokers = {"j_Roland_escapey", "j_Roland_escapey"},
|
||||
execute = function()
|
||||
Balatest.q(function()
|
||||
G.FUNCS.Bakery_use_joker {config = {ref_table = G.jokers.cards[1]}}
|
||||
end)
|
||||
|
||||
Balatest.wait()
|
||||
end,
|
||||
assert = function()
|
||||
Balatest.assert_eq(#G.jokers.cards, 1)
|
||||
Balatest.assert_eq(G.jokers.cards[1].sell_cost, 8)
|
||||
Balatest.assert_eq(G.jokers.cards[1].ability.extra.levels, 2)
|
||||
end,
|
||||
}
|
||||
|
||||
Balatest.TestPlay {
|
||||
category = {"joker", "escapey", "fuse"},
|
||||
name = "escapey_consumable_takes_precedence",
|
||||
jokers = {"j_Roland_escapey", "j_Roland_escapey"},
|
||||
consumeables = {"c_strength"},
|
||||
execute = function()
|
||||
Balatest.q(function()
|
||||
G.FUNCS.Bakery_use_joker {config = {ref_table = G.jokers.cards[1]}}
|
||||
end)
|
||||
|
||||
Balatest.wait()
|
||||
end,
|
||||
assert = function()
|
||||
Balatest.assert_eq(#G.jokers.cards, 2)
|
||||
Balatest.assert_eq(G.GAME.hands["High Card"].level, 2)
|
||||
end,
|
||||
}
|
||||
|
||||
Balatest.TestPlay {
|
||||
category = {"joker", "escapey", "fuse"},
|
||||
name = "escapey_tag_takes_precedence",
|
||||
jokers = {"j_Roland_escapey", "j_Roland_escapey"},
|
||||
no_auto_start = true,
|
||||
execute = function()
|
||||
Balatest.skip_blind("tag_investment")
|
||||
|
||||
Balatest.q(function()
|
||||
G.FUNCS.Bakery_use_joker {config = {ref_table = G.jokers.cards[1]}}
|
||||
end)
|
||||
|
||||
Balatest.wait()
|
||||
end,
|
||||
assert = function()
|
||||
Balatest.assert_eq(#G.jokers.cards, 2)
|
||||
Balatest.assert_eq(G.GAME.hands["High Card"].level, 2)
|
||||
end,
|
||||
}
|
||||
|
||||
Balatest.TestPlay {
|
||||
category = {"joker", "escapey", "fuse"},
|
||||
name = "escapey_fusion_takes_precedence",
|
||||
jokers = {"j_Roland_escapey", "j_Roland_escapey"},
|
||||
consumeables = {"c_strength"},
|
||||
execute = function()
|
||||
Balatest.q(function()
|
||||
G.consumeables:add_to_highlighted(G.consumeables.cards[1])
|
||||
end)
|
||||
|
||||
Balatest.wait()
|
||||
|
||||
Balatest.q(function()
|
||||
G.FUNCS.Bakery_use_joker {config = {ref_table = G.jokers.cards[1]}}
|
||||
end)
|
||||
|
||||
Balatest.wait()
|
||||
end,
|
||||
assert = function()
|
||||
Balatest.assert_eq(#G.jokers.cards, 1)
|
||||
Balatest.assert_eq(G.jokers.cards[1].sell_cost, 8)
|
||||
Balatest.assert_eq(G.jokers.cards[1].ability.extra.levels, 2)
|
||||
end,
|
||||
}
|
||||
|
||||
Balatest.TestPlay {
|
||||
category = {"joker", "escapey", "fuse"},
|
||||
name = "escapey_scribe_fusion",
|
||||
jokers = {"j_Roland_escapey"},
|
||||
execute = function()
|
||||
if not G.P_CENTERS.c_Bakery_Scribe then
|
||||
sendWarnMessage("escapey_scribe_fusion cannot run without c_Bakery_Scribe, skipping test.")
|
||||
return
|
||||
end
|
||||
|
||||
Balatest.q(function()
|
||||
local scribe = create_card(nil, G.consumeables, nil, nil, nil, nil, "c_Bakery_Scribe", "balatest")
|
||||
scribe:add_to_deck()
|
||||
G.consumeables:emplace(scribe)
|
||||
end)
|
||||
|
||||
Balatest.wait()
|
||||
|
||||
Balatest.q(function()
|
||||
G.jokers:add_to_highlighted(G.jokers.cards[1])
|
||||
end)
|
||||
|
||||
Balatest.wait()
|
||||
Balatest.use(function() return G.consumeables.cards[1] end)
|
||||
|
||||
Balatest.q(function()
|
||||
G.FUNCS.Bakery_use_joker {config = {ref_table = G.jokers.cards[1]}}
|
||||
end)
|
||||
|
||||
Balatest.wait()
|
||||
end,
|
||||
assert = function()
|
||||
if not G.P_CENTERS.c_Bakery_Scribe then
|
||||
return
|
||||
end
|
||||
|
||||
Balatest.assert_eq(#G.jokers.cards, 1)
|
||||
Balatest.assert_eq(G.jokers.cards[1].sell_cost, 8)
|
||||
Balatest.assert_eq(G.jokers.cards[1].ability.extra.levels, 1)
|
||||
end,
|
||||
}
|
||||
|
||||
Balatest.TestPlay {
|
||||
category = {"joker", "escapey", "fuse"},
|
||||
name = "escapey_scribe_fusion_alt",
|
||||
jokers = {"j_Roland_escapey"},
|
||||
execute = function()
|
||||
if not G.P_CENTERS.c_Bakery_Scribe then
|
||||
sendWarnMessage("escapey_scribe_fusion_alt cannot run without c_Bakery_Scribe, skipping test.")
|
||||
return
|
||||
end
|
||||
|
||||
Balatest.q(function()
|
||||
local scribe = create_card(nil, G.consumeables, nil, nil, nil, nil, "c_Bakery_Scribe", "balatest")
|
||||
scribe:add_to_deck()
|
||||
G.consumeables:emplace(scribe)
|
||||
end)
|
||||
|
||||
Balatest.wait()
|
||||
|
||||
Balatest.q(function()
|
||||
G.jokers:add_to_highlighted(G.jokers.cards[1])
|
||||
end)
|
||||
|
||||
Balatest.wait()
|
||||
Balatest.use(function() return G.consumeables.cards[1] end)
|
||||
|
||||
Balatest.q(function()
|
||||
G.jokers:add_to_highlighted(G.jokers.cards[2])
|
||||
G.FUNCS.Bakery_use_joker {config = {ref_table = G.jokers.cards[2]}}
|
||||
end)
|
||||
|
||||
Balatest.wait()
|
||||
end,
|
||||
assert = function()
|
||||
if not G.P_CENTERS.c_Bakery_Scribe then
|
||||
return
|
||||
end
|
||||
|
||||
Balatest.assert_eq(#G.jokers.cards, 1)
|
||||
Balatest.assert_eq(G.jokers.cards[1].sell_cost, 8)
|
||||
Balatest.assert_eq(G.jokers.cards[1].ability.extra.levels, 1)
|
||||
end,
|
||||
}
|
||||
|
||||
Balatest.TestPlay {
|
||||
category = {"joker", "martingale"},
|
||||
name = "martingale_oops",
|
||||
|
|
@ -10,7 +334,7 @@ Balatest.TestPlay {
|
|||
Balatest.play_hand {"2S"}
|
||||
end,
|
||||
assert = function()
|
||||
Balatest.assert_chips(7)
|
||||
Balatest.assert_chips(7 * 2)
|
||||
end,
|
||||
}
|
||||
|
||||
|
|
@ -23,6 +347,6 @@ Balatest.TestPlay {
|
|||
Balatest.play_hand {"2S"}
|
||||
end,
|
||||
assert = function()
|
||||
Balatest.assert_chips(1 / 0)
|
||||
Balatest.assert_chips(7 * math.pow(2, 32))
|
||||
end,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,22 @@ if not Balatest then
|
|||
return
|
||||
end
|
||||
|
||||
Balatest.TestPlay {
|
||||
category = {"spectral", "afterimage"},
|
||||
name = "afterimage",
|
||||
consumeables = {"c_Roland_afterimage"},
|
||||
deck = {cards = {{s = "S", r = "2"}}},
|
||||
execute = function()
|
||||
Balatest.highlight({"2S"})
|
||||
Balatest.use(G.consumeables.cards[1])
|
||||
Balatest.end_round()
|
||||
end,
|
||||
assert = function()
|
||||
Balatest.assert_eq(G.hand.config.card_limit, 51)
|
||||
Balatest.assert(G.deck.cards[1].edition.negative)
|
||||
end,
|
||||
}
|
||||
|
||||
Balatest.TestPlay {
|
||||
category = {"spectral", "void"},
|
||||
name = "spectral",
|
||||
|
|
|
|||
136
src/tweaks.lua
|
|
@ -1,40 +1,54 @@
|
|||
local f, q = (... or require "lib.shared")[1], (... or require "lib.shared")[2]
|
||||
SMODS.Joker:take_ownership("joker", {cost = 1}, true)
|
||||
local orig_set_debuff = Card.set_debuff
|
||||
local f, q = unpack(... or require "lib.shared")
|
||||
|
||||
function Card:set_debuff(should_debuff, ...)
|
||||
if self.ability.Roland_crimson ~= nil then
|
||||
self.ability.Roland_crimson = not not should_debuff
|
||||
return
|
||||
SMODS.Joker:take_ownership("joker", {cost = 1}, true)
|
||||
local orig_can_highlight = CardArea.can_highlight
|
||||
local orig_set_debuff = Card.set_debuff
|
||||
local orig_highlight = Card.highlight
|
||||
local orig_copy_card = copy_card
|
||||
|
||||
---@diagnostic disable-next-line: duplicate-set-field
|
||||
function CardArea:can_highlight(...)
|
||||
if self ~= G.consumeables then
|
||||
return orig_can_highlight(self, ...)
|
||||
end
|
||||
|
||||
if SMODS.get_enhancements(self).m_wild and SMODS.Mods.Roland.config.no_wild_debuff then
|
||||
--- Allows more flexibility when using the Escapey joker to delete specific consumables.
|
||||
self.config.highlighted_limit = 1 / 0
|
||||
return true
|
||||
end
|
||||
|
||||
---@diagnostic disable-next-line: duplicate-set-field
|
||||
function Card:set_debuff(...)
|
||||
if self.config and self.config.center_key == "m_wild" then
|
||||
self.debuff = false
|
||||
else
|
||||
orig_set_debuff(self, should_debuff, ...)
|
||||
orig_set_debuff(self, ...)
|
||||
end
|
||||
end
|
||||
|
||||
---@diagnostic disable-next-line: duplicate-set-field
|
||||
function Card:highlight(is_highlighted, ...)
|
||||
self.highlighted = is_highlighted
|
||||
|
||||
if not G.CONTROLLER.HID.controller then
|
||||
return orig_highlight(self, is_highlighted, ...)
|
||||
end
|
||||
end
|
||||
|
||||
local orig_use_consumeable = Card.use_consumeable
|
||||
|
||||
---@diagnostic disable-next-line: duplicate-set-field
|
||||
function Card:use_consumeable(area, copier, ...)
|
||||
if SMODS.Mods.Roland.config.faster_planets and self.ability.consumeable.hand_type then
|
||||
set_consumeable_usage(self)
|
||||
level_up_hand(copier or self, self.ability.consumeable.hand_type, true)
|
||||
return
|
||||
end
|
||||
|
||||
local seal_spectrals = {["Deja Vu"] = true, Medium = true, Talisman = true, Trance = true}
|
||||
|
||||
if not seal_spectrals[self.ability.name] then
|
||||
return orig_use_consumeable(self, area, copier, ...)
|
||||
end
|
||||
|
||||
local card = copier or self
|
||||
|
||||
f(Bakery_API.get_highlighted()):each(function(v)
|
||||
q(function()
|
||||
play_sound "tarot1"
|
||||
local card = (copier or self)
|
||||
card:juice_up(0.3, 0.5)
|
||||
end)
|
||||
|
||||
|
|
@ -47,83 +61,55 @@ function Card:use_consumeable(area, copier, ...)
|
|||
}
|
||||
end)
|
||||
|
||||
q {delay = 0.7, trigger = "after", func = Bakery_API.unhighlight_all}
|
||||
q {
|
||||
delay = 0.7,
|
||||
trigger = "after",
|
||||
func = function()
|
||||
Bakery_API.unhighlight_all()
|
||||
end,
|
||||
}
|
||||
end
|
||||
|
||||
local orig_use_card = G.FUNCS.use_card
|
||||
---@diagnostic disable-next-line: lowercase-global
|
||||
function copy_card(other, new_card, ...)
|
||||
local ret = orig_copy_card(other, new_card, ...)
|
||||
|
||||
function G.FUNCS.use_card(e, ...)
|
||||
local ref = e.config.ref_table or {}
|
||||
local consumeable = (ref.ability or {}).consumeable or {}
|
||||
|
||||
if not SMODS.Mods.Roland.config.faster_planets or
|
||||
(not consumeable.hand_type and not consumeable.hand_types) then
|
||||
return orig_use_card(e, ...)
|
||||
if new_card and new_card.edition and new_card.edition.key == "e_negative" then
|
||||
--- Fixes an issue where using 'c_death' will make negative
|
||||
--- cards do the inverse of what they're supposed to do.
|
||||
new_card.ability.card_limit = math.max(new_card.ability.card_limit, 1)
|
||||
end
|
||||
|
||||
local normal = ref.area ~= G.pack_cards or not G.GAME.pack_choices or G.GAME.pack_choices <= 0
|
||||
ref.from_area = ref.from_area or ref.area
|
||||
play_sound("tarot1", percent, 0.6)
|
||||
discover_card(ref.config.center)
|
||||
ref:use_consumeable(ref.area)
|
||||
SMODS.calculate_context {area = ref.area, consumeable = ref, using_consumeable = true}
|
||||
return ret
|
||||
end
|
||||
|
||||
q(function()
|
||||
ref:remove()
|
||||
local orig_can_highlight_area = Bakery_API.can_highlight_area
|
||||
|
||||
---@diagnostic disable-next-line: duplicate-set-field
|
||||
function Bakery_API.can_highlight_area(area, ...)
|
||||
return area == G.consumeables or orig_can_highlight_area(area, ...)
|
||||
end
|
||||
end)
|
||||
|
||||
if normal then
|
||||
return
|
||||
end
|
||||
|
||||
G.GAME.pack_choices = G.GAME.pack_choices - 1
|
||||
local _ = G.GAME.pack_choices <= 0 and G.FUNCS.end_consumeable()
|
||||
end
|
||||
|
||||
local orig_create_card_for_shop = create_card_for_shop
|
||||
|
||||
---@diagnostic disable-next-line: lowercase-global
|
||||
function create_card_for_shop(...)
|
||||
---@type Card
|
||||
local ret = orig_create_card_for_shop(...)
|
||||
|
||||
if not SMODS.Mods.Roland.config.illusion_seal or
|
||||
not G.GAME.used_vouchers.v_illusion or
|
||||
if not G.GAME.used_vouchers.v_illusion or
|
||||
not ({Default = true, Enhanced = true})[(((ret or {}).config or {}).center or {}).set] or
|
||||
pseudorandom(pseudoseed "Roland_illusion") <= 0.8 then
|
||||
return ret
|
||||
end
|
||||
|
||||
local seal = SMODS.poll_seal {type_key = "Roland_illusion_seal", guaranteed = true}
|
||||
local seal = SMODS.poll_seal {
|
||||
type_key = "Roland_illusion_seal",
|
||||
guaranteed = true,
|
||||
}
|
||||
|
||||
ret:set_seal(seal, true, true)
|
||||
return ret
|
||||
end
|
||||
|
||||
local orig_get_blind_amount = get_blind_amount
|
||||
|
||||
---@param ante number
|
||||
---@return table|number
|
||||
local function blind(ante)
|
||||
return ante == 39 and 1e294 or (to_number or f.id)(orig_get_blind_amount(ante))
|
||||
end
|
||||
|
||||
local function no_harsh_ante_scaling()
|
||||
return not Talisman or not SMODS.Mods.Roland.config.harsh_ante_scaling
|
||||
end
|
||||
|
||||
function get_blind_amount(ante, ...)
|
||||
local loop = 39
|
||||
|
||||
if ante < loop or no_harsh_ante_scaling() then
|
||||
return orig_get_blind_amount(ante, ...)
|
||||
end
|
||||
|
||||
if (ante - 9) / 15 >= loop then
|
||||
return 1 / 0
|
||||
end
|
||||
|
||||
local rem = tonumber(blind((ante % loop) + 1))
|
||||
|
||||
return ante / 15 >= loop and Big:new(f(blind(ante - (loop * 15))):map(f.const(10)):table()) or
|
||||
(ante / 9 >= loop and Big:new(f(ante / loop - 8):map(f.const(10)):concat {rem}:table()) or
|
||||
(ante / 2 >= loop and Big:new {rem, ante / loop} or
|
||||
(Big.constants and Big.constants.TEN or Big:new {10}):pow(rem)))
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,44 +0,0 @@
|
|||
local voucher = (function()
|
||||
local x = 0
|
||||
|
||||
---@param tbl SMODS.Voucher|{attributes: Attributes[]}
|
||||
---@return SMODS.Voucher
|
||||
return function(tbl)
|
||||
tbl.pos = {x = x, y = 0}
|
||||
tbl.atlas = "voucher"
|
||||
tbl.cost = 10
|
||||
x = x + 1
|
||||
return SMODS.Voucher(tbl)
|
||||
end
|
||||
end)()
|
||||
|
||||
SMODS.Atlas {
|
||||
px = 71,
|
||||
py = 95,
|
||||
key = "voucher",
|
||||
path = "voucher.png",
|
||||
}
|
||||
|
||||
voucher {
|
||||
key = "ceres",
|
||||
pronouns = "it_its",
|
||||
config = {extra = {amount = 1, hand_type = "Flush House"}},
|
||||
attributes = {"planet", "passive", "hand_type", "space"},
|
||||
loc_vars = function(_, _, card)
|
||||
return {vars = {card.ability.extra.amount}}
|
||||
end,
|
||||
in_pool = function(self)
|
||||
return G.GAME.hands[self.config.extra.hand_type].visible
|
||||
end,
|
||||
}
|
||||
|
||||
voucher {
|
||||
key = "neptune",
|
||||
pronouns = "it_its",
|
||||
requires = {"v_Roland_ceres"},
|
||||
config = {extra = {amount = 2, hand_type = "Straight Flush"}},
|
||||
attributes = {"planet", "passive", "hand_type", "space"},
|
||||
loc_vars = function(_, _, card)
|
||||
return {vars = {card.ability.extra.amount}}
|
||||
end,
|
||||
}
|
||||