Compare commits
No commits in common. "main" and "rewrite" have entirely different histories.
|
|
@ -33,7 +33,7 @@ table_separator_style = none
|
|||
trailing_table_separator = smart
|
||||
|
||||
# keep/remove/remove_table_only/remove_string_only
|
||||
call_arg_parentheses = remove
|
||||
call_arg_parentheses = keep
|
||||
|
||||
detect_end_of_line = false
|
||||
|
||||
|
|
|
|||
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"
|
||||
],
|
||||
}
|
||||
}
|
||||
52
README.md
|
|
@ -1,52 +0,0 @@
|
|||
# Roland
|
||||
|
||||
[](https://github.com/Emik03/Roland/blob/main/LICENSE)
|
||||
|
||||
This is a [Steamodded](https://github.com/Steamodded/smods) mod for the video game [Balatro (2024)](https://playbalatro.com).
|
||||
|
||||
This mod has been in the works since early 2025, and been worked on continously until its official public release as a celebration for my 23rd birthday.
|
||||
|
||||
---
|
||||
|
||||
- [About](#about)
|
||||
- [Contents](#contents)
|
||||
- [Installation](#installation)
|
||||
- [License](#license)
|
||||
|
||||
---
|
||||
|
||||
## About
|
||||
|
||||
The main theme of this mod centers around the addition of a new edition: Frozen.
|
||||
|
||||
Frozen can be applied to playing cards or jokers and will cause whatever state they have to be locked in place, removing any possibility of future scaling; positive or negative.
|
||||
|
||||
The primary goal is to create interesting interactions in-and-outside of the added editions. This does not necessarily mean that these mechanics have to be balanced, but does hopefully make new strategies viable and breathe new life into some of the base game's weaker jokers. It is designed to work very well with its parent mod [Bakery](https://github.com/BakersDozenBagels/BalatroBakery), but can work just as well on its own or with other content mods.
|
||||
|
||||
The mod offers a config for accessibility options, general convenience, modifications that I believe make the game healthier, and otherwise purely cosmetic.
|
||||
|
||||
## Contents
|
||||
|
||||
- 31 Jokers
|
||||
- 1 Tarot Card
|
||||
- 4 Spectral Cards
|
||||
- 2 Vouchers
|
||||
- 1 Seal
|
||||
- 1 Edition
|
||||
- 2 Tags
|
||||
- 9 Blinds
|
||||
- 4 Decks
|
||||
- 4 [Deck Sleeves (CardSleeves)](https://github.com/larswijn/CardSleeves)
|
||||
- 5 [Charms (Bakery)](https://github.com/BakersDozenBagels/BalatroBakery)
|
||||
|
||||
## Installation
|
||||
|
||||
1. Set up [Steamodded](https://github.com/Steamodded/smods/wiki#i-want-to-play-with-mods).
|
||||
2. Set up [Bakery](https://github.com/BakersDozenBagels). You are free to use the [Lite version](https://github.com/BakersDozenBagels/BalatroBakery/tree/lite) if you want to play Roland standalone.
|
||||
3. Clone the repository into your mods folder, or download it as a zip and place it there.
|
||||
|
||||
## License
|
||||
|
||||
This repository falls under the [MPL-2 license](https://www.mozilla.org/en-US/MPL/2.0/).
|
||||
|
||||
You may copy individual or multiple source files, granted that you keep the copyright license, and disclose the source back to this repository.
|
||||
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 5.2 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: 51 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: 5.3 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: 8.6 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 3.6 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: 66 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: 4.7 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
|
||||
|
|
|
|||
|
|
@ -1,19 +1,8 @@
|
|||
#!/bin/sh
|
||||
cd "$(dirname "$0")"
|
||||
directory=$(dirname $(readlink -f "$0"))
|
||||
|
||||
for file in 2x/*.png; do
|
||||
for file in "$directory"/1x/*.png; do
|
||||
filename=$(basename "$file")
|
||||
if [ ! -f "1x/${filename}" ]; then
|
||||
echo "Removing deleted file ${file} from 2x"
|
||||
rm "2x/${filename}"
|
||||
fi
|
||||
done
|
||||
|
||||
for file in 1x/*.png; do
|
||||
filename=$(basename "$file")
|
||||
output_file="2x/${filename}"
|
||||
if [ ! -f "$output_file" ] || [ "$file" -nt "$output_file" ]; then
|
||||
echo "Updating changed file ${file} in 2x/"
|
||||
output_file="$directory/2x/${filename}"
|
||||
magick "$file" -filter point -resize 200% "$output_file"
|
||||
fi
|
||||
done
|
||||
|
|
|
|||
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,71 +6,48 @@ return {
|
|||
text = {
|
||||
"{C:attention}Small{} and {C:attention}Big Blinds{} are",
|
||||
"replaced with {C:attention}Boss Blinds",
|
||||
"that are {C:dark_edition}debuffed thrice",
|
||||
"",
|
||||
"{C:Bakery_credit_fg_Roland_bakersdozenbagels,s:0.75}Art: BakersDozenBagels",
|
||||
"that are {C:dark_edition}debuffed #1# times",
|
||||
},
|
||||
},
|
||||
b_Roland_dropship = {
|
||||
name = "Dropship Deck",
|
||||
b_Roland_go = {
|
||||
name = "Pass GO Deck",
|
||||
text = {
|
||||
"{C:attention}Jokers {}are {C:money}free",
|
||||
"and {C:attention}Perishable",
|
||||
"",
|
||||
"{C:Bakery_credit_fg_Roland_bakersdozenbagels,s:0.75}Art: BakersDozenBagels",
|
||||
"Start with a {C:attention}Credit Card",
|
||||
"Set money to {C:money}$0",
|
||||
"when entering the shop",
|
||||
},
|
||||
unlock = {"Have exclusively", "{C:attention}Perishable Jokers"},
|
||||
},
|
||||
b_Roland_swapper = {
|
||||
name = "Swapper Deck",
|
||||
text = {
|
||||
"{C:tarot}Tarot {}and {C:spectral}Spectral",
|
||||
"cards swap places",
|
||||
"",
|
||||
"{C:Bakery_credit_fg_Roland_bakersdozenbagels,s:0.75}Art: BakersDozenBagels",
|
||||
},
|
||||
},
|
||||
b_Roland_wish = {
|
||||
name = "Wish Deck",
|
||||
text = {
|
||||
"Redeem a random {C:attention}Voucher",
|
||||
"after {C:attention}Small {}and {C:attention}Big Blinds",
|
||||
"{C:attention}Vouchers {}no longer",
|
||||
"appear in the shop",
|
||||
"",
|
||||
"{C:Bakery_credit_fg_Roland_bakersdozenbagels,s:0.75}Art: BakersDozenBagels",
|
||||
},
|
||||
unlock = {"Discover all {C:attention}Vouchers"},
|
||||
},
|
||||
},
|
||||
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",
|
||||
|
|
@ -79,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.",
|
||||
|
|
@ -140,12 +105,6 @@ return {
|
|||
},
|
||||
},
|
||||
},
|
||||
Edition = {
|
||||
e_Roland_frozen = {
|
||||
name = "Frozen",
|
||||
text = {"Values on", "this card do", "not change"},
|
||||
},
|
||||
},
|
||||
Enhanced = {
|
||||
m_wild = {
|
||||
name = "Wild Card",
|
||||
|
|
@ -153,70 +112,52 @@ return {
|
|||
},
|
||||
},
|
||||
Joker = {
|
||||
j_Roland_amber = {
|
||||
name = "Amber Acorn",
|
||||
text = {
|
||||
"{X:mult,C:white}X#1#{} Mult",
|
||||
"Moves before",
|
||||
"hand is played",
|
||||
},
|
||||
unlock = {"Defeat {C:attention}#1#"},
|
||||
},
|
||||
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 = {
|
||||
"Give the {C:attention}Blind",
|
||||
"{C:attention}Base {}as {X:red,C:white}XMult",
|
||||
"{C:inactive}(Currently {X:red,C:white}X#1#{C:inactive} Mult)",
|
||||
"Give {X:red,C:white}XMult{} equal to",
|
||||
"the current {C:attention}Blind Size{C:attention}",
|
||||
"{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",
|
||||
"Gains {C:money}$#1#{} of",
|
||||
"{C:attention}sell value{} if",
|
||||
"played hand is a",
|
||||
"{C:attention}#2#",
|
||||
},
|
||||
unlock = {"Defeat {C:blue}#1#"},
|
||||
},
|
||||
j_Roland_crimson = {
|
||||
name = "Crimson Heart",
|
||||
text = {
|
||||
"{X:mult,C:white}X#1#{} Mult",
|
||||
"{C:red}Debuffs {C:attention}Joker",
|
||||
"to the left",
|
||||
},
|
||||
unlock = {"Defeat {C:red}#1#"},
|
||||
},
|
||||
j_Roland_domino = {
|
||||
name = "Domino",
|
||||
|
|
@ -227,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 = {
|
||||
|
|
@ -285,22 +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 = {
|
||||
"Cards created by",
|
||||
"{C:attention}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 = {
|
||||
|
|
@ -315,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 = {
|
||||
|
|
@ -331,18 +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_polaris = {
|
||||
name = "Polaris",
|
||||
text = {
|
||||
"The {C:attention}first {}scored",
|
||||
"card each round",
|
||||
"becomes {C:dark_edition}Frozen",
|
||||
},
|
||||
},
|
||||
j_Roland_sapling = {
|
||||
name = "Sapling",
|
||||
text = {
|
||||
|
|
@ -352,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})",
|
||||
},
|
||||
},
|
||||
|
|
@ -381,48 +250,13 @@ 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",
|
||||
},
|
||||
unlock = {"Defeat {C:green}#1#"},
|
||||
},
|
||||
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",
|
||||
},
|
||||
unlock = {"Defeat {C:purple}#1#"},
|
||||
},
|
||||
j_Roland_venerable = {
|
||||
name = "Venerable Visage",
|
||||
text = {"{X:red,C:white}X#1#{} discards each round"},
|
||||
unlock = {"Defeat {C:dark_edition}#1#"},
|
||||
},
|
||||
j_Roland_yard = {
|
||||
name = "Yard Sale",
|
||||
text = {
|
||||
"Gain {C:money}$#1#{} when a",
|
||||
"card is {C:attention}added",
|
||||
"or {C:attention}removed",
|
||||
"card is {C:attention}removed",
|
||||
"from the deck",
|
||||
},
|
||||
unlock = {"Complete the", "{C:attention}#1#", "challenge"},
|
||||
},
|
||||
},
|
||||
Other = {
|
||||
|
|
@ -441,104 +275,70 @@ return {
|
|||
text = {
|
||||
"{C:attention}Small{} and {C:attention}Big Blinds{} are",
|
||||
"replaced with {C:attention}Boss Blinds",
|
||||
"that are {C:dark_edition}debuffed thrice",
|
||||
"",
|
||||
"{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 thrice)",
|
||||
"",
|
||||
"{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_dropship = {
|
||||
name = "Dropship Sleeve",
|
||||
sleeve_Roland_go = {
|
||||
name = "Pass GO Sleeve",
|
||||
text = {
|
||||
"{C:attention}Jokers {}are {C:money}free",
|
||||
"and {C:attention}Perishable",
|
||||
"",
|
||||
"{C:Bakery_credit_fg_Roland_bakersdozenbagels,s:0.75}Art: BakersDozenBagels",
|
||||
"Start with a {C:attention}Credit Card",
|
||||
"Set money to {C:money}$0",
|
||||
"when entering the shop",
|
||||
},
|
||||
unlock = {"Have exclusively", "{C:attention}Perishable Jokers"},
|
||||
},
|
||||
sleeve_Roland_dropship_alt = {
|
||||
name = "Business Sleeve",
|
||||
sleeve_Roland_go_alt = {
|
||||
name = "Free Parking Sleeve",
|
||||
text = {
|
||||
"{C:attention}Jokers {}are instead",
|
||||
"{C:dark_edition}Negative {}and {C:money}Rental",
|
||||
"",
|
||||
"{C:Bakery_credit_fg_Roland_bakersdozenbagels,s:0.75}Art: BakersDozenBagels",
|
||||
"Start with an additional",
|
||||
"{X:attention,C:white}#1#{C:attention} Credit Cards",
|
||||
},
|
||||
unlock = {"Have exclusively", "{C:attention}Perishable Jokers"},
|
||||
},
|
||||
sleeve_Roland_swapper = {
|
||||
name = "Swapper Sleeve",
|
||||
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",
|
||||
},
|
||||
},
|
||||
sleeve_Roland_wish = {
|
||||
name = "Wish Sleeve",
|
||||
text = {
|
||||
"A random {C:attention}voucher{} is",
|
||||
"{C:attention}redeemed {}at the end",
|
||||
"of {C:attention}Small {}and {C:attention}Big Blinds",
|
||||
"{C:attention}Vouchers {}no longer",
|
||||
"appear in the shop",
|
||||
"",
|
||||
"{C:Bakery_credit_fg_Roland_bakersdozenbagels,s:0.75}Art: BakersDozenBagels",
|
||||
},
|
||||
unlock = {"Discover all {C:attention}Vouchers"},
|
||||
},
|
||||
sleeve_Roland_wish_alt = {
|
||||
name = "Miracle Sleeve",
|
||||
text = {
|
||||
"All {C:attention}vouchers",
|
||||
"start {C:attention}redeemed",
|
||||
"",
|
||||
"{C:Bakery_credit_fg_Roland_bakersdozenbagels,s:0.75}Art: BakersDozenBagels",
|
||||
},
|
||||
unlock = {"Discover all {C:attention}Vouchers"},
|
||||
},
|
||||
},
|
||||
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 = {
|
||||
|
|
@ -550,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 = {
|
||||
|
|
@ -599,41 +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_Spring_Cleaning = "Spring Cleaning",
|
||||
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_frozen = "Frozen!",
|
||||
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 = {
|
||||
|
|
@ -642,17 +385,15 @@ 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)"},
|
||||
ch_c_Roland_Showdown_Verdant = {"Showdown blinds are {C:attention}Verdant Leaf {}(stacks with above)"},
|
||||
ch_c_Roland_Showdown_Violet = {"Showdown blinds are {C:attention}Violet Vessel {}(stacks with above)"},
|
||||
ch_c_Roland_Spring_Cleaning = {"Earn {C:red}no money {}from sources other than {C:attention}Yard Sale"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
|||
137
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]]
|
||||
|
|
@ -65,19 +65,6 @@ position = "at"
|
|||
payload = "elseif G.GAME.blind_on_deck == 'Big' then"
|
||||
match_indent = true
|
||||
|
||||
# Prevent Incantation from overriding Faster Planets
|
||||
[[patches]]
|
||||
[patches.pattern]
|
||||
target = '=[SMODS incantation "Incantation.lua"]'
|
||||
pattern = "function Card:use_consumeable(area, copier)"
|
||||
position = "after"
|
||||
payload = """if SMODS.Mods.Roland.config.faster_planets and
|
||||
self.ability.consumeable.hand_type then
|
||||
return useconsumeref(self, area, copier)
|
||||
end"""
|
||||
match_indent = true
|
||||
|
||||
# Misfortune Cookie
|
||||
[[patches]]
|
||||
[patches.pattern]
|
||||
target = "card.lua"
|
||||
|
|
@ -95,120 +82,6 @@ pattern = "local card = create_card('Tarot',G.consumeables, nil, nil, nil, nil,
|
|||
position = "after"
|
||||
times = 1
|
||||
payload = """if next(SMODS.find_card "j_Roland_misfortune") then
|
||||
card:set_edition("e_negative", true, true)
|
||||
card:set_edition "e_negative"
|
||||
end"""
|
||||
match_indent = true
|
||||
|
||||
[[patches]]
|
||||
[patches.pattern]
|
||||
target = "card.lua"
|
||||
pattern = "if self.seal == 'Blue' and #G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit and not self.ability.extra_enhancement then"
|
||||
position = "at"
|
||||
payload = """if self.seal == 'Blue' and
|
||||
(next(SMODS.find_card "j_Roland_misfortune") or
|
||||
#G.consumeables.cards + G.GAME.consumeable_buffer < G.consumeables.config.card_limit and
|
||||
not self.ability.extra_enhancement) then
|
||||
"""
|
||||
match_indent = true
|
||||
|
||||
[[patches]]
|
||||
[patches.pattern]
|
||||
target = "card.lua"
|
||||
pattern = "local card = create_card(card_type,G.consumeables, nil, nil, nil, nil, _planet, 'blusl')"
|
||||
position = "after"
|
||||
payload = """if next(SMODS.find_card "j_Roland_misfortune") then
|
||||
card:set_edition("e_negative", true, true)
|
||||
end"""
|
||||
match_indent = true
|
||||
|
||||
# Frozen
|
||||
[[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 = "SMODS.Mods.Roland.bootstraps_mult(self)"
|
||||
|
||||
[[patches]]
|
||||
[patches.regex]
|
||||
target = "card.lua"
|
||||
pattern = "if self\\.ability\\.h_size ~= 0 then"
|
||||
position = "at"
|
||||
payload = "if self.ability.h_size and self.ability.h_size ~= 0 then"
|
||||
|
||||
[[patches]]
|
||||
[patches.regex]
|
||||
target = "card.lua"
|
||||
pattern = "if self\\.ability\\.d_size > 0 then"
|
||||
position = "at"
|
||||
payload = "if self.ability.d_size and self.ability.d_size > 0 then"
|
||||
|
||||
[[patches]]
|
||||
[patches.pattern]
|
||||
target = '=[SMODS _ "src/utils.lua"]'
|
||||
pattern = "value = value + card.ability[property]"
|
||||
position = "at"
|
||||
payload = "value = value + (card.ability[property] or 0)"
|
||||
match_indent = true
|
||||
|
||||
# [[patches]]
|
||||
# [patches.pattern]
|
||||
# target = '=[SMODS DebugPlus "debugplus/console.lua"]'
|
||||
# pattern = "if toCheck == '/' or toCheck == 'kp/' then"
|
||||
# position = "at"
|
||||
# payload = "if toCheck == '/' or toCheck == 'kp/' or toCheck == 'f' then"
|
||||
# match_indent = true
|
||||
|
||||
# [[patches]]
|
||||
# [patches.pattern]
|
||||
# target = '=[SMODS DebugPlus "debugplus/console.lua"]'
|
||||
# pattern = 'local cmdName = string.lower(string.gsub(inputText, "^(%S+).*", "%1"))'
|
||||
# position = "at"
|
||||
# payload = 'local cmdName = "eval"'
|
||||
# match_indent = true
|
||||
|
||||
# [[patches]]
|
||||
# [patches.pattern]
|
||||
# target = '=[SMODS DebugPlus "debugplus/console.lua"]'
|
||||
# pattern = 'local rawArgs = string.gsub(inputText, "^%S+%s*(.*)", "%1")'
|
||||
# position = "at"
|
||||
# payload = 'local cmdName = inputText'
|
||||
# match_indent = true
|
||||
|
|
|
|||
|
|
@ -3,20 +3,20 @@
|
|||
"id": "Roland",
|
||||
"name": "Roland",
|
||||
"prefix": "Roland",
|
||||
"version": "3.0.2",
|
||||
"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/
|
||||
1
refs/src
|
|
@ -1 +0,0 @@
|
|||
../../smods/src
|
||||
288
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,31 +8,45 @@ end
|
|||
local back = (function()
|
||||
local x = 0
|
||||
|
||||
---@param tbl SMODS.Back|{attributes?: Attributes[], pronouns: string, 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",
|
||||
pronouns = tbl.pronouns,
|
||||
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 {}
|
||||
|
|
@ -40,7 +54,7 @@ local back = (function()
|
|||
return ret
|
||||
end,
|
||||
apply = function(self, ...)
|
||||
return save((tbl.alt_apply and self:is_alt() and tbl.alt_apply or apply)(self, ...))
|
||||
return (tbl.alt_apply and self:is_alt() and tbl.alt_apply or apply)(self, ...)
|
||||
end,
|
||||
calculate = function(self, ...)
|
||||
return (tbl.alt_calculate and self:is_alt() and tbl.alt_calculate or calculate)(self, ...)
|
||||
|
|
@ -49,176 +63,116 @@ local back = (function()
|
|||
return self.get_current_deck_key() == "b_Roland_" .. key
|
||||
end,
|
||||
}
|
||||
|
||||
return back
|
||||
end
|
||||
end)()
|
||||
|
||||
local back_atlas = SMODS.Atlas {
|
||||
SMODS.Atlas {
|
||||
key = "back",
|
||||
path = "back.png",
|
||||
px = 71,
|
||||
py = 95,
|
||||
}
|
||||
|
||||
local extra_atlas = SMODS.Atlas {
|
||||
key = "back_extra",
|
||||
path = "backExtra.png",
|
||||
px = 71,
|
||||
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 = 9, times = 3}},
|
||||
attributes = {"passive", "boss_blind"},
|
||||
loc_vars = function(self)
|
||||
return {vars = {self.config.extra.alt_times}}
|
||||
config = {extra = {times = 2}},
|
||||
loc_vars = function(self, _, _)
|
||||
return {vars = {self.config.extra.times}}
|
||||
end,
|
||||
apply = function()
|
||||
apply = function(_, _)
|
||||
G.GAME.modifiers.Roland_blossom_deck = true
|
||||
end,
|
||||
calculate = function(self, b, context)
|
||||
if not context.forcetrigger and not context.setting_blind then
|
||||
calculate = function(self, card, context)
|
||||
if not context.setting_blind then
|
||||
return
|
||||
end
|
||||
|
||||
local blinds = G.GAME.round_resets.blind_states
|
||||
|
||||
if not context.forcetrigger and
|
||||
blinds.Small ~= "Current" and
|
||||
blinds.Big ~= "Current" then
|
||||
if blinds.Small ~= "Current" and blinds.Big ~= "Current" then
|
||||
return
|
||||
end
|
||||
|
||||
local function debuff(times)
|
||||
return function()
|
||||
if times <= 0 then
|
||||
return
|
||||
end
|
||||
local count = self:is_alt() and G.GAME.round_resets.ante or self.config.extra.times
|
||||
|
||||
for _ = 1, count do
|
||||
G.GAME.blind:disable()
|
||||
SMODS.calculate_effect({message = localize "ph_boss_disabled"}, b)
|
||||
|
||||
q {
|
||||
delay = 0.4,
|
||||
func = function()
|
||||
SMODS.calculate_effect({message = localize "ph_boss_disabled"}, card)
|
||||
G.GAME.blind:wiggle()
|
||||
play_sound "timpani"
|
||||
q {func = debuff(times - 1)}
|
||||
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
|
||||
|
||||
local times = self:is_alt() and
|
||||
G.GAME.round_resets.ante * self.config.extra.alt_times or
|
||||
self.config.extra.times
|
||||
ease_dollars(-G.GAME.dollars)
|
||||
|
||||
debuff(times)()
|
||||
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 = {"passive", "editions", "sell_value"},
|
||||
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,
|
||||
}
|
||||
|
||||
local b_dropship = back {
|
||||
key = "dropship",
|
||||
pronouns = "he_him",
|
||||
attributes = {"passive", "generation"},
|
||||
unlocked = false,
|
||||
discovered = false,
|
||||
check_for_unlock = function(_, args)
|
||||
return args ~= "Bakery_nothing" and
|
||||
G.jokers and
|
||||
next((G.jokers or {}).cards) and
|
||||
not not f(G.jokers.cards):map "ability":all "perishable"
|
||||
end,
|
||||
apply = function(self)
|
||||
G.GAME.modifiers.Roland_dropship = not self:is_alt()
|
||||
G.GAME.modifiers.Roland_dropship_alt = self:is_alt()
|
||||
end,
|
||||
calculate = f.noop,
|
||||
}
|
||||
|
||||
local dropship_tape
|
||||
|
||||
q {
|
||||
blocking = false,
|
||||
no_delete = true,
|
||||
func = function()
|
||||
dropship_tape = SMODS.create_sprite(0, 0, G.CARD_W, G.CARD_H, extra_atlas, {x = 0, y = 0})
|
||||
end,
|
||||
}
|
||||
|
||||
SMODS.DrawStep {
|
||||
key = "dropship_tape",
|
||||
order = 5,
|
||||
conditions = {vortex = false, facing = "back"},
|
||||
func = function(self)
|
||||
if self.children.back.atlas ~= back_atlas or self.children.back.sprite_pos.x ~= b_dropship.pos.x then
|
||||
return
|
||||
end
|
||||
|
||||
dropship_tape.role.draw_major = self
|
||||
local deck = self.area.config.type == "deck"
|
||||
local sticker_offset = self.sticker_offset or {}
|
||||
|
||||
-- Don't draw dissolve since it's baked into the sprite already. Also, I had to boost its alpha for the
|
||||
-- shine to look correct, so drawing this would look *awful*.
|
||||
-- dropship_tape:draw_shader("dissolve", nil, nil, deck, self.children.center, self.sticker_rotation, sticker_offset.x, sticker_offset.y)
|
||||
dropship_tape:draw_shader(
|
||||
"voucher",
|
||||
nil,
|
||||
self.ARGS.send_to_shader,
|
||||
deck,
|
||||
self.children.center,
|
||||
self.sticker_rotation,
|
||||
sticker_offset.x,
|
||||
sticker_offset.y
|
||||
)
|
||||
end,
|
||||
calculate = function() end,
|
||||
}
|
||||
|
||||
local swapper = {Spectral = "Tarot", Tarot = "Spectral"}
|
||||
local orig_create_card = create_card
|
||||
|
||||
local function create_dropshipped_card(_type, ...)
|
||||
local ret = orig_create_card(_type, ...)
|
||||
local ok = _type == "Joker" and ret.ability
|
||||
|
||||
if ok and G.GAME.modifiers.Roland_dropship_alt then
|
||||
ret.ability.rental = true
|
||||
local _ = ret:set_edition({negative = true}, true, true)
|
||||
end
|
||||
|
||||
if ok and G.GAME.modifiers.Roland_dropship then
|
||||
ret.ability.perish_tally = 5
|
||||
ret.ability.perishable = true
|
||||
ret.cost, ret.sell_cost = 0, 0
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
---@diagnostic disable-next-line: lowercase-global
|
||||
function create_card(_type, ...)
|
||||
if not G.GAME.modifiers.Roland_swapper_deck then
|
||||
return create_dropshipped_card(_type, ...)
|
||||
return orig_create_card(_type, ...)
|
||||
end
|
||||
|
||||
if not G.GAME.modifiers.Roland_alt_swapper_deck then
|
||||
return create_dropshipped_card(swapper[_type] or _type, ...)
|
||||
return orig_create_card(swapper[_type] or _type, ...)
|
||||
end
|
||||
|
||||
local type = f(SMODS.ConsumableTypes):keys():where(function(v)
|
||||
|
|
@ -226,79 +180,5 @@ function create_card(_type, ...)
|
|||
end):table()
|
||||
|
||||
local has_type = SMODS.ConsumableTypes[_type]
|
||||
return create_dropshipped_card(
|
||||
has_type and pseudorandom_element(type, pseudoseed "Roland_alt_swapper_deck") or _type, ...)
|
||||
end
|
||||
|
||||
local function redeem(key, fast)
|
||||
if fast then
|
||||
G.GAME.used_vouchers[key] = true
|
||||
end
|
||||
|
||||
q {
|
||||
delay = 1,
|
||||
func = function()
|
||||
local voucher = SMODS.create_card {key = key, set = "Voucher"}
|
||||
voucher.cost = 0
|
||||
voucher.T.x = (fast and pseudorandom(pseudoseed "Roland_wish_deck") + 0.5 or 1) * 9
|
||||
voucher.T.y = (fast and pseudorandom(pseudoseed "Roland_wish_deck") + 0.5 or 1) * 4.25
|
||||
voucher:start_materialize()
|
||||
|
||||
q {
|
||||
delay = 1,
|
||||
func = function()
|
||||
if fast then
|
||||
play_sound "card1"
|
||||
voucher:apply_to_run()
|
||||
voucher:juice_up(0.3, 0.5)
|
||||
else
|
||||
local state = G.STATE
|
||||
voucher:redeem()
|
||||
G.STATE = state
|
||||
end
|
||||
|
||||
q {
|
||||
delay = 1,
|
||||
func = function()
|
||||
voucher:start_dissolve()
|
||||
end,
|
||||
}
|
||||
end,
|
||||
}
|
||||
end,
|
||||
}
|
||||
end
|
||||
|
||||
back {
|
||||
key = "wish",
|
||||
pronouns = "he_him",
|
||||
attributes = {"passive", "generation"},
|
||||
unlocked = false,
|
||||
discovered = false,
|
||||
check_for_unlock = function(_, args)
|
||||
return args ~= "Bakery_nothing" and f(G.P_CENTER_POOLS.Voucher):all "discovered"
|
||||
end,
|
||||
apply = function(self)
|
||||
G.GAME.modifiers.Roland_no_voucher = true
|
||||
local _ = self:is_alt() and f(G.P_CENTER_POOLS.Voucher):map "key":each(redeem)
|
||||
end,
|
||||
calculate = function(_, _, context)
|
||||
local _ = (context.forcetrigger or
|
||||
context.blind_defeated and
|
||||
not context.repetition and
|
||||
not G.GAME.blind.boss) and
|
||||
f(G.P_CENTER_POOLS.Voucher)
|
||||
:map "key"
|
||||
:where(f.index_into(G.GAME.used_vouchers), false)
|
||||
:any() and
|
||||
redeem(get_next_voucher_key())
|
||||
end,
|
||||
}
|
||||
|
||||
local orig_add_voucher_to_shop = SMODS.add_voucher_to_shop
|
||||
|
||||
function SMODS.add_voucher_to_shop(...)
|
||||
if not G.GAME.modifiers.Roland_no_voucher then
|
||||
return orig_add_voucher_to_shop(...)
|
||||
end
|
||||
return orig_create_card(has_type and pseudorandom_element(type, pseudoseed "Roland_alt_swapper_deck") or _type, ...)
|
||||
end
|
||||
|
|
|
|||
318
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,17 +148,32 @@ 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 not not f(G.playing_cards):any(has_enhancement)
|
||||
return G.playing_cards and f(G.playing_cards):any(has_enhancement)
|
||||
end,
|
||||
}
|
||||
|
||||
|
|
@ -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,48 +232,18 @@ 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},
|
||||
boss_colour = HEX "bdaeccff",
|
||||
pronouns = "they_them",
|
||||
collection_loc_vars = function()
|
||||
collection_loc_vars = function(_)
|
||||
return {
|
||||
vars = {localize {
|
||||
type = "variable",
|
||||
|
|
@ -265,10 +251,13 @@ blind {
|
|||
}},
|
||||
}
|
||||
end,
|
||||
loc_vars = function()
|
||||
loc_vars = function(_)
|
||||
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,14 +298,14 @@ blind {
|
|||
|
||||
blind {
|
||||
key = "improbable",
|
||||
boss = {min = 3},
|
||||
boss = {min = 4},
|
||||
boss_colour = HEX "009966ff",
|
||||
pronouns = "it_its",
|
||||
mult = 2,
|
||||
dollars = 5,
|
||||
defeat = disable_improbable,
|
||||
disable = disable_improbable,
|
||||
set_blind = function()
|
||||
set_blind = function(_)
|
||||
G.GAME.modifiers.Roland_improbable = true
|
||||
end,
|
||||
}
|
||||
|
|
@ -327,70 +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
|
||||
|
||||
local function call(key, value)
|
||||
local obj = G[key .. "obj"]
|
||||
local _ = type(obj) == "function" and obj(value)
|
||||
|
||||
if not G[key] or value == "Bakery_nothing" then
|
||||
return
|
||||
end
|
||||
|
||||
if type(G[key]) == "function" then
|
||||
G[key] = {G[key]}
|
||||
end
|
||||
|
||||
if type(G[key]) ~= "table" then
|
||||
return
|
||||
end
|
||||
|
||||
local str
|
||||
|
||||
local _ = f(type(value) == "table" and value or {[value] = true})
|
||||
:keys()
|
||||
:map(f.index_into(G[key]))
|
||||
:where(type, "function")
|
||||
:each(function(v)
|
||||
str = str or type(value) == "table" and f(value):keys():string() or value
|
||||
v(str)
|
||||
end)
|
||||
|
||||
local _ = not str and
|
||||
type(G[key][1]) == "function" and
|
||||
G[key][1](type(value) == "table" and f(value):keys():string() or value)
|
||||
end
|
||||
|
||||
local orig_check_for_unlock = check_for_unlock
|
||||
|
||||
function check_for_unlock(args, ...)
|
||||
call("lock", type(args) == "table" and args.type or args)
|
||||
return orig_check_for_unlock(args, ...)
|
||||
end
|
||||
|
||||
function SMODS.current_mod:calculate(context)
|
||||
call("calc", context)
|
||||
|
||||
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, false, v.config.extra.amount)
|
||||
end)
|
||||
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
|
||||
|
||||
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
|
||||
|
|
@ -404,7 +341,7 @@ function SMODS.current_mod:calculate(context)
|
|||
|
||||
local normal = orig.normal
|
||||
|
||||
G.GAME.probabilities = setmetatable({}, {
|
||||
local mt = {
|
||||
orig = orig,
|
||||
__index = function(_, k)
|
||||
return k == "normal" and 0 or orig[k]
|
||||
|
|
@ -412,7 +349,11 @@ function SMODS.current_mod:calculate(context)
|
|||
__newindex = function(_, k, v)
|
||||
orig[k] = (k == "normal" and v == 0) and normal or v
|
||||
end,
|
||||
})
|
||||
}
|
||||
|
||||
local proxy = {}
|
||||
setmetatable(proxy, mt)
|
||||
G.GAME.probabilities = proxy
|
||||
end
|
||||
|
||||
blind {
|
||||
|
|
@ -441,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
|
||||
|
|
@ -454,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
|
||||
|
|
@ -469,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
|
||||
|
|
@ -482,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
|
||||
|
||||
|
|
@ -501,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"),
|
||||
|
|
@ -535,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,26 +1,19 @@
|
|||
local f, q = (... or require "lib.shared")[1], (... or require "lib.shared")[2]
|
||||
local f, q = unpack(... or require "lib.shared")
|
||||
|
||||
---@return {banned_cards: {}, banned_tags: {}, banned_other: {}}
|
||||
local function bans()
|
||||
return {banned_cards = {}, banned_tags = {}, banned_other = {}}
|
||||
end
|
||||
|
||||
---@param tbl table
|
||||
---@return fun(v: SMODS.GameObject)
|
||||
local function adder(tbl)
|
||||
return function(v)
|
||||
table.insert(tbl, {id = v.key, type = "blind"})
|
||||
end
|
||||
end
|
||||
|
||||
---@param v SMODS.GameObject
|
||||
---@return boolean
|
||||
local function is_banned_from_pastry(v)
|
||||
return not ({Bakery = true, Roland = true})[(v.mod or {}).id]
|
||||
end
|
||||
|
||||
---@param v SMODS.Center
|
||||
---@return boolean
|
||||
local function is_center_banned_from_pastry(v)
|
||||
local arcana_boosters = {
|
||||
p_arcana_normal_1 = true,
|
||||
|
|
@ -37,109 +30,40 @@ 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
|
||||
|
||||
---@param v SMODS.GameObject
|
||||
---@return boolean|string
|
||||
local function is_economy(v)
|
||||
return f(Bakery_API.econ_only_items):where(f.eq(v.key)):any()
|
||||
local function is_joker(v)
|
||||
return v.set == "Joker" and not ({j_joker = true, j_Roland_msjoker = true})[v.key]
|
||||
end
|
||||
|
||||
---@param key string
|
||||
---@return fun(v: SMODS.Blind, k: string): boolean?
|
||||
local function is_showdown_except(key)
|
||||
---@param v SMODS.Blind
|
||||
---@param k string
|
||||
---@return boolean?
|
||||
return function(v, k)
|
||||
return v.boss and v.boss.showdown and key ~= k
|
||||
end
|
||||
end
|
||||
|
||||
---@param name string
|
||||
---@param amount number
|
||||
---@return {id: string}[]
|
||||
local function multirule(name, amount)
|
||||
return f(amount):map(function(v)
|
||||
return {id = "Roland_" .. name .. v}
|
||||
end):table()
|
||||
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
|
||||
|
||||
local pastries, amber, cerulean, crimson, verdant, violet, yard =
|
||||
bans(), bans(), bans(), bans(), bans(), bans(), bans()
|
||||
local jokerful, vanillas, pastries, amber, cerulean, crimson, verdant, violet, final
|
||||
= bans(), bans(), bans(), bans(), bans(), bans(), bans(), bans(), bans()
|
||||
|
||||
SMODS.Challenge {
|
||||
key = "Glass",
|
||||
rules = {custom = multirule("Glass", 2)},
|
||||
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"
|
||||
end)
|
||||
end,
|
||||
}
|
||||
|
||||
SMODS.Challenge {
|
||||
key = "Spring_Cleaning",
|
||||
config = {no_interest = true},
|
||||
consumeables = {{id = "c_hanged_man"}},
|
||||
jokers = {{id = "j_Roland_yard"}, {id = "j_Roland_yard"}},
|
||||
vouchers = {{id = "v_magic_trick"}, {id = "v_overstock_norm"}},
|
||||
rules = {custom = {{id = "Roland_Spring_Cleaning"}}},
|
||||
restrictions = yard,
|
||||
apply = function()
|
||||
G.GAME.modifiers.no_blind_reward = {Small = true, Big = true, Boss = true}
|
||||
G.GAME.modifiers.no_extra_hand_money = true
|
||||
|
||||
f(Bakery_API.econ_only_items):keys():where(f.nq "j_Roland_yard"):each(function(v)
|
||||
G.GAME.banned_keys[v] = true
|
||||
end)
|
||||
end,
|
||||
}
|
||||
|
||||
SMODS.Challenge {
|
||||
key = "Go",
|
||||
rules = {custom = {{id = "Roland_Go"}}},
|
||||
jokers = {{id = "j_credit_card"}},
|
||||
key = "Jokerful",
|
||||
rules = {custom = {{id = "Roland_Jokerful"}}},
|
||||
restrictions = jokerful,
|
||||
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,
|
||||
SMODS.Challenge {
|
||||
key = "Ornate",
|
||||
rules = {custom = {{id = "Roland_Ornate"}}},
|
||||
restrictions = vanillas,
|
||||
pronouns = "any_all",
|
||||
}
|
||||
|
||||
SMODS.Challenge {
|
||||
|
|
@ -149,15 +73,12 @@ SMODS.Challenge {
|
|||
pronouns = "she_them",
|
||||
}
|
||||
|
||||
SMODS.Challenge {
|
||||
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",
|
||||
unlocked = function()
|
||||
return G.P_CENTERS.j_Roland_amber and G.P_CENTERS.j_Roland_amber.check_for_unlock()
|
||||
end,
|
||||
calculate = function(_, context)
|
||||
local function slide(pitch)
|
||||
q(function()
|
||||
|
|
@ -189,17 +110,11 @@ SMODS.Challenge {
|
|||
end,
|
||||
}
|
||||
end,
|
||||
}
|
||||
|
||||
SMODS.Challenge {
|
||||
},
|
||||
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",
|
||||
unlocked = function()
|
||||
return G.P_CENTERS.j_Roland_cerulean and G.P_CENTERS.j_Roland_cerulean.check_for_unlock()
|
||||
end,
|
||||
calculate = function(_, context)
|
||||
if not context.hand_drawn then
|
||||
return
|
||||
|
|
@ -219,25 +134,20 @@ SMODS.Challenge {
|
|||
G.hand:add_to_highlighted(v)
|
||||
end)
|
||||
end,
|
||||
}
|
||||
|
||||
SMODS.Challenge {
|
||||
},
|
||||
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",
|
||||
unlocked = function()
|
||||
return G.P_CENTERS.j_Roland_crimson and G.P_CENTERS.j_Roland_crimson.check_for_unlock()
|
||||
end,
|
||||
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
|
||||
|
|
@ -265,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()
|
||||
|
|
@ -282,17 +194,11 @@ SMODS.Challenge {
|
|||
mod.Roland_Eternally_Crimson = not context.hand_drawn and
|
||||
mod.Roland_Eternally_Crimson or nil
|
||||
end,
|
||||
}
|
||||
|
||||
SMODS.Challenge {
|
||||
},
|
||||
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",
|
||||
unlocked = function()
|
||||
return G.P_CENTERS.j_Roland_verdant and G.P_CENTERS.j_Roland_verdant.check_for_unlock()
|
||||
end,
|
||||
calculate = function(_, context)
|
||||
if context.setting_blind then
|
||||
G.GAME.modifiers.Roland_Eternally_Verdant = true
|
||||
|
|
@ -308,55 +214,44 @@ SMODS.Challenge {
|
|||
end)
|
||||
end
|
||||
end,
|
||||
},
|
||||
SMODS.Challenge {
|
||||
key = "Eternally_Violet",
|
||||
rules = {custom = {{id = "Roland_Eternally_Violet"}, {id = "Roland_Showdown_Violet"}}},
|
||||
restrictions = violet,
|
||||
calculate = function(_, context)
|
||||
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 = "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",
|
||||
unlocked = function()
|
||||
return G.P_CENTERS.j_Roland_violet and G.P_CENTERS.j_Roland_violet.check_for_unlock()
|
||||
end,
|
||||
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)
|
||||
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
|
||||
G.GAME.blind.chip_text = number_format(G.GAME.blind.chips)
|
||||
f(finalizers):each(function(v)
|
||||
v:calculate(context)
|
||||
end)
|
||||
end,
|
||||
}
|
||||
|
||||
q {
|
||||
blocking = false,
|
||||
no_delete = true,
|
||||
func = function()
|
||||
if not Bakery_API or not Bakery_API.no_money_decks then
|
||||
return false
|
||||
end
|
||||
|
||||
table.insert(Bakery_API.econ_only_items, "j_Roland_yard")
|
||||
table.insert(Bakery_API.econ_only_items, "j_Roland_artemis")
|
||||
local orig = Bakery_API.no_money_decks
|
||||
|
||||
Bakery_API.no_money_decks = setmetatable({}, {
|
||||
orig = orig,
|
||||
__index = function(_, k)
|
||||
return (G.GAME or {}).challenge == "c_Roland_Spring_Cleaning" or orig[k]
|
||||
end,
|
||||
})
|
||||
|
||||
f(spin_to_win.jokers):each(function(v)
|
||||
v.id = G.P_CENTERS.j_Bakery_Spinner and "j_Bakery_Spinner" or v.id
|
||||
end)
|
||||
|
||||
q(function()
|
||||
f {
|
||||
{G.P_TAGS, is_economy, yard.banned_tags},
|
||||
{G.P_BLINDS, is_economy, yard.banned_other},
|
||||
{G.P_CENTERS, is_economy, yard.banned_cards},
|
||||
{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},
|
||||
|
|
@ -365,8 +260,8 @@ q {
|
|||
{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,
|
||||
}
|
||||
end)
|
||||
|
|
|
|||
313
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"
|
||||
end
|
||||
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,
|
||||
}
|
||||
if type(value) == "number" then
|
||||
ability[key] = value + n
|
||||
return
|
||||
end
|
||||
|
||||
local orig_can_discard = G.FUNCS.can_discard
|
||||
if type(value) ~= "table" then
|
||||
return
|
||||
end
|
||||
|
||||
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, ...)
|
||||
local new_value = f(value):map(new):table()
|
||||
|
||||
f(new_value):each(function(v, k)
|
||||
ability[k] = v
|
||||
end)
|
||||
|
||||
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
|
||||
|
||||
G.FUNCS.Roland_cocacola = function()
|
||||
stop_use()
|
||||
G.CONTROLLER.interrupt.focus = true
|
||||
G.CONTROLLER:save_cardarea_focus "hand"
|
||||
|
||||
f(G.playing_cards):map "ability":each(function(v)
|
||||
v.forced_selection = nil
|
||||
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
|
||||
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,70 +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()
|
||||
f((G.GAME.modifiers.extra_boosters or 0) + 2)
|
||||
:map(f.const(nil))
|
||||
:each(SMODS.add_booster_to_shop)
|
||||
|
||||
q(function()
|
||||
card.ability.extra.active = false
|
||||
end)
|
||||
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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +0,0 @@
|
|||
-- Special shoutout to all contributors. <3
|
||||
return {
|
||||
aster = {
|
||||
name = "asterSSH",
|
||||
fg = HEX "f8f8f2ff",
|
||||
bg = HEX "bd93f9ff",
|
||||
},
|
||||
bakersdozenbagels = {
|
||||
name = "BakersDozenBagels",
|
||||
fg = HEX "362708ff",
|
||||
bg = HEX "edd198ff",
|
||||
},
|
||||
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",
|
||||
},
|
||||
}
|
||||
377
src/edition.lua
|
|
@ -1,377 +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
|
||||
|
||||
local config = card.config or {}
|
||||
|
||||
(card.ability or {}).Roland_crimson = not not (card.ability or {}).Roland_crimson
|
||||
card.Roland_frozen_base = card.Roland_frozen_base or copy(card.base)
|
||||
card.Roland_frozen_card = card.Roland_frozen_card or copy(config.card)
|
||||
card.Roland_frozen_ability = card.Roland_frozen_ability or copy(card.ability)
|
||||
card.base = card.Roland_frozen_base and copy(card.Roland_frozen_base) or card.base
|
||||
|
||||
local diff = type(card.set_sprites) == "function" and
|
||||
f(card.Roland_frozen_card):diff(config.card, f.chain(type, f.nq "table"))
|
||||
|
||||
config.card = card.Roland_frozen_card and copy(card.Roland_frozen_card) or config.card
|
||||
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)}
|
||||
|
||||
if diff then
|
||||
card:set_sprites(card.config.center, card.config.card)
|
||||
end
|
||||
|
||||
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_base,
|
||||
card.Roland_frozen_card,
|
||||
card.Roland_frozen_ability,
|
||||
card.Roland_frozen_current_round = nil, nil, nil, nil, nil
|
||||
end,
|
||||
get_weight = function(self)
|
||||
return self.weight * G.GAME.edition_rate
|
||||
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_save = Card.save
|
||||
|
||||
function Card:save(...)
|
||||
if false then
|
||||
---@type Card|{Roland_frozen: table, Roland_frozen_ability: table, Roland_frozen_base: table, Roland_frozen_card: table, Roland_frozen_current_round: table}
|
||||
self = self
|
||||
end
|
||||
|
||||
local ret = orig_save(self, ...)
|
||||
|
||||
ret.Roland_frozen,
|
||||
ret.Roland_frozen_base,
|
||||
ret.Roland_frozen_card,
|
||||
ret.Roland_frozen_ability,
|
||||
ret.Roland_frozen_current_round =
|
||||
self.Roland_frozen,
|
||||
self.Roland_frozen_base,
|
||||
self.Roland_frozen_card,
|
||||
self.Roland_frozen_ability,
|
||||
self.Roland_frozen_current_round
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
local is_bean = {["Turtle Bean"] = true, j_mp_turtle_bean = true}
|
||||
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 is_bean[self.ability.name] 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
|
||||
|
||||
function SMODS.current_mod.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
|
||||
|
||||
local orig_get_probability_vars = SMODS.get_probability_vars
|
||||
|
||||
function SMODS.get_probability_vars(trigger_obj, ...)
|
||||
local numerator, denominator = orig_get_probability_vars(trigger_obj, ...)
|
||||
local override = ((trigger_obj or {}).Roland_frozen or {}).probability
|
||||
|
||||
if override then
|
||||
return type(denominator) == "table" and to_big(override) or override, denominator
|
||||
else
|
||||
return numerator, denominator
|
||||
end
|
||||
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,
|
||||
}
|
||||
1427
src/joker.lua
|
|
@ -3,227 +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 T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, R
|
||||
---@param self F
|
||||
---@param first? T1
|
||||
---@param second? T2
|
||||
---@param third? T3
|
||||
---@param fourth? T4
|
||||
---@param fifth? T5
|
||||
---@param sixth? T6
|
||||
---@param seventh? T7
|
||||
---@param eighth? T8
|
||||
---@param ninth? T9
|
||||
---@param tenth? T10
|
||||
---@return fun(v: fun(first: T1, second: T2, third: T3, fourth: T4, fifth: T5, sixth: T6, seventh: T7, eighth: T8, ninth: T9, tenth: T10): R): R
|
||||
---@nodiscard
|
||||
function f:call(first, second, third, fourth, fifth, sixth, seventh, eighth, ninth, tenth)
|
||||
error {first, second, third, fourth, fifth, sixth, seventh, eighth, ninth, tenth}
|
||||
end
|
||||
|
||||
---@generic T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, R
|
||||
---@param self string
|
||||
---@param first? T1
|
||||
---@param second? T2
|
||||
---@param third? T3
|
||||
---@param fourth? T4
|
||||
---@param fifth? T5
|
||||
---@param sixth? T6
|
||||
---@param seventh? T7
|
||||
---@param eighth? T8
|
||||
---@param ninth? T9
|
||||
---@param tenth? T10
|
||||
---@return fun(v: {[string]: fun(self: self, first: T1, second: T2, third: T3, fourth: T4, fifth: T5, sixth: T6, seventh: T7, eighth: T8, ninth: T9, tenth: T10): R}): R
|
||||
---@nodiscard
|
||||
function f.call(self, first, second, third, fourth, fifth, sixth, seventh, eighth, ninth, tenth)
|
||||
error {self, first, second, third, fourth, fifth, sixth, seventh, eighth, ninth, tenth}
|
||||
end
|
||||
|
||||
---@generic I, O
|
||||
---@param first integer|string|fun(v: I): O
|
||||
---@return fun(v: I): O
|
||||
---@nodiscard
|
||||
function f.chain(first)
|
||||
error {first}
|
||||
end
|
||||
|
||||
---@generic I, T, O
|
||||
---@param first integer|string|fun(v: I): T
|
||||
---@param second integer|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 integer|string|fun(v: I): T1
|
||||
---@param second integer|string|fun(v: T1): T2
|
||||
---@param third integer|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 integer|string|fun(v: I): T1
|
||||
---@param second integer|string|fun(v: T1): T2
|
||||
---@param third integer|string|fun(v: T2): T3
|
||||
---@param fourth integer|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 integer|string|fun(v: I): T1
|
||||
---@param second integer|string|fun(v: T1): T2
|
||||
---@param third integer|string|fun(v: T2): T3
|
||||
---@param fourth integer|string|fun(v: T3): T4
|
||||
---@param fifth integer|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]: (integer|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]: (integer|string|fun(v: I): T), [2]: (integer|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]: (integer|string|fun(v: I): T1), [2]: (integer|string|fun(v: T1): T2), [3]: (integer|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]: (integer|string|fun(v: I): T1), [2]: (integer|string|fun(v: T1): T2), [3]: (integer|string|fun(v: T2): T3), [4]: (integer|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]: (integer|string|fun(v: I): T1), [2]: (integer|string|fun(v: T1): T2), [3]: (integer|string|fun(v: T2): T3), [4]: (integer|string|fun(v: T3): T4), [4]: (integer|string|fun(v: T4): O) }
|
||||
---@return fun(v: I): O
|
||||
---@nodiscard
|
||||
function f.chain(all)
|
||||
error(all)
|
||||
end
|
||||
|
||||
---@generic I, O
|
||||
---@param first integer|string|fun(v: I): O
|
||||
---@return fun(v: I): O
|
||||
---@nodiscard
|
||||
function f.compose(first)
|
||||
error {first}
|
||||
end
|
||||
|
||||
---@generic I, T, O
|
||||
---@param first integer|string|fun(v: T): O
|
||||
---@param second integer|string|fun(v: I): T
|
||||
---@return fun(v: I): O
|
||||
---@nodiscard
|
||||
function f.compose(first, second)
|
||||
error {first, second}
|
||||
end
|
||||
|
||||
---@generic I, T1, T2, O
|
||||
---@param first integer|string|fun(v: T2): O
|
||||
---@param second integer|string|fun(v: T1): T2
|
||||
---@param third integer|string|fun(v: I): T1
|
||||
---@return fun(v: I): O
|
||||
---@nodiscard
|
||||
function f.compose(first, second, third)
|
||||
error {first, second, third}
|
||||
end
|
||||
|
||||
---@generic I, T1, T2, T3, O
|
||||
---@param first integer|string|fun(v: T3): O
|
||||
---@param second integer|string|fun(v: T2): T3
|
||||
---@param third integer|string|fun(v: T1): T2
|
||||
---@param fourth integer|string|fun(v: I): T1
|
||||
---@return fun(v: I): O
|
||||
---@nodiscard
|
||||
function f.compose(first, second, third, fourth)
|
||||
error {first, second, third, fourth}
|
||||
end
|
||||
|
||||
---@generic I, T1, T2, T3, T4, O
|
||||
---@param first integer|string|fun(v: T4): O
|
||||
---@param second integer|string|fun(v: T3): T4
|
||||
---@param third integer|string|fun(v: T2): T3
|
||||
---@param fourth integer|string|fun(v: T1): T2
|
||||
---@param fifth integer|string|fun(v: I): T1
|
||||
---@return fun(v: I): O
|
||||
---@nodiscard
|
||||
function f.compose(first, second, third, fourth, fifth)
|
||||
error {first, second, third, fourth, fifth}
|
||||
end
|
||||
|
||||
---@generic I, O
|
||||
---@param all { [1]: (integer|string|fun(v: I): O) }
|
||||
---@return fun(v: I): O
|
||||
---@nodiscard
|
||||
function f.compose(all)
|
||||
error(all)
|
||||
end
|
||||
|
||||
---@generic I, T, O
|
||||
---@param all { [1]: (integer|string|fun(v: T): O), [2]: (integer|string|fun(v: I): T) }
|
||||
---@return fun(v: I): O
|
||||
---@nodiscard
|
||||
function f.compose(all)
|
||||
error(all)
|
||||
end
|
||||
|
||||
---@generic I, T1, T2, O
|
||||
---@param all { [1]: (integer|string|fun(v: T2): O), [2]: (integer|string|fun(v: T1): T2), [3]: (integer|string|fun(v: I): T1) }
|
||||
---@return fun(v: I): O
|
||||
---@nodiscard
|
||||
function f.compose(all)
|
||||
error(all)
|
||||
end
|
||||
|
||||
---@generic I, T1, T2, T3, O
|
||||
---@param all { [1]: (integer|string|fun(v: T3): O), [2]: (integer|string|fun(v: T2): T3), [3]: (integer|string|fun(v: T1): T2), [4]: (integer|string|fun(v: I): T1) }
|
||||
---@return fun(v: I): O
|
||||
---@nodiscard
|
||||
function f.compose(all)
|
||||
error(all)
|
||||
end
|
||||
|
||||
---@generic I, T1, T2, T3, T4, O
|
||||
---@param all { [1]: (integer|string|fun(v: T4): O), [2]: (integer|string|fun(v: T3): T4), [3]: (integer|string|fun(v: T2): T3), [4]: (integer|string|fun(v: T1): T2), [4]: (integer|string|fun(v: I): T1) }
|
||||
---@return fun(v: I): O
|
||||
---@nodiscard
|
||||
function f.compose(all)
|
||||
error(all)
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param self F | { [K]: V }
|
||||
---@return K?, V?
|
||||
|
|
@ -235,84 +18,39 @@ end
|
|||
---@type F
|
||||
local none
|
||||
|
||||
---@generic T: F|function|string|nil
|
||||
---@param func T
|
||||
---@return T
|
||||
---@nodiscard
|
||||
local function autofunc(func)
|
||||
if func == false then
|
||||
return f.fals
|
||||
elseif func == true then
|
||||
return f.tru
|
||||
elseif type(func) == "number" then
|
||||
return f.arg(func)
|
||||
elseif type(func) == "string" then
|
||||
return f.indices(func)
|
||||
else
|
||||
return func or f.id
|
||||
end
|
||||
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[1] 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(v: 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
|
||||
|
|
@ -331,212 +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)
|
||||
for i in v:gmatch "[^.]+" do
|
||||
if type(x) ~= "table" then
|
||||
return x
|
||||
end
|
||||
|
||||
x = x[i]
|
||||
end
|
||||
|
||||
return x
|
||||
end
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param v V
|
||||
---@param k K
|
||||
---@return fun(x: { [K]: V }): { [K]: V }
|
||||
---@nodiscard
|
||||
function f.insert(v, k)
|
||||
return function(x)
|
||||
if type(x) == "table" then
|
||||
x[k] = v
|
||||
end
|
||||
|
||||
return x
|
||||
end
|
||||
end
|
||||
|
||||
---@generic T
|
||||
---@param tbl T[]
|
||||
---@return fun(t: T[], i?: integer): integer, T
|
||||
---@return T[]
|
||||
function f.revpairs(tbl)
|
||||
return function(t, i)
|
||||
local k = i and i - 1 or #t
|
||||
local v = t[k]
|
||||
|
||||
if v ~= nil then
|
||||
return k, v
|
||||
end
|
||||
end, tbl
|
||||
end
|
||||
|
||||
---@param any any
|
||||
---@return boolean
|
||||
---@nodiscard
|
||||
function f.isf(any)
|
||||
return type(any) == "table" and any.from == f.from and any.new == f.new
|
||||
end
|
||||
|
||||
local unpack = table.unpack or unpack
|
||||
|
||||
f[true and "call"] = function(self, ...)
|
||||
local args = {...}
|
||||
|
||||
return type(self) == "string" and function(v)
|
||||
return v[self](v, unpack(args))
|
||||
end or function(v)
|
||||
return v(unpack(args))
|
||||
end
|
||||
end
|
||||
|
||||
f[true and "chain"] = function(...)
|
||||
local ret
|
||||
|
||||
for _, v in ipairs {...} do
|
||||
v = f.isf(v) and v:table() or v
|
||||
|
||||
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
|
||||
|
||||
f[true and "compose"] = function(...)
|
||||
return f.chain(f.from({...}, f.revpairs):values())
|
||||
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,
|
||||
call = f.call,
|
||||
chain = f.chain,
|
||||
compose = f.compose,
|
||||
concat = f.concat,
|
||||
const = f.const,
|
||||
count = f.count,
|
||||
diff = f.diff,
|
||||
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,
|
||||
insert = f.insert,
|
||||
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,
|
||||
rev = f.rev,
|
||||
revpairs = f.revpairs,
|
||||
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
|
||||
|
|
@ -545,24 +138,16 @@ 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, tbl, 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(tbl, k)
|
||||
k, v = next(context, k)
|
||||
return k, v
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
|
|
@ -571,69 +156,46 @@ end
|
|||
---@return F|{ [K]: V }
|
||||
---@nodiscard
|
||||
function f:concat(...)
|
||||
self = f.isf(self) and self or f.from(self)
|
||||
local fsi = 0
|
||||
local fs = {...}
|
||||
local sum, last = 0, 0
|
||||
|
||||
for i = 1, #fs do
|
||||
local s = fs[i]
|
||||
fs[i] = f.isf(s) and s or f.from(s)
|
||||
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)
|
||||
self = f.isf(self) and self or f.from(self)
|
||||
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)
|
||||
self = f.isf(self) and self or f.from(self)
|
||||
func = autofunc(func)
|
||||
func = type(func) == "string" and f.index(func) or func
|
||||
|
||||
return f.new(function()
|
||||
local k, v = self:next()
|
||||
|
|
@ -646,20 +208,17 @@ 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)
|
||||
self = f.isf(self) and self or f.from(self)
|
||||
-- local i = 0
|
||||
local vt, vk, vp
|
||||
func = autofunc(func)
|
||||
local vt, vk, vv, vp
|
||||
func = type(func) == "string" and f.index(func) or func
|
||||
|
||||
return f.new(function()
|
||||
local vv
|
||||
|
||||
if vk then
|
||||
vk, vv = vp(vt, vk)
|
||||
|
||||
|
|
@ -699,14 +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)
|
||||
self = f.isf(self) and self or f.from(self)
|
||||
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
|
||||
|
|
@ -718,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
|
||||
|
|
@ -738,7 +287,6 @@ end
|
|||
---@return F|{ [integer]: K }
|
||||
---@nodiscard
|
||||
function f:keys()
|
||||
self = f.isf(self) and self or f.from(self)
|
||||
local i = 0
|
||||
|
||||
return f.new(function()
|
||||
|
|
@ -756,7 +304,6 @@ end
|
|||
---@return F|{ [integer]: V }
|
||||
---@nodiscard
|
||||
function f:values()
|
||||
self = f.isf(self) and self or f.from(self)
|
||||
local i = 0
|
||||
|
||||
return f.new(function()
|
||||
|
|
@ -769,44 +316,6 @@ function f:values()
|
|||
end)
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
---@return F|{ [V]: K }
|
||||
---@nodiscard
|
||||
function f:swap()
|
||||
self = f.isf(self) and self or f.from(self)
|
||||
|
||||
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 }
|
||||
---@return F|{ [K]: V }
|
||||
---@nodiscard
|
||||
function f:rev()
|
||||
self = f.isf(self) and self or f.from(self)
|
||||
local t, p, k
|
||||
|
||||
return f.new(function()
|
||||
if not t then
|
||||
p, t = f.revpairs(self:table())
|
||||
end
|
||||
|
||||
local v
|
||||
k, v = p(t, k)
|
||||
|
||||
if k ~= nil then
|
||||
return k, v
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
---@param skip? integer
|
||||
|
|
@ -814,8 +323,6 @@ end
|
|||
---@return F|{ [K]: V }
|
||||
---@nodiscard
|
||||
function f:slice(skip, take)
|
||||
self = f.isf(self) and self or f.from(self)
|
||||
|
||||
if (not skip or skip <= 0) and not take then
|
||||
return self
|
||||
end
|
||||
|
|
@ -847,7 +354,6 @@ end
|
|||
---@return F|{ [K]: V }
|
||||
---@nodiscard
|
||||
function f:skip(n)
|
||||
self = f.isf(self) and self or f.from(self)
|
||||
return self:slice(n)
|
||||
end
|
||||
|
||||
|
|
@ -857,7 +363,6 @@ end
|
|||
---@return F|{ [K]: V }
|
||||
---@nodiscard
|
||||
function f:take(n)
|
||||
self = f.isf(self) and self or f.from(self)
|
||||
return self:slice(0, n)
|
||||
end
|
||||
|
||||
|
|
@ -869,7 +374,6 @@ end
|
|||
---@overload fun(self: F|{ [K]: V }, seed: fun(a: A, v: V, k: K): A): A
|
||||
---@nodiscard
|
||||
function f:fold(seed, func)
|
||||
self = f.isf(self) and self or f.from(self)
|
||||
local k, v
|
||||
|
||||
if not func then
|
||||
|
|
@ -894,13 +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)
|
||||
self = f.isf(self) and self or f.from(self)
|
||||
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
|
||||
|
|
@ -913,13 +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)
|
||||
self = f.isf(self) and self or f.from(self)
|
||||
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
|
||||
|
|
@ -932,14 +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)
|
||||
self = f.isf(self) and self or f.from(self)
|
||||
func = autofunc(func)
|
||||
local ret = 0
|
||||
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
|
||||
|
|
@ -950,39 +451,11 @@ function f:count(func)
|
|||
return ret
|
||||
end
|
||||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
---@param other { [K]: V }
|
||||
---@param func? fun(v: V, k: K): any
|
||||
---@return K?, V?
|
||||
---@overload fun(self: F|{ [K]: V }, func: string): integer
|
||||
---@nodiscard
|
||||
function f:diff(other, func)
|
||||
self = f.isf(self) and self or f.from(self)
|
||||
func = autofunc(func)
|
||||
|
||||
for k, v in self.next do
|
||||
if (not func or func(v, k)) and other[k] ~= v then
|
||||
return k, v
|
||||
end
|
||||
end
|
||||
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
|
||||
---@nodiscard
|
||||
function f:string()
|
||||
self = f.isf(self) and self or f.from(self)
|
||||
local k, v = self:next()
|
||||
|
||||
if k == nil then
|
||||
|
|
@ -1007,7 +480,6 @@ end
|
|||
---@return { [K]: V }
|
||||
---@nodiscard
|
||||
function f:table()
|
||||
self = f.isf(self) and self or f.from(self)
|
||||
local ret = {}
|
||||
|
||||
for k, v in self.next do
|
||||
|
|
@ -1019,10 +491,8 @@ 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)
|
||||
self = f.isf(self) and self or f.from(self)
|
||||
|
||||
for k, v in self.next do
|
||||
if func then
|
||||
func(v, k)
|
||||
|
|
@ -1032,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,97 +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
|
||||
|
||||
---@return Card
|
||||
function copy_card(...)
|
||||
error(...)
|
||||
end
|
||||
|
||||
--- @type fun(area: CardArea, ...: ...): Card
|
||||
create_card_for_shop = create_card_for_shop
|
||||
|
||||
--- @type CardArea
|
||||
G.Bakery_charm_area = G.Bakery_charm_area
|
||||
|
||||
--- @type boolean|table
|
||||
G.Bakery_charm_area.cards[1].ability.extra = G.Bakery_charm_area.cards[1].ability.extra
|
||||
|
||||
---@type Card[]
|
||||
G.playing_cards = G.playing_cards
|
||||
|
||||
---@type userdata|{getWidth: fun(self: self): number}
|
||||
SMODS.Atlas.image_data = SMODS.Atlas.image_data
|
||||
|
||||
---@param context CalcContext|table|{hand_drawn: true, other_drawn: true}
|
||||
---@param return_table? table
|
||||
---@return table?
|
||||
function SMODS.calculate_context(context, return_table)
|
||||
error {context, return_table}
|
||||
end
|
||||
|
||||
SMODS.Mods.Roland.config = require "config"
|
||||
|
||||
---@type (fun(rem: number): number|table)[]
|
||||
SMODS.Mods.Roland.harsh_ante_scaling = SMODS.Mods.Roland.harsh_ante_scaling
|
||||
|
||||
--- @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,89 +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 v == "op" then
|
||||
local op = SMODS.add_card {no_edition = true, key = "j_joker"}
|
||||
op.ability.mult = 1e100
|
||||
return op
|
||||
elseif v == "xop" then
|
||||
local xop = SMODS.add_card {no_edition = true, key = "j_Roland_jokersr"}
|
||||
xop.ability.extra.xmult = 1e100
|
||||
return xop
|
||||
end
|
||||
|
||||
if G.P_BLINDS[v] then
|
||||
if G.STATE ~= G.STATES.MENU then
|
||||
G.from_boss_tag = true
|
||||
G.GAME.perscribed_bosses = G.GAME.perscribed_bosses or {}
|
||||
G.GAME.perscribed_bosses[G.GAME.round_resets.ante] = v
|
||||
G.FUNCS.reroll_boss()
|
||||
end
|
||||
|
||||
return G.P_BLINDS[v]
|
||||
end
|
||||
|
||||
if not G.P_TAGS[v] then
|
||||
return SMODS.add_card {
|
||||
no_edition = true,
|
||||
key = v,
|
||||
area = G.P_CENTERS[v] and
|
||||
(({Default = true, Enhanced = true})[G.P_CENTERS[v].set] and G.hand or
|
||||
G.P_CENTERS[v].set == "Booster" and G.shop_booster or
|
||||
G.P_CENTERS[v].set == "Voucher" and G.shop_vouchers) or nil,
|
||||
}
|
||||
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 ({op = true, xop = true})[it] or (G.P_CENTERS[it] or {}).config then
|
||||
return it
|
||||
end
|
||||
|
||||
local match = simplify(it)
|
||||
|
||||
local pool = match == "Blind" and G.P_BLINDS or
|
||||
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(function(v, k)
|
||||
return ((G.P_CENTERS[k] or {}).config or G.P_BLINDS[k]) and
|
||||
(match == simplify(k) or match == simplify(v.name))
|
||||
end)
|
||||
:keys()
|
||||
:any()
|
||||
end
|
||||
|
||||
local function protect(fun)
|
||||
return function()
|
||||
local res, ret = pcall(fun)
|
||||
|
|
@ -92,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}
|
||||
|
|
|
|||
122
src/main.lua
|
|
@ -1,97 +1,73 @@
|
|||
local qol = assert(SMODS.load_file "src/lib/shared.lua")() or require "lib.shared"
|
||||
local animated = SMODS.current_mod.config.animated_icon
|
||||
SMODS.current_mod.qol = qol
|
||||
local f, q = qol[1], qol[2]
|
||||
|
||||
q {
|
||||
front = true,
|
||||
no_delete = true,
|
||||
blocking = false,
|
||||
blockable = false,
|
||||
func = function()
|
||||
local contributors = (Bakery_API or {}).contributors
|
||||
|
||||
if not contributors then
|
||||
return false
|
||||
end
|
||||
|
||||
f(assert(SMODS.load_file("src/credits.lua", "Roland"))() or require "credits"):each(function(v, k)
|
||||
contributors["Roland_" .. k] = v
|
||||
end)
|
||||
|
||||
if SMODS.Mods.DebugPlus and SMODS.Mods.Roland.config.import_funky then
|
||||
_G.f, _G.q, _G.u, _G.c = unpack(qol)
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
f {"challenge", "spectral", "edition", "voucher", "tweaks", "blind", "charm", "joker", "tarot", "back", "seal", "tag"}
|
||||
: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)
|
||||
|
||||
local _ = Balatest and f {"joker", "blind", "spectral"}:each(function(v)
|
||||
assert(SMODS.load_file("src/tests/" .. v .. ".tests.lua"))(qol)
|
||||
end)
|
||||
|
||||
local function realign(tbl)
|
||||
f(tbl):where(function(v, k)
|
||||
if k == "align" and type(v) == "string" then
|
||||
tbl[k] = "tr"
|
||||
end
|
||||
|
||||
return k ~= "nodes" and type(v) == "table"
|
||||
end):each(realign)
|
||||
|
||||
return tbl
|
||||
if Balatest then
|
||||
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 realign(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
|
||||
|
||||
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 = "tr", padding = 0.1, colour = G.C.BLACK},
|
||||
nodes = {
|
||||
{
|
||||
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 = "tr", 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 "vitriol",
|
||||
toggle "equinox_assist",
|
||||
G.P_CENTERS.c_Bakery_Scribe and toggle "scribable_basket",
|
||||
create_toggle {
|
||||
label = localize {type = "variable", key = "b_Roland_equinox_assist"},
|
||||
ref_table = SMODS.Mods.Roland.config,
|
||||
ref_value = "equinox_assist",
|
||||
scale = 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
n = G.UIT.C,
|
||||
config = {minw = 1, minh = 1, align = "tr", padding = 0.1, colour = G.C.CLEAR},
|
||||
nodes = {
|
||||
toggle "faster_planets",
|
||||
toggle "illusion_seal",
|
||||
toggle "no_wild_debuff",
|
||||
SMODS.Mods.DebugPlus and toggle "import_funky",
|
||||
Talisman and toggle "harsh_ante_scaling",
|
||||
},
|
||||
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
|
||||
|
||||
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
|
||||
|
|
|
|||
183
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,140 +38,99 @@ 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,
|
||||
can_use = function()
|
||||
return next(G.hand.cards) and u()
|
||||
return u() and #G.hand.cards > 0
|
||||
end,
|
||||
use = function(_, card)
|
||||
local cards = f(G.hand.cards):table()
|
||||
use = function(_, card, _)
|
||||
local cards = f(G.hand.cards, ipairs):table()
|
||||
pseudoshuffle(cards, pseudoseed "RolandDual")
|
||||
|
||||
f(cards):take(card.ability.extra.amount):each(function(v)
|
||||
local seal = SMODS.poll_seal {
|
||||
guaranteed = true,
|
||||
options = f(G.P_SEALS):keys():where(f.nq "Roland_glass"):values():table(),
|
||||
}
|
||||
local seal
|
||||
|
||||
local _ = not card.Roland_immediate and q {
|
||||
delay = 0.5,
|
||||
trigger = "after",
|
||||
func = function()
|
||||
v:set_seal(seal, nil, true)
|
||||
end,
|
||||
} or v:set_seal(seal, true, true)
|
||||
for _ = 1, 31 do
|
||||
seal = SMODS.poll_seal {guaranteed = true}
|
||||
|
||||
if seal ~= "Roland_glass" then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
v:set_seal(seal == "Roland_glass" and "Red" or seal)
|
||||
end)
|
||||
end,
|
||||
bulk_use = function(self, card, area, copier, number)
|
||||
card.Roland_immediate = true
|
||||
f(number):map(f.const(self)):each(f.call("use", card, area, copier))
|
||||
card.Roland_immediate = nil
|
||||
end,
|
||||
}
|
||||
|
||||
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}}
|
||||
end,
|
||||
can_use = function(_, card)
|
||||
local count = #Bakery_API.get_highlighted()
|
||||
return u() and count > 0 and count <= card.ability.extra.amount
|
||||
return u() and #Bakery_API.get_highlighted() == card.ability.extra.amount
|
||||
end,
|
||||
use = function()
|
||||
use = function(_, _, _)
|
||||
f(Bakery_API.get_highlighted()):each(function(v)
|
||||
v:set_seal "Roland_glass"
|
||||
end)
|
||||
end,
|
||||
}
|
||||
|
||||
spectral {
|
||||
local void = spectral {
|
||||
key = "void",
|
||||
pronouns = "it_its",
|
||||
artist = "aster",
|
||||
hidden = true,
|
||||
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)
|
||||
|
|
@ -189,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)
|
||||
|
|
|
|||
144
src/tag.lua
|
|
@ -1,144 +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)
|
||||
tag.ability = tag.ability or {}
|
||||
table.insert(info_queue, G.P_CENTERS.e_Roland_frozen)
|
||||
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
|
||||
not context.card or
|
||||
context.card.edition or
|
||||
context.type ~= "Bakery_score_card" or
|
||||
(tag.ability.amount or self.config.amount) <= 0 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 G.jokers 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,46 +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()
|
||||
local count = #G.jokers.highlighted + #highlighted
|
||||
|
||||
return count > 0 and count <= 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
|
||||
|
|
@ -68,7 +68,8 @@ Balatest.TestPlay {
|
|||
}
|
||||
end)
|
||||
|
||||
Balatest.wait_for_input(G.STATES.ROUND_EVAL)
|
||||
Balatest.wait_for_input()
|
||||
Balatest.wait()
|
||||
end,
|
||||
assert = function()
|
||||
Balatest.assert_chips(2720)
|
||||
|
|
@ -191,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,
|
||||
|
|
@ -203,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",
|
||||
|
|
|
|||
155
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, self.ability.qty or 1)
|
||||
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,98 +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 = G.STATE == G.STATES.SHOP or
|
||||
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}
|
||||
ref:remove()
|
||||
|
||||
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()
|
||||
return ret
|
||||
end
|
||||
|
||||
q(function()
|
||||
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)
|
||||
|
||||
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
|
||||
|
||||
---@type (fun(rem: number): number|table)[]
|
||||
SMODS.current_mod.harsh_ante_scaling = {
|
||||
function(rem)
|
||||
return (Big.constants and Big.constants.TEN or Big:new {10}):pow(blind(rem + 1))
|
||||
end,
|
||||
function(rem)
|
||||
return Big:new {1, rem + 2}
|
||||
end,
|
||||
function(rem)
|
||||
return Big:new {1, 1, [rem + 2] = 1}
|
||||
end,
|
||||
function(rem)
|
||||
return Big:new {1, 1, [blind(rem) + 2] = 1}
|
||||
end,
|
||||
function(rem)
|
||||
return rem <= 1 and Big:new {1.7976931348623157e308, 1, [1.7975e308] = 1} or 1 / 0
|
||||
end,
|
||||
}
|
||||
|
||||
function get_blind_amount(ante, ...)
|
||||
local offset = 40
|
||||
|
||||
if ante < offset or no_harsh_ante_scaling() then
|
||||
return orig_get_blind_amount(ante, ...)
|
||||
end
|
||||
|
||||
local loop = 10
|
||||
|
||||
return f(SMODS.Mods.Roland.harsh_ante_scaling, f.revpairs):any(function(_, k)
|
||||
return (ante - offset) / loop + 1 >= k
|
||||
end)((ante - offset) % loop + 1)
|
||||
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,
|
||||
}
|
||||