Compare commits
No commits in common. "main" and "frozen-jokers" have entirely different histories.
main
...
frozen-jok
|
|
@ -33,7 +33,7 @@ table_separator_style = none
|
||||||
trailing_table_separator = smart
|
trailing_table_separator = smart
|
||||||
|
|
||||||
# keep/remove/remove_table_only/remove_string_only
|
# keep/remove/remove_table_only/remove_string_only
|
||||||
call_arg_parentheses = remove
|
call_arg_parentheses = keep
|
||||||
|
|
||||||
detect_end_of_line = false
|
detect_end_of_line = false
|
||||||
|
|
||||||
|
|
|
||||||
6
.gitignore
vendored
|
|
@ -38,9 +38,3 @@ luac.out
|
||||||
*.i*86
|
*.i*86
|
||||||
*.x86_64
|
*.x86_64
|
||||||
*.hex
|
*.hex
|
||||||
|
|
||||||
# Syncthing
|
|
||||||
.stfolder
|
|
||||||
|
|
||||||
# Autogenerated
|
|
||||||
assets/1x/jokers
|
|
||||||
|
|
|
||||||
4
.vscode/settings.json
vendored
|
|
@ -65,8 +65,4 @@
|
||||||
"unused-local": "Error",
|
"unused-local": "Error",
|
||||||
"unused-vararg": "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: 72 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: 75 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 29 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: 82 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: 88 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: 41 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,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 1x') do magick 1x\%%x -scale 200%% 2x\%%x
|
||||||
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
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,8 @@
|
||||||
#!/bin/sh
|
#!/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")
|
filename=$(basename "$file")
|
||||||
if [ ! -f "1x/${filename}" ]; then
|
output_file="$directory/2x/${filename}"
|
||||||
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/"
|
|
||||||
magick "$file" -filter point -resize 200% "$output_file"
|
magick "$file" -filter point -resize 200% "$output_file"
|
||||||
fi
|
|
||||||
done
|
done
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,9 @@
|
||||||
return {
|
return {
|
||||||
animated_icon = true,
|
|
||||||
cool_phones = true,
|
|
||||||
equinox_assist = false,
|
equinox_assist = false,
|
||||||
faster_planets = false,
|
fusable_escapey = false,
|
||||||
harsh_ante_scaling = false,
|
harsh_ante_scaling = true,
|
||||||
illusion_seal = true,
|
illusion_seal = true,
|
||||||
import_funky = false,
|
import_funky = false,
|
||||||
|
no_highlight_limit = true,
|
||||||
no_wild_debuff = true,
|
no_wild_debuff = true,
|
||||||
scribable_basket = false,
|
|
||||||
vitriol = true,
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,71 +6,52 @@ return {
|
||||||
text = {
|
text = {
|
||||||
"{C:attention}Small{} and {C:attention}Big Blinds{} are",
|
"{C:attention}Small{} and {C:attention}Big Blinds{} are",
|
||||||
"replaced with {C:attention}Boss Blinds",
|
"replaced with {C:attention}Boss Blinds",
|
||||||
"that are {C:dark_edition}debuffed thrice",
|
"that are {C:dark_edition}debuffed #1# times",
|
||||||
"",
|
|
||||||
"{C:Bakery_credit_fg_Roland_bakersdozenbagels,s:0.75}Art: BakersDozenBagels",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
b_Roland_dropship = {
|
b_Roland_go = {
|
||||||
name = "Dropship Deck",
|
name = "Pass GO Deck",
|
||||||
text = {
|
text = {
|
||||||
"{C:attention}Jokers {}are {C:money}free",
|
"Start with a {C:attention}Credit Card",
|
||||||
"and {C:attention}Perishable",
|
"Set money to {C:money}$0 {}when",
|
||||||
"",
|
"entering the shop",
|
||||||
"{C:Bakery_credit_fg_Roland_bakersdozenbagels,s:0.75}Art: BakersDozenBagels",
|
|
||||||
},
|
},
|
||||||
unlock = {"Have exclusively", "{C:attention}Perishable Jokers"},
|
|
||||||
},
|
},
|
||||||
b_Roland_swapper = {
|
b_Roland_swapper = {
|
||||||
name = "Swapper Deck",
|
name = "Swapper Deck",
|
||||||
text = {
|
text = {
|
||||||
"{C:tarot}Tarot {}and {C:spectral}Spectral",
|
"{C:tarot}Tarot {}and {C:spectral}Spectral",
|
||||||
"cards swap places",
|
"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 = {
|
||||||
BakeryCharm_Roland_cocacola = {
|
BakeryCharm_Roland_cocacola = {
|
||||||
name = SMODS.Mods.Roland.config.cool_phones and "coca cola phone" or "Pentagram",
|
name = "coca cola phone",
|
||||||
text = {
|
text = {
|
||||||
"{C:attention}Discard 0 cards {}to",
|
"Values on consumables",
|
||||||
"gain {C:red}#1# {}discards and",
|
"increase by {C:attention}1",
|
||||||
"lose {C:attention}#2# {}hand size",
|
"{C:inactive}(excluding {C:planet}Planets{C:inactive})",
|
||||||
"this round",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
BakeryCharm_Roland_fat = {
|
BakeryCharm_Roland_fat = {
|
||||||
name = SMODS.Mods.Roland.config.cool_phones and "fat i phone" or "Product",
|
name = "fat i phone",
|
||||||
text = {
|
text = {
|
||||||
"{C:attention}+#1# Booster Pack {}slots",
|
-- "{C:attention}+#1# Booster Pack {}slots",
|
||||||
"All {C:attention}Booster Packs {}are {C:attention}Mega",
|
"All {C:attention}Booster Packs {}are {C:attention}Mega",
|
||||||
"{C:inactive}(Whenever applicable)",
|
"{C:inactive}(Whenever applicable)",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
BakeryCharm_Roland_flexible = {
|
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)},
|
text = {unpack(G.localization.descriptions.Joker.j_ring_master.text)},
|
||||||
},
|
},
|
||||||
BakeryCharm_Roland_hand = {
|
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"},
|
text = {"{C:attention}+#1# {}hand size", "{C:blue}#2# {}hands"},
|
||||||
},
|
},
|
||||||
BakeryCharm_Roland_wii = {
|
BakeryCharm_Roland_wii = {
|
||||||
name = SMODS.Mods.Roland.config.cool_phones and "wii phone" or "Tire",
|
name = "wii phone",
|
||||||
text = {
|
text = {
|
||||||
"Enter the shop",
|
"Enter the shop",
|
||||||
"when any {C:attention}Blind",
|
"when any {C:attention}Blind",
|
||||||
|
|
@ -81,47 +62,39 @@ return {
|
||||||
Blind = {
|
Blind = {
|
||||||
bl_Roland_blizzard = {
|
bl_Roland_blizzard = {
|
||||||
name = "The Blizzard",
|
name = "The Blizzard",
|
||||||
text = {"All cards", "are {C:dark_edition}Frozen"},
|
text = {"All cards", "are Frozen"},
|
||||||
},
|
},
|
||||||
bl_Roland_divide = {
|
bl_Roland_divide = {
|
||||||
name = "The Great Divide",
|
name = "The Great Divide",
|
||||||
text = {"Half of the deck", "is {C:red}discarded"},
|
text = {"Half of the deck", "is discarded"},
|
||||||
},
|
},
|
||||||
bl_Roland_equinox = {
|
bl_Roland_equinox = {
|
||||||
name = "The Equinox",
|
name = "The Equinox",
|
||||||
text = {"{C:inactive}No UI"},
|
text = {"No UI"},
|
||||||
},
|
},
|
||||||
bl_Roland_falseshuffle = {
|
bl_Roland_falseshuffle = {
|
||||||
name = "The False Shuffle",
|
name = "The False Shuffle",
|
||||||
text = {"{C:enhanced}Enhanced {}cards", "are drawn {C:attention}last"},
|
text = {"Enhanced cards", "are drawn last"},
|
||||||
},
|
},
|
||||||
bl_Roland_improbable = {
|
bl_Roland_improbable = {
|
||||||
name = "The Improbable",
|
name = "The Improbable",
|
||||||
text = {"All {C:green}probabilities", "cannot happen"},
|
text = {"All probabilities", "cannot happen"},
|
||||||
},
|
},
|
||||||
bl_Roland_mitotic = {
|
bl_Roland_mitotic = {
|
||||||
name = "The Mitotic",
|
name = "The Mitotic",
|
||||||
text = {"{C:red}Discarded {}cards", "are {C:attention}copied"},
|
text = {"Discarded cards", "are copied"},
|
||||||
},
|
},
|
||||||
bl_Roland_nimble = {
|
bl_Roland_nimble = {
|
||||||
name = "The 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 = {
|
bl_Roland_tranquilizer = {
|
||||||
name = "The Tranquilizer",
|
name = "The Tranquilizer",
|
||||||
text = {
|
text = {"#1#s are debuffed", "Changes based on", "most common rank"},
|
||||||
"{C:attention}#1#s {}are {C:red}debuffed",
|
|
||||||
"Changes based on",
|
|
||||||
"most common rank",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
bl_Roland_venerable_visage = {
|
bl_Roland_venerable_visage = {
|
||||||
name = "Venerable Visage",
|
name = "Venerable Visage",
|
||||||
text = {
|
text = {"Infinite discards", "Lose if any card was", "not played or discarded"},
|
||||||
"Infinite {C:red}discards",
|
|
||||||
"Lose if {C:attention}any {}card was",
|
|
||||||
"not {C:blue}played {}or {C:red}discarded",
|
|
||||||
},
|
|
||||||
fail = {
|
fail = {
|
||||||
"Blasphemy.",
|
"Blasphemy.",
|
||||||
"Blunder.",
|
"Blunder.",
|
||||||
|
|
@ -153,28 +126,9 @@ return {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Joker = {
|
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 = {
|
j_Roland_arctic = {
|
||||||
name = "Arctic Circle",
|
name = "Arctic Circle",
|
||||||
text = {"Retrigger {C:attention}all", "{C:dark_edition}Frozen {}cards"},
|
text = {"Retrigger 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 = {
|
j_Roland_basket = {
|
||||||
name = "Basket",
|
name = "Basket",
|
||||||
|
|
@ -187,37 +141,11 @@ return {
|
||||||
j_Roland_bulldozer = {
|
j_Roland_bulldozer = {
|
||||||
name = "Bulldozer",
|
name = "Bulldozer",
|
||||||
text = {
|
text = {
|
||||||
"Give the {C:attention}Blind",
|
"Give {X:red,C:white}XMult{} equal to",
|
||||||
"{C:attention}Base {}as {X:red,C:white}XMult",
|
"the current {C:attention}Blind Size{C:attention}",
|
||||||
"{C:inactive}(Currently {X:red,C:white}X#1#{C:inactive} Mult)",
|
"{C:inactive}(Currently {X:red,C:white}X#1#{C:inactive})",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
j_Roland_cold = {
|
|
||||||
name = "Cold Turkey",
|
|
||||||
text = {
|
|
||||||
"Third scored card",
|
|
||||||
"gives {X:red,C:white}X#1#{} Mult",
|
|
||||||
"if it is {C:dark_edition}Frozen",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
j_Roland_cerulean = {
|
|
||||||
name = "Cerulean Bell",
|
|
||||||
text = {
|
|
||||||
"{X:mult,C:white}X#1#{} Mult",
|
|
||||||
"All other {C:attention}Jokers {}cannot",
|
|
||||||
"be selected or dragged",
|
|
||||||
},
|
|
||||||
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 = {
|
j_Roland_domino = {
|
||||||
name = "Domino",
|
name = "Domino",
|
||||||
text = {
|
text = {
|
||||||
|
|
@ -227,20 +155,30 @@ return {
|
||||||
"{C:inactive}(Currently {C:red}+#3#{C:inactive} Mult)",
|
"{C:inactive}(Currently {C:red}+#3#{C:inactive} Mult)",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
j_Roland_excalibur = {
|
j_Roland_escapey = {
|
||||||
name = "Excalibur",
|
name = "Escapey",
|
||||||
text = {
|
text = {
|
||||||
"Score {C:attention}#1# {C:enhanced}Stone Cards",
|
"Use to {C:attention}destroy tags{} or {C:attention}unselected consumables",
|
||||||
"to {C:attention}pull {}this {C:attention}Joker",
|
"in exchange for {C:planet}leveling up {X:planet,C:white}#1#{C:planet} random hands",
|
||||||
"{C:inactive}(Currently {C:attention}#2#{C:inactive})",
|
"{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_excalibur_Back = {
|
|
||||||
name = "Excalibur",
|
|
||||||
text = {
|
|
||||||
"Scored and held in",
|
|
||||||
"hand {C:enhanced}Stone Cards",
|
|
||||||
"each give {X:mult,C:white}X#3#{} Mult",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
j_Roland_hardboiled = {
|
j_Roland_hardboiled = {
|
||||||
|
|
@ -251,23 +189,6 @@ return {
|
||||||
"hand {C:dark_edition}Frozen",
|
"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 = {
|
j_Roland_jokersr = {
|
||||||
name = "Joker Sr.",
|
name = "Joker Sr.",
|
||||||
text = {"{X:mult,C:white}X#1#{} Mult"},
|
text = {"{X:mult,C:white}X#1#{} Mult"},
|
||||||
|
|
@ -288,8 +209,9 @@ return {
|
||||||
j_Roland_misfortune = {
|
j_Roland_misfortune = {
|
||||||
name = "Misfortune Cookie",
|
name = "Misfortune Cookie",
|
||||||
text = {
|
text = {
|
||||||
"Cards created by",
|
"{C:tarot}Tarot{} cards created",
|
||||||
"{C:attention}Seals {}become {C:dark_edition}Negative",
|
"by {C:tarot}Purple Seals",
|
||||||
|
"become {C:dark_edition}Negative",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
j_Roland_monomino = {
|
j_Roland_monomino = {
|
||||||
|
|
@ -315,14 +237,6 @@ return {
|
||||||
name = "Ms. Joker",
|
name = "Ms. Joker",
|
||||||
text = {"{C:chips}+#1#{} Chips"},
|
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 = {
|
j_Roland_oops = {
|
||||||
name = "Oops! All 7s",
|
name = "Oops! All 7s",
|
||||||
text = {
|
text = {
|
||||||
|
|
@ -333,15 +247,7 @@ return {
|
||||||
},
|
},
|
||||||
j_Roland_phytoestrogens = {
|
j_Roland_phytoestrogens = {
|
||||||
name = "Phytoestrogens",
|
name = "Phytoestrogens",
|
||||||
text = {"{C:mult}+Chips{} Mult, {X:mult,C:white}X#1#{} Mult"},
|
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 = {
|
j_Roland_sapling = {
|
||||||
name = "Sapling",
|
name = "Sapling",
|
||||||
|
|
@ -352,15 +258,6 @@ return {
|
||||||
"least {C:attention}#2# suits",
|
"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 = {
|
j_Roland_suitable = {
|
||||||
name = "Suitable",
|
name = "Suitable",
|
||||||
text = {"{V:1}#1# {}are {C:attention}Wild", "Suit changes", "every round"},
|
text = {"{V:1}#1# {}are {C:attention}Wild", "Suit changes", "every round"},
|
||||||
|
|
@ -370,7 +267,7 @@ return {
|
||||||
text = {
|
text = {
|
||||||
"Sell this Joker to",
|
"Sell this Joker to",
|
||||||
"{C:attention}draw{} the bottom",
|
"{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})",
|
"{C:inactive}(Currently {V:1}#1#{C:inactive}#2#{V:2}#3#{C:inactive})",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -391,38 +288,13 @@ return {
|
||||||
"{C:attention}#2#",
|
"{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 = {
|
j_Roland_yard = {
|
||||||
name = "Yard Sale",
|
name = "Yard Sale",
|
||||||
text = {
|
text = {
|
||||||
"Gain {C:money}$#1#{} when a",
|
"Gain {C:money}$#1#{} when a",
|
||||||
"card is {C:attention}added",
|
"card is {C:attention}removed",
|
||||||
"or {C:attention}removed",
|
|
||||||
"from the deck",
|
"from the deck",
|
||||||
},
|
},
|
||||||
unlock = {"Complete the", "{C:attention}#1#", "challenge"},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Other = {
|
Other = {
|
||||||
|
|
@ -441,104 +313,78 @@ return {
|
||||||
text = {
|
text = {
|
||||||
"{C:attention}Small{} and {C:attention}Big Blinds{} are",
|
"{C:attention}Small{} and {C:attention}Big Blinds{} are",
|
||||||
"replaced with {C:attention}Boss Blinds",
|
"replaced with {C:attention}Boss Blinds",
|
||||||
"that are {C:dark_edition}debuffed thrice",
|
"that are {C:dark_edition}debuffed #1# times",
|
||||||
"",
|
|
||||||
"{C:Bakery_credit_fg_Roland_bakersdozenbagels,s:0.75}Art: BakersDozenBagels",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
sleeve_Roland_blossom_alt = {
|
sleeve_Roland_blossom_alt = {
|
||||||
name = "Efflorescent Sleeve",
|
name = "Efflorescent Sleeve",
|
||||||
text = {
|
text = {
|
||||||
"{C:dark_edition}Debuff {X:dark_edition,C:white}#1#X<ante>{C:dark_edition} times",
|
"{C:attention}Blinds{} are {C:dark_edition}debuffed",
|
||||||
"{C:inactive}(Instead of thrice)",
|
"{C:dark_edition}({X:dark_edition,C:white}ante{} {X:dark_edition,C:white}number{C:dark_edition}) times",
|
||||||
"",
|
"{C:inactive}(Instead of #1#)",
|
||||||
"{C:Bakery_credit_fg_Roland_bakersdozenbagels,s:0.75}Art: BakersDozenBagels",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
sleeve_Roland_dropship = {
|
sleeve_Roland_go = {
|
||||||
name = "Dropship Sleeve",
|
name = "Pass GO Sleeve",
|
||||||
text = {
|
text = {
|
||||||
"{C:attention}Jokers {}are {C:money}free",
|
"Start with a {C:attention}Credit Card",
|
||||||
"and {C:attention}Perishable",
|
"Set money to {C:money}$0 {}when",
|
||||||
"",
|
"entering the shop",
|
||||||
"{C:Bakery_credit_fg_Roland_bakersdozenbagels,s:0.75}Art: BakersDozenBagels",
|
|
||||||
},
|
},
|
||||||
unlock = {"Have exclusively", "{C:attention}Perishable Jokers"},
|
|
||||||
},
|
},
|
||||||
sleeve_Roland_dropship_alt = {
|
sleeve_Roland_go_alt = {
|
||||||
name = "Business Sleeve",
|
name = "Free Parking Sleeve",
|
||||||
text = {
|
text = {
|
||||||
"{C:attention}Jokers {}are instead",
|
"Start with an additional",
|
||||||
"{C:dark_edition}Negative {}and {C:money}Rental",
|
"{X:attention,C:white}#1#{C:attention} Credit Cards",
|
||||||
"",
|
|
||||||
"{C:Bakery_credit_fg_Roland_bakersdozenbagels,s:0.75}Art: BakersDozenBagels",
|
|
||||||
},
|
},
|
||||||
unlock = {"Have exclusively", "{C:attention}Perishable Jokers"},
|
|
||||||
},
|
},
|
||||||
sleeve_Roland_swapper = {
|
sleeve_Roland_swapper = {
|
||||||
name = "Swapper Sleeve",
|
name = "Swapper Sleeve",
|
||||||
text = {
|
text = {
|
||||||
"{C:tarot}Tarot {}and {C:spectral}Spectral",
|
"{C:tarot}Tarot {}and {C:spectral}Spectral",
|
||||||
"cards swap places",
|
"cards swap places",
|
||||||
"",
|
|
||||||
"{C:Bakery_credit_fg_Roland_bakersdozenbagels,s:0.75}Art: BakersDozenBagels",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
sleeve_Roland_swapper_alt = {
|
sleeve_Roland_swapper_alt = {
|
||||||
name = "Sleeve Swapper",
|
name = "Sleeve Swapper",
|
||||||
text = {
|
text = {
|
||||||
"Swap {C:attention}all {}consumables",
|
"{C:attention}All {}consumable",
|
||||||
"",
|
"types swap places",
|
||||||
"{C:Bakery_credit_fg_Roland_bakersdozenbagels,s:0.75}Art: BakersDozenBagels",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
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 = {
|
Spectral = {
|
||||||
c_Roland_afterimage = {
|
c_Roland_afterimage = {
|
||||||
name = "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 = {
|
text = {
|
||||||
"Add random seals",
|
"Add random seals",
|
||||||
"to {C:attention}#1#{} random",
|
"to {C:attention}#1#{} random",
|
||||||
"cards in hand",
|
"cards in {C:hands}hand",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
c_Roland_primal = {
|
c_Roland_coolheaded = {
|
||||||
name = "Primal Force",
|
name = "Coolheaded",
|
||||||
text = {
|
text = {
|
||||||
"Enhance {C:attention}all {}cards",
|
"Add {C:dark_edition}Frozen {}to {C:attention}#1#",
|
||||||
"held in hand to",
|
"selected {C:attention}playing",
|
||||||
"{C:enhanced}Stone Cards",
|
"{C:attention}card {}or {C:attention}Joker",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
c_Roland_refract = {
|
c_Roland_mirror = {
|
||||||
name = "Refract",
|
name = "Mirror",
|
||||||
text = {
|
text = {
|
||||||
"Add a {C:dark_edition}Glass Seal",
|
"Add a {C:dark_edition}Glass Tag",
|
||||||
"to {C:attention}#1#{} selected",
|
"to {C:attention}#1#{} selected",
|
||||||
"cards in hand",
|
"card in {C:hands}hand",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
c_Roland_void = {
|
c_Roland_void = {
|
||||||
|
|
@ -550,47 +396,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 = {
|
misc = {
|
||||||
challenge_names = {
|
challenge_names = {
|
||||||
|
|
@ -599,38 +404,28 @@ return {
|
||||||
c_Roland_Eternally_Crimson = "Eternally Crimson",
|
c_Roland_Eternally_Crimson = "Eternally Crimson",
|
||||||
c_Roland_Eternally_Verdant = "Eternally Verdant",
|
c_Roland_Eternally_Verdant = "Eternally Verdant",
|
||||||
c_Roland_Eternally_Violet = "Eternally Violet",
|
c_Roland_Eternally_Violet = "Eternally Violet",
|
||||||
c_Roland_Glass = "Glass House",
|
|
||||||
c_Roland_Go = "Pass GO",
|
|
||||||
c_Roland_Jokerful = "Jokerful",
|
c_Roland_Jokerful = "Jokerful",
|
||||||
|
c_Roland_Ornate = "Ornate",
|
||||||
c_Roland_Pastries = "Sweet Pastries",
|
c_Roland_Pastries = "Sweet Pastries",
|
||||||
c_Roland_Spin_To_Win = "Spin to Win",
|
c_Roland_Showdown = "Showdown",
|
||||||
c_Roland_Spring_Cleaning = "Spring Cleaning",
|
|
||||||
},
|
},
|
||||||
v_dictionary = {
|
v_dictionary = {
|
||||||
b_Roland_add = "ADD",
|
|
||||||
b_Roland_animated_icon = "Animated Icon (requires restart)",
|
|
||||||
b_Roland_bye = "Bye!",
|
b_Roland_bye = "Bye!",
|
||||||
b_Roland_comma = ", ",
|
b_Roland_comma = ", ",
|
||||||
b_Roland_cool_phones = "cool phones (requires restart)",
|
|
||||||
b_Roland_debuffed = "DEBUFFED",
|
b_Roland_debuffed = "DEBUFFED",
|
||||||
b_Roland_disabled = "Disabled",
|
|
||||||
b_Roland_enabled = "Enabled",
|
|
||||||
b_Roland_entering_shop = "Entering shop!",
|
b_Roland_entering_shop = "Entering shop!",
|
||||||
|
b_Roland_escape = "ESCAPE",
|
||||||
|
b_Roland_fuse = "FUSE",
|
||||||
b_Roland_equinox_assist = "Assist: Only hide text (Equinox)",
|
b_Roland_equinox_assist = "Assist: Only hide text (Equinox)",
|
||||||
b_Roland_faster_planets = "Faster Planets",
|
b_Roland_fusable_escapey = "Fusable Escapey (overpowered)",
|
||||||
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_harsh_ante_scaling = "Harsh ante scaling (Ante 40+)",
|
||||||
b_Roland_illusion_seal = "Allow seals from Illusion voucher",
|
b_Roland_illusion_seal = "Allow seals from Illusion voucher",
|
||||||
b_Roland_import_funky = "Debug: Import funky.lua",
|
b_Roland_import_funky = "Debug: Import funky.lua",
|
||||||
b_Roland_most_common_card = "Rank",
|
b_Roland_most_common_card = "(Rank)",
|
||||||
|
b_Roland_no_highlight_limit = "No consumable highlight limit",
|
||||||
b_Roland_no_wild_debuff = "No wild card debuffs",
|
b_Roland_no_wild_debuff = "No wild card debuffs",
|
||||||
b_Roland_na = "N/A",
|
b_Roland_na = "N/A",
|
||||||
b_Roland_of = " of ",
|
b_Roland_of = " of ",
|
||||||
b_Roland_toggle = "TOGGLE",
|
|
||||||
b_Roland_unassigned = "(Unassigned)",
|
|
||||||
b_Roland_vitriol = "Vitriol (Venerable Visage)",
|
|
||||||
},
|
},
|
||||||
labels = {
|
labels = {
|
||||||
Roland_frozen = "Frozen",
|
Roland_frozen = "Frozen",
|
||||||
|
|
@ -642,17 +437,15 @@ return {
|
||||||
ch_c_Roland_Eternally_Crimson = {"{C:attention}Crimson Heart{}'s effect is active every blind"},
|
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_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_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_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_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_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_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_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_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_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"
|
target = "game.lua"
|
||||||
pattern = "self.GAME.round_resets.blind_choices.Boss = get_new_boss()"
|
pattern = "self.GAME.round_resets.blind_choices.Boss = get_new_boss()"
|
||||||
position = "before"
|
position = "before"
|
||||||
payload = """
|
payload = '''
|
||||||
if G.GAME.modifiers.Roland_blossom_deck then
|
if G.GAME.modifiers.Roland_blossom_deck then
|
||||||
self.GAME.round_resets.blind_choices.Small = get_new_boss()
|
self.GAME.round_resets.blind_choices.Small = get_new_boss()
|
||||||
self.GAME.round_resets.blind_choices.Big = get_new_boss()
|
self.GAME.round_resets.blind_choices.Big = get_new_boss()
|
||||||
end
|
end
|
||||||
"""
|
'''
|
||||||
match_indent = true
|
match_indent = true
|
||||||
|
|
||||||
[[patches]]
|
[[patches]]
|
||||||
|
|
@ -25,12 +25,12 @@ match_indent = true
|
||||||
target = "functions/common_events.lua"
|
target = "functions/common_events.lua"
|
||||||
pattern = "G.GAME.round_resets.blind_choices.Boss = get_new_boss()"
|
pattern = "G.GAME.round_resets.blind_choices.Boss = get_new_boss()"
|
||||||
position = "before"
|
position = "before"
|
||||||
payload = """
|
payload = '''
|
||||||
if G.GAME.modifiers.Roland_blossom_deck then
|
if G.GAME.modifiers.Roland_blossom_deck then
|
||||||
G.GAME.round_resets.blind_choices.Small = get_new_boss()
|
G.GAME.round_resets.blind_choices.Small = get_new_boss()
|
||||||
G.GAME.round_resets.blind_choices.Big = get_new_boss()
|
G.GAME.round_resets.blind_choices.Big = get_new_boss()
|
||||||
end
|
end
|
||||||
"""
|
'''
|
||||||
match_indent = true
|
match_indent = true
|
||||||
|
|
||||||
[[patches]]
|
[[patches]]
|
||||||
|
|
@ -65,19 +65,6 @@ position = "at"
|
||||||
payload = "elseif G.GAME.blind_on_deck == 'Big' then"
|
payload = "elseif G.GAME.blind_on_deck == 'Big' then"
|
||||||
match_indent = true
|
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]]
|
||||||
[patches.pattern]
|
[patches.pattern]
|
||||||
target = "card.lua"
|
target = "card.lua"
|
||||||
|
|
@ -95,120 +82,6 @@ pattern = "local card = create_card('Tarot',G.consumeables, nil, nil, nil, nil,
|
||||||
position = "after"
|
position = "after"
|
||||||
times = 1
|
times = 1
|
||||||
payload = """if next(SMODS.find_card "j_Roland_misfortune") then
|
payload = """if next(SMODS.find_card "j_Roland_misfortune") then
|
||||||
card:set_edition("e_negative", true, true)
|
card:set_edition "e_negative"
|
||||||
end"""
|
end"""
|
||||||
match_indent = true
|
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",
|
"id": "Roland",
|
||||||
"name": "Roland",
|
"name": "Roland",
|
||||||
"prefix": "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": [
|
"author": [
|
||||||
"Emik"
|
"Emik"
|
||||||
],
|
],
|
||||||
|
"version": "2.2.0",
|
||||||
|
"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": [
|
"dependencies": [
|
||||||
"Steamodded (>=1.0.0~BETA-1606b)",
|
"Steamodded (>=1.*)",
|
||||||
"Lovely (>=0.6)",
|
"Lovely (>=0.6)",
|
||||||
"Bakery (>=3.2.0~*)"
|
"Bakery (>=1.3.2~*)"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
1
refs/src
|
|
@ -1 +0,0 @@
|
||||||
../../smods/src
|
|
||||||
280
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)
|
local function save(ret)
|
||||||
q(save_run)
|
q(save_run)
|
||||||
|
|
@ -8,7 +8,7 @@ end
|
||||||
local back = (function()
|
local back = (function()
|
||||||
local x = 0
|
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)
|
return function(tbl)
|
||||||
local key = tbl.key
|
local key = tbl.key
|
||||||
local apply = tbl.apply
|
local apply = tbl.apply
|
||||||
|
|
@ -23,16 +23,27 @@ local back = (function()
|
||||||
end
|
end
|
||||||
|
|
||||||
tbl.pos = {x = x, y = 0}
|
tbl.pos = {x = x, y = 0}
|
||||||
tbl.is_alt = f.fals
|
|
||||||
tbl.atlas = "back"
|
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
|
||||||
|
|
||||||
|
local sleeve = (_G["CardSleeves"] or {}).Sleeve
|
||||||
|
SMODS.Back(tbl)
|
||||||
|
x = x + 1
|
||||||
|
|
||||||
|
if not sleeve then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
sleeve {
|
||||||
key = key,
|
key = key,
|
||||||
pos = tbl.pos,
|
pos = tbl.pos,
|
||||||
atlas = "sleeve",
|
atlas = "back",
|
||||||
pronouns = tbl.pronouns,
|
|
||||||
config = tbl.config and f(tbl.config):table() or nil,
|
config = tbl.config and f(tbl.config):table() or nil,
|
||||||
loc_vars = function(self, ...)
|
loc_vars = function(self, ...)
|
||||||
local ret = tbl.loc_vars and tbl.loc_vars(self, ...) or {}
|
local ret = tbl.loc_vars and tbl.loc_vars(self, ...) or {}
|
||||||
|
|
@ -40,7 +51,7 @@ local back = (function()
|
||||||
return ret
|
return ret
|
||||||
end,
|
end,
|
||||||
apply = function(self, ...)
|
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,
|
end,
|
||||||
calculate = function(self, ...)
|
calculate = function(self, ...)
|
||||||
return (tbl.alt_calculate and self:is_alt() and tbl.alt_calculate or calculate)(self, ...)
|
return (tbl.alt_calculate and self:is_alt() and tbl.alt_calculate or calculate)(self, ...)
|
||||||
|
|
@ -49,176 +60,115 @@ local back = (function()
|
||||||
return self.get_current_deck_key() == "b_Roland_" .. key
|
return self.get_current_deck_key() == "b_Roland_" .. key
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
return back
|
|
||||||
end
|
end
|
||||||
end)()
|
end)()
|
||||||
|
|
||||||
local back_atlas = SMODS.Atlas {
|
SMODS.Atlas {
|
||||||
key = "back",
|
key = "back",
|
||||||
path = "back.png",
|
path = "back.png",
|
||||||
px = 71,
|
px = 71,
|
||||||
py = 95,
|
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 {
|
back {
|
||||||
key = "blossom",
|
key = "blossom",
|
||||||
pronouns = "any_all",
|
pronouns = "any_all",
|
||||||
config = {extra = {alt_times = 9, times = 3}},
|
config = {extra = {times = 2}},
|
||||||
attributes = {"passive", "boss_blind"},
|
loc_vars = function(self, _, _)
|
||||||
loc_vars = function(self)
|
return {vars = {self.config.extra.times}}
|
||||||
return {vars = {self.config.extra.alt_times}}
|
|
||||||
end,
|
end,
|
||||||
apply = function()
|
apply = function(_, _)
|
||||||
G.GAME.modifiers.Roland_blossom_deck = true
|
G.GAME.modifiers.Roland_blossom_deck = true
|
||||||
end,
|
end,
|
||||||
calculate = function(self, b, context)
|
calculate = function(self, card, context)
|
||||||
if not context.forcetrigger and not context.setting_blind then
|
if not context.setting_blind then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local blinds = G.GAME.round_resets.blind_states
|
local blinds = G.GAME.round_resets.blind_states
|
||||||
|
|
||||||
if not context.forcetrigger and
|
if blinds.Small ~= "Current" and blinds.Big ~= "Current" then
|
||||||
blinds.Small ~= "Current" and
|
|
||||||
blinds.Big ~= "Current" then
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local function debuff(times)
|
local count = self:is_alt() and G.GAME.round_resets.ante or self.config.extra.times
|
||||||
return function()
|
|
||||||
if times <= 0 then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
|
for _ = 1, count do
|
||||||
G.GAME.blind:disable()
|
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()
|
G.GAME.blind:wiggle()
|
||||||
play_sound "timpani"
|
play_sound "timpani"
|
||||||
q {func = debuff(times - 1)}
|
end,
|
||||||
|
}
|
||||||
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
|
end
|
||||||
|
|
||||||
local times = self:is_alt() and
|
ease_dollars(-G.GAME.dollars)
|
||||||
G.GAME.round_resets.ante * self.config.extra.alt_times or
|
|
||||||
self.config.extra.times
|
|
||||||
|
|
||||||
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,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
back {
|
back {
|
||||||
key = "swapper",
|
key = "swapper",
|
||||||
pronouns = "he_him",
|
pronouns = "he_him",
|
||||||
attributes = {"passive", "editions", "sell_value"},
|
|
||||||
apply = function(self)
|
apply = function(self)
|
||||||
local modifiers = G.GAME.modifiers
|
local modifiers = G.GAME.modifiers
|
||||||
modifiers.Roland_swapper_deck = true
|
modifiers.Roland_swapper_deck = true
|
||||||
modifiers.Roland_alt_swapper_deck = modifiers.Roland_alt_swapper_deck or self:is_alt()
|
modifiers.Roland_alt_swapper_deck = modifiers.Roland_alt_swapper_deck or self:is_alt()
|
||||||
end,
|
end,
|
||||||
calculate = f.noop,
|
calculate = function() end,
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
local swapper = {Spectral = "Tarot", Tarot = "Spectral"}
|
local swapper = {Spectral = "Tarot", Tarot = "Spectral"}
|
||||||
local orig_create_card = create_card
|
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
|
|
||||||
|
|
||||||
function create_card(_type, ...)
|
function create_card(_type, ...)
|
||||||
if not G.GAME.modifiers.Roland_swapper_deck then
|
if not G.GAME.modifiers.Roland_swapper_deck then
|
||||||
return create_dropshipped_card(_type, ...)
|
return orig_create_card(_type, ...)
|
||||||
end
|
end
|
||||||
|
|
||||||
if not G.GAME.modifiers.Roland_alt_swapper_deck then
|
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
|
end
|
||||||
|
|
||||||
local type = f(SMODS.ConsumableTypes):keys():where(function(v)
|
local type = f(SMODS.ConsumableTypes):keys():where(function(v)
|
||||||
|
|
@ -226,79 +176,5 @@ function create_card(_type, ...)
|
||||||
end):table()
|
end):table()
|
||||||
|
|
||||||
local has_type = SMODS.ConsumableTypes[_type]
|
local has_type = SMODS.ConsumableTypes[_type]
|
||||||
return create_dropshipped_card(
|
return orig_create_card(has_type and pseudorandom_element(type, pseudoseed "Roland_alt_swapper_deck") or _type, ...)
|
||||||
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
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
215
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 blind = (function()
|
||||||
local y = 0
|
local y = 0
|
||||||
|
|
||||||
---@param tbl SMODS.Blind|{idea?: string}
|
---@param tbl SMODS.Blind
|
||||||
---@return SMODS.Blind
|
---@return SMODS.Blind
|
||||||
return function(tbl)
|
return function(tbl)
|
||||||
tbl.idea = tbl.idea and "Roland_" .. tbl.idea or nil
|
|
||||||
tbl.pos = {x = 0, y = y}
|
tbl.pos = {x = 0, y = y}
|
||||||
tbl.atlas = "blind"
|
tbl.atlas = "blind"
|
||||||
|
local ret = SMODS.Blind(tbl)
|
||||||
y = y + 1
|
y = y + 1
|
||||||
return q(SMODS.Blind(tbl))
|
return ret
|
||||||
end
|
end
|
||||||
end)()
|
end)()
|
||||||
|
|
||||||
|
|
@ -23,12 +23,18 @@ SMODS.Atlas {
|
||||||
atlas_table = "ANIMATION_ATLAS",
|
atlas_table = "ANIMATION_ATLAS",
|
||||||
}
|
}
|
||||||
|
|
||||||
SMODS.Sound {key = "kick", path = "kick.ogg"}
|
SMODS.Sound {
|
||||||
|
key = "kick",
|
||||||
|
path = "kick.ogg",
|
||||||
|
}
|
||||||
|
|
||||||
local function common_rank()
|
local function common_rank()
|
||||||
|
---@type { [integer]: integer }, { [integer]: string }
|
||||||
local tally, to_name = {}, {}
|
local tally, to_name = {}, {}
|
||||||
|
|
||||||
f(G.playing_cards):where(SMODS.has_no_rank, false):each(function(v)
|
f(G.playing_cards):where(function(v)
|
||||||
|
return not SMODS.has_no_rank(v)
|
||||||
|
end):each(function(v)
|
||||||
local id = v:get_id()
|
local id = v:get_id()
|
||||||
to_name[id] = v.base.value
|
to_name[id] = v.base.value
|
||||||
tally[id] = (tally[id] or 0) + 1
|
tally[id] = (tally[id] or 0) + 1
|
||||||
|
|
@ -52,7 +58,7 @@ end
|
||||||
|
|
||||||
local function has_enhancement(card)
|
local function has_enhancement(card)
|
||||||
local e = SMODS.get_enhancements(card)
|
local e = SMODS.get_enhancements(card)
|
||||||
return e and next(e)
|
return not not (e and next(e))
|
||||||
end
|
end
|
||||||
|
|
||||||
local function set_freeze(state)
|
local function set_freeze(state)
|
||||||
|
|
@ -62,10 +68,6 @@ local function set_freeze(state)
|
||||||
|
|
||||||
---@param card Card|{ Roland_blizzard: true|nil }
|
---@param card Card|{ Roland_blizzard: true|nil }
|
||||||
return function(card)
|
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
|
local last_edition = card.Roland_blizzard
|
||||||
card.Roland_blizzard = state and (copy(card.edition) or true) or nil
|
card.Roland_blizzard = state and (copy(card.edition) or true) or nil
|
||||||
|
|
||||||
|
|
@ -163,7 +165,7 @@ blind {
|
||||||
local _ = not b.disabled and context.drawing_cards and table.sort(G.deck.cards, sort_by_enhancement)
|
local _ = not b.disabled and context.drawing_cards and table.sort(G.deck.cards, sort_by_enhancement)
|
||||||
end,
|
end,
|
||||||
in_pool = function()
|
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,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -174,7 +176,13 @@ blind {
|
||||||
pronouns = "he_they",
|
pronouns = "he_they",
|
||||||
disable = function()
|
disable = function()
|
||||||
-- Ensures that this runs after 'set_blind' since it also gets added to queue.
|
-- 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,
|
end,
|
||||||
set_blind = function()
|
set_blind = function()
|
||||||
-- Allows the background to ease in first before drawing cards.
|
-- Allows the background to ease in first before drawing cards.
|
||||||
|
|
@ -216,10 +224,6 @@ blind {
|
||||||
draw_card(G.hand, G.discard, i / count * 100, "down", false, copy, nil, nil, true)
|
draw_card(G.hand, G.discard, i / count * 100, "down", false, copy, nil, nil, true)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
if not next(cards_added) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
b:wiggle()
|
b:wiggle()
|
||||||
b.triggered = true
|
b.triggered = true
|
||||||
playing_card_joker_effects(cards_added)
|
playing_card_joker_effects(cards_added)
|
||||||
|
|
@ -228,27 +232,25 @@ blind {
|
||||||
|
|
||||||
blind {
|
blind {
|
||||||
key = "blizzard",
|
key = "blizzard",
|
||||||
idea = "redstoad",
|
|
||||||
boss = {min = 3},
|
boss = {min = 3},
|
||||||
boss_colour = HEX "102a41ff",
|
boss_colour = HEX "102a41ff",
|
||||||
pronouns = "it_its",
|
pronouns = "it_its",
|
||||||
defeat = function(self)
|
defeat = function(self)
|
||||||
self.cards():where "Roland_blizzard":each(set_freeze())
|
self.cards():each(set_freeze())
|
||||||
G.GAME.blind.disabled = true
|
G.GAME.blind.disabled = true
|
||||||
end,
|
end,
|
||||||
disable = function(self)
|
disable = function(self)
|
||||||
self:defeat()
|
self:defeat()
|
||||||
end,
|
end,
|
||||||
calculate = function(self, b, context)
|
calculate = function(self, b)
|
||||||
return not b.disabled and
|
return not b.disabled and self.cards():where(function(v)
|
||||||
context.hand_drawn and
|
return not v.Roland_blizzard and v.facing == "front"
|
||||||
self.cards()
|
end):each(set_freeze(true)) or nil
|
||||||
:where("Roland_blizzard", false)
|
|
||||||
:where("facing", "front")
|
|
||||||
:each(set_freeze(true)) or nil
|
|
||||||
end,
|
end,
|
||||||
cards = function()
|
cards = function()
|
||||||
return f(G):where(getmetatable, CardArea):flatmap("cards", ipairs)
|
return f(G):where(function(v)
|
||||||
|
return type(v) == "table" and type(v.cards) == "table"
|
||||||
|
end):flatmap("cards", ipairs)
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -257,7 +259,7 @@ blind {
|
||||||
boss = {min = 6},
|
boss = {min = 6},
|
||||||
boss_colour = HEX "bdaeccff",
|
boss_colour = HEX "bdaeccff",
|
||||||
pronouns = "they_them",
|
pronouns = "they_them",
|
||||||
collection_loc_vars = function()
|
collection_loc_vars = function(_)
|
||||||
return {
|
return {
|
||||||
vars = {localize {
|
vars = {localize {
|
||||||
type = "variable",
|
type = "variable",
|
||||||
|
|
@ -265,7 +267,7 @@ blind {
|
||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
end,
|
end,
|
||||||
loc_vars = function()
|
loc_vars = function(_)
|
||||||
local _, name = common_rank()
|
local _, name = common_rank()
|
||||||
return {vars = {localize(name or "Ace", "ranks")}}
|
return {vars = {localize(name or "Ace", "ranks")}}
|
||||||
end,
|
end,
|
||||||
|
|
@ -299,12 +301,9 @@ blind {
|
||||||
b:set_text()
|
b:set_text()
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
disable = function()
|
|
||||||
G.GAME.blind.disabled = true
|
|
||||||
end,
|
|
||||||
recalc_debuff = function(self, card)
|
recalc_debuff = function(self, card)
|
||||||
local id, _ = common_rank()
|
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
|
self.triggered = ret
|
||||||
return ret
|
return ret
|
||||||
end,
|
end,
|
||||||
|
|
@ -319,7 +318,7 @@ blind {
|
||||||
dollars = 5,
|
dollars = 5,
|
||||||
defeat = disable_improbable,
|
defeat = disable_improbable,
|
||||||
disable = disable_improbable,
|
disable = disable_improbable,
|
||||||
set_blind = function()
|
set_blind = function(_)
|
||||||
G.GAME.modifiers.Roland_improbable = true
|
G.GAME.modifiers.Roland_improbable = true
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
@ -332,65 +331,15 @@ if cry_prob then
|
||||||
end
|
end
|
||||||
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)
|
function SMODS.current_mod:calculate(context)
|
||||||
call("calc", context)
|
if context.setting_blind and G.GAME.blind.name == "bl_mp_nemesis" then
|
||||||
|
local modifiers = G.GAME.modifiers
|
||||||
local _ = context.before and
|
modifiers.Roland_martingale_seed = (modifiers.Roland_martingale_seed or 0) + 1
|
||||||
f {"v_Roland_ceres", "v_Roland_neptune"}
|
end
|
||||||
: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)
|
|
||||||
|
|
||||||
|
local _ = type(G.calc) == "function" and G.calc(f(context):keys():string())
|
||||||
local improbable, orig = G.GAME.modifiers.Roland_improbable, G.GAME.probabilities
|
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,
|
-- Normally unreachable since we set it to nil ourselves,
|
||||||
-- but other mods may want to use this modifier.
|
-- but other mods may want to use this modifier.
|
||||||
if improbable == false then
|
if improbable == false then
|
||||||
|
|
@ -404,7 +353,7 @@ function SMODS.current_mod:calculate(context)
|
||||||
|
|
||||||
local normal = orig.normal
|
local normal = orig.normal
|
||||||
|
|
||||||
G.GAME.probabilities = setmetatable({}, {
|
local mt = {
|
||||||
orig = orig,
|
orig = orig,
|
||||||
__index = function(_, k)
|
__index = function(_, k)
|
||||||
return k == "normal" and 0 or orig[k]
|
return k == "normal" and 0 or orig[k]
|
||||||
|
|
@ -412,7 +361,11 @@ function SMODS.current_mod:calculate(context)
|
||||||
__newindex = function(_, k, v)
|
__newindex = function(_, k, v)
|
||||||
orig[k] = (k == "normal" and v == 0) and normal or v
|
orig[k] = (k == "normal" and v == 0) and normal or v
|
||||||
end,
|
end,
|
||||||
})
|
}
|
||||||
|
|
||||||
|
local proxy = {}
|
||||||
|
setmetatable(proxy, mt)
|
||||||
|
G.GAME.probabilities = proxy
|
||||||
end
|
end
|
||||||
|
|
||||||
blind {
|
blind {
|
||||||
|
|
@ -501,31 +454,15 @@ local venerable_visage = blind {
|
||||||
}
|
}
|
||||||
end,
|
end,
|
||||||
vitriol = function(b)
|
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
|
if type(b) == "table" and type(b.wiggle) == "function" then
|
||||||
b:wiggle()
|
b:wiggle()
|
||||||
end
|
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 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 {
|
attention_text {
|
||||||
text = pseudorandom_element(fail, pseudoseed "RolandVenerableVisage"),
|
text = pseudorandom_element(fail, pseudoseed "RolandVenerableVisage"),
|
||||||
|
|
@ -535,50 +472,46 @@ local venerable_visage = blind {
|
||||||
hold = 2,
|
hold = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
f {0.15, 0.3, 0.45, 0.6}:each(function(v)
|
delay(1)
|
||||||
play_sound("gong", v)
|
|
||||||
end)
|
|
||||||
|
|
||||||
---@type number, number, table
|
f(G.playing_cards):each(function(v)
|
||||||
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)
|
|
||||||
q {
|
q {
|
||||||
trigger = "before",
|
trigger = "before",
|
||||||
delay = 6 / len,
|
delay = speed,
|
||||||
func = function()
|
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:start_dissolve()
|
||||||
v:shatter()
|
v:shatter()
|
||||||
b:wiggle()
|
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
local _ = vitriol and q {
|
delay(1)
|
||||||
trigger = "before",
|
|
||||||
delay = 1.5,
|
f(G.P_CARDS):each(function(v)
|
||||||
|
q {
|
||||||
|
delay = speed,
|
||||||
func = function()
|
func = function()
|
||||||
love.window.setPosition(x, y)
|
G.playing_card = (G.playing_card and G.playing_card + 1) or 1
|
||||||
love.window.setMode(w, h, flags)
|
|
||||||
love.resize(w, h)
|
local card = Card(
|
||||||
love.window.setFullscreen(is_fullscreen)
|
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,
|
||||||
}
|
}
|
||||||
|
end)
|
||||||
|
|
||||||
delay(1.5)
|
delay(1)
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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()
|
local function bans()
|
||||||
return {banned_cards = {}, banned_tags = {}, banned_other = {}}
|
return {banned_cards = {}, banned_tags = {}, banned_other = {}}
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param tbl table
|
|
||||||
---@return fun(v: SMODS.GameObject)
|
|
||||||
local function adder(tbl)
|
local function adder(tbl)
|
||||||
return function(v)
|
return function(v)
|
||||||
table.insert(tbl, {id = v.key, type = "blind"})
|
table.insert(tbl, {id = v.key, type = "blind"})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param v SMODS.GameObject
|
|
||||||
---@return boolean
|
|
||||||
local function is_banned_from_pastry(v)
|
local function is_banned_from_pastry(v)
|
||||||
return not ({Bakery = true, Roland = true})[(v.mod or {}).id]
|
return not ({Bakery = true, Roland = true})[(v.mod or {}).id]
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param v SMODS.Center
|
|
||||||
---@return boolean
|
|
||||||
local function is_center_banned_from_pastry(v)
|
local function is_center_banned_from_pastry(v)
|
||||||
local arcana_boosters = {
|
local arcana_boosters = {
|
||||||
p_arcana_normal_1 = true,
|
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)
|
return arcana_boosters[v.key] or pastries_targets[v.set] and is_banned_from_pastry(v)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param v SMODS.GameObject
|
local function is_joker(v)
|
||||||
---@return boolean|string
|
return v.set == "Joker" and not ({j_joker = true, j_Roland_msjoker = true})[v.key]
|
||||||
local function is_economy(v)
|
|
||||||
return f(Bakery_API.econ_only_items):where(f.eq(v.key)):any()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param key string
|
|
||||||
---@return fun(v: SMODS.Blind, k: string): boolean?
|
|
||||||
local function is_showdown_except(key)
|
local function is_showdown_except(key)
|
||||||
|
---@param v SMODS.Blind
|
||||||
|
---@param k string
|
||||||
|
---@return boolean?
|
||||||
return function(v, k)
|
return function(v, k)
|
||||||
return v.boss and v.boss.showdown and key ~= k
|
return v.boss and v.boss.showdown and key ~= k
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param name string
|
local function is_vanilla(v)
|
||||||
---@param amount number
|
return v.set and not v.mod and f(G.P_CENTERS):concat(G.P_CARDS, G.P_TAGS):any(function(c)
|
||||||
---@return {id: string}[]
|
return c.mod and not c.in_pool and c.set == v.set
|
||||||
local function multirule(name, amount)
|
end)
|
||||||
return f(amount):map(function(v)
|
|
||||||
return {id = "Roland_" .. name .. v}
|
|
||||||
end):table()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local pastries, amber, cerulean, crimson, verdant, violet, yard =
|
local jokerful, vanillas, pastries, amber, cerulean, crimson, verdant, violet, final
|
||||||
bans(), bans(), bans(), bans(), bans(), bans(), bans()
|
= bans(), bans(), bans(), bans(), bans(), bans(), bans(), bans(), bans()
|
||||||
|
|
||||||
SMODS.Challenge {
|
SMODS.Challenge {
|
||||||
key = "Glass",
|
key = "Jokerful",
|
||||||
rules = {custom = multirule("Glass", 2)},
|
rules = {custom = {{id = "Roland_Jokerful"}}},
|
||||||
pronouns = "they_them",
|
restrictions = jokerful,
|
||||||
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"}},
|
|
||||||
pronouns = "he_him",
|
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 {
|
SMODS.Challenge {
|
||||||
key = "Spin_To_Win",
|
key = "Ornate",
|
||||||
jokers = f(4):map(f.const {id = "j_joker", eternal = true}):table(),
|
rules = {custom = {{id = "Roland_Ornate"}}},
|
||||||
restrictions = {banned_cards = {{id = "c_Roland_coolheaded"}}},
|
restrictions = vanillas,
|
||||||
pronouns = "they_them",
|
pronouns = "any_all",
|
||||||
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 {
|
SMODS.Challenge {
|
||||||
|
|
@ -149,15 +73,12 @@ SMODS.Challenge {
|
||||||
pronouns = "she_them",
|
pronouns = "she_them",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local finalizers = {
|
||||||
|
|
||||||
SMODS.Challenge {
|
SMODS.Challenge {
|
||||||
key = "Eternally_Amber",
|
key = "Eternally_Amber",
|
||||||
rules = {custom = {{id = "Roland_Eternally_Amber"}, {id = "Roland_Showdown_Amber"}}},
|
rules = {custom = {{id = "Roland_Eternally_Amber"}, {id = "Roland_Showdown_Amber"}}},
|
||||||
jokers = {{id = "j_Roland_amber"}},
|
|
||||||
restrictions = 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)
|
calculate = function(_, context)
|
||||||
local function slide(pitch)
|
local function slide(pitch)
|
||||||
q(function()
|
q(function()
|
||||||
|
|
@ -189,17 +110,11 @@ SMODS.Challenge {
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
end,
|
end,
|
||||||
}
|
},
|
||||||
|
|
||||||
SMODS.Challenge {
|
SMODS.Challenge {
|
||||||
key = "Eternally_Cerulean",
|
key = "Eternally_Cerulean",
|
||||||
rules = {custom = {{id = "Roland_Eternally_Cerulean"}, {id = "Roland_Showdown_Cerulean"}}},
|
rules = {custom = {{id = "Roland_Eternally_Cerulean"}, {id = "Roland_Showdown_Cerulean"}}},
|
||||||
jokers = {{id = "j_Roland_cerulean"}},
|
|
||||||
restrictions = 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)
|
calculate = function(_, context)
|
||||||
if not context.hand_drawn then
|
if not context.hand_drawn then
|
||||||
return
|
return
|
||||||
|
|
@ -219,25 +134,20 @@ SMODS.Challenge {
|
||||||
G.hand:add_to_highlighted(v)
|
G.hand:add_to_highlighted(v)
|
||||||
end)
|
end)
|
||||||
end,
|
end,
|
||||||
}
|
},
|
||||||
|
|
||||||
SMODS.Challenge {
|
SMODS.Challenge {
|
||||||
key = "Eternally_Crimson",
|
key = "Eternally_Crimson",
|
||||||
rules = {custom = {{id = "Roland_Eternally_Crimson"}, {id = "Roland_Showdown_Crimson"}}},
|
rules = {custom = {{id = "Roland_Eternally_Crimson"}, {id = "Roland_Showdown_Crimson"}}},
|
||||||
jokers = {{id = "j_Roland_crimson"}},
|
|
||||||
restrictions = 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)
|
calculate = function(_, context)
|
||||||
local _ = context.blind_defeated and f(G.jokers.cards):each(function(v)
|
local _ = context.blind_defeated and f(G.jokers.cards):each(function(v)
|
||||||
v.ability.Roland_crimson_heart_chosen = nil
|
v.ability.Roland_crimson_heart_chosen = nil
|
||||||
end)
|
end)
|
||||||
|
|
||||||
local mod = G.GAME.modifiers
|
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
|
local debuff = context.debuff_card
|
||||||
|
---@type (SMODS.Joker|{ability?: {Roland_crimson_heart_chosen: boolean?}, debuff: boolean?})[]
|
||||||
local cards = G.jokers.cards
|
local cards = G.jokers.cards
|
||||||
|
|
||||||
if debuff and
|
if debuff and
|
||||||
|
|
@ -265,7 +175,9 @@ SMODS.Challenge {
|
||||||
local _ = v.debuff and SMODS.recalc_debuff(v)
|
local _ = v.debuff and SMODS.recalc_debuff(v)
|
||||||
end)
|
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)
|
local _ = not prev[v] and table.insert(jokers, v)
|
||||||
return v
|
return v
|
||||||
end):table()
|
end):table()
|
||||||
|
|
@ -282,17 +194,11 @@ SMODS.Challenge {
|
||||||
mod.Roland_Eternally_Crimson = not context.hand_drawn and
|
mod.Roland_Eternally_Crimson = not context.hand_drawn and
|
||||||
mod.Roland_Eternally_Crimson or nil
|
mod.Roland_Eternally_Crimson or nil
|
||||||
end,
|
end,
|
||||||
}
|
},
|
||||||
|
|
||||||
SMODS.Challenge {
|
SMODS.Challenge {
|
||||||
key = "Eternally_Verdant",
|
key = "Eternally_Verdant",
|
||||||
rules = {custom = {{id = "Roland_Eternally_Verdant"}, {id = "Roland_Showdown_Verdant"}}},
|
rules = {custom = {{id = "Roland_Eternally_Verdant"}, {id = "Roland_Showdown_Verdant"}}},
|
||||||
jokers = {{id = "j_Roland_verdant"}},
|
|
||||||
restrictions = 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)
|
calculate = function(_, context)
|
||||||
if context.setting_blind then
|
if context.setting_blind then
|
||||||
G.GAME.modifiers.Roland_Eternally_Verdant = true
|
G.GAME.modifiers.Roland_Eternally_Verdant = true
|
||||||
|
|
@ -308,55 +214,44 @@ SMODS.Challenge {
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
}
|
},
|
||||||
|
|
||||||
SMODS.Challenge {
|
SMODS.Challenge {
|
||||||
key = "Eternally_Violet",
|
key = "Eternally_Violet",
|
||||||
rules = {custom = {{id = "Roland_Eternally_Violet"}, {id = "Roland_Showdown_Violet"}}},
|
rules = {custom = {{id = "Roland_Eternally_Violet"}, {id = "Roland_Showdown_Violet"}}},
|
||||||
jokers = {{id = "j_joker"}, {id = "j_Roland_violet"}},
|
|
||||||
restrictions = 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,
|
|
||||||
calculate = function(_, context)
|
calculate = function(_, context)
|
||||||
if not context.setting_blind then
|
if context.setting_blind then
|
||||||
return
|
G.GAME.blind.chips = G.GAME.blind.chips * (6 / G.GAME.blind.mult)
|
||||||
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)
|
G.GAME.blind.chip_text = number_format(G.GAME.blind.chips)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
SMODS.Challenge {
|
||||||
|
key = "Showdown",
|
||||||
|
rules = {custom = {
|
||||||
|
{id = "Roland_Eternally_Amber"},
|
||||||
|
{id = "Roland_Eternally_Cerulean"},
|
||||||
|
{id = "Roland_Eternally_Crimson"},
|
||||||
|
{id = "Roland_Eternally_Verdant"},
|
||||||
|
{id = "Roland_Eternally_Violet"},
|
||||||
|
{id = "Roland_Showdown"},
|
||||||
|
}},
|
||||||
|
restrictions = final,
|
||||||
|
calculate = function(_, context)
|
||||||
|
f(finalizers):each(function(v)
|
||||||
|
v:calculate(context)
|
||||||
|
end)
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
q {
|
q(function()
|
||||||
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)
|
|
||||||
|
|
||||||
f {
|
f {
|
||||||
{G.P_TAGS, is_economy, yard.banned_tags},
|
{G.P_CENTERS, is_joker, jokerful.banned_cards},
|
||||||
{G.P_BLINDS, is_economy, yard.banned_other},
|
{G.P_TAGS, is_vanilla, vanillas.banned_tags},
|
||||||
{G.P_CENTERS, is_economy, yard.banned_cards},
|
{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_TAGS, is_banned_from_pastry, pastries.banned_tags},
|
||||||
{G.P_BLINDS, is_banned_from_pastry, pastries.banned_other},
|
{G.P_BLINDS, is_banned_from_pastry, pastries.banned_other},
|
||||||
{G.P_CENTERS, is_center_banned_from_pastry, pastries.banned_cards},
|
{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_heart", crimson.banned_other},
|
||||||
{G.P_BLINDS, is_showdown_except "bl_final_leaf", verdant.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_final_vessel", violet.banned_other},
|
||||||
|
{G.P_BLINDS, is_showdown_except "bl_Roland_venerable_visage", final.banned_other},
|
||||||
}:each(function(v)
|
}:each(function(v)
|
||||||
f(v[1]):where(v[2]):each(adder(v[3]))
|
f(v[1]):where(v[2]):each(adder(v[3]))
|
||||||
end)
|
end)
|
||||||
end,
|
end)
|
||||||
}
|
|
||||||
|
|
|
||||||
306
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 mod = SMODS.current_mod
|
||||||
local cool_phones = SMODS.Mods.Roland.config.cool_phones
|
|
||||||
|
|
||||||
SMODS.Atlas {
|
SMODS.Atlas {
|
||||||
key = "charm",
|
key = "charm",
|
||||||
path = cool_phones and "phorm.png" or "charm.png",
|
path = "charm.png",
|
||||||
px = 68,
|
px = 68,
|
||||||
py = 68,
|
py = 68,
|
||||||
}
|
}
|
||||||
|
|
||||||
local _ = cool_phones and SMODS.Sound {
|
|
||||||
key = "phone",
|
|
||||||
path = "phone.ogg",
|
|
||||||
}
|
|
||||||
|
|
||||||
local charm = (function()
|
local charm = (function()
|
||||||
local x = 0
|
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)
|
return function(tbl)
|
||||||
q {
|
q(function()
|
||||||
blocking = false,
|
|
||||||
no_delete = true,
|
|
||||||
func = function()
|
|
||||||
if not Bakery_API or not Bakery_API.Charm then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local current_mod = SMODS.current_mod
|
local current_mod = SMODS.current_mod
|
||||||
SMODS.current_mod = mod
|
SMODS.current_mod = mod
|
||||||
|
|
||||||
|
|
@ -35,143 +22,110 @@ local charm = (function()
|
||||||
tbl.unlocked = true
|
tbl.unlocked = true
|
||||||
tbl.discovered = true
|
tbl.discovered = true
|
||||||
tbl.pos = {x = x, y = 0}
|
tbl.pos = {x = x, y = 0}
|
||||||
tbl.atlas = "charm"
|
|
||||||
tbl.artist = not cool_phones and "Roland_bakersdozenbagels" or nil
|
|
||||||
x = x + 1
|
x = x + 1
|
||||||
|
tbl.atlas = "charm"
|
||||||
|
|
||||||
local orig_equip = tbl.equip
|
local charm = Bakery_API.Charm(tbl)
|
||||||
|
|
||||||
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))
|
|
||||||
charm:inject()
|
charm:inject()
|
||||||
charm:process_loc_text()
|
charm:process_loc_text()
|
||||||
SMODS.current_mod = current_mod
|
SMODS.current_mod = current_mod
|
||||||
end,
|
end, true)
|
||||||
}
|
|
||||||
end
|
end
|
||||||
end)()
|
end)()
|
||||||
|
|
||||||
local function can_discard_zero()
|
local function add_to_consumable_ability_by(n)
|
||||||
return G.GAME.current_round.discards_left > 0 and
|
local function new(v)
|
||||||
not next(G.hand.highlighted) and
|
return type(v) == "number" and v + n or type(v) == "table" and f(v):map(new):table() or v
|
||||||
G.hand.config.card_limit > 0 and
|
|
||||||
G.GAME.Bakery_charm == "BakeryCharm_Roland_cocacola"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
charm {
|
---@param card Card
|
||||||
key = "hand",
|
return function(card)
|
||||||
pronouns = "he_him",
|
local ability = card.ability or {}
|
||||||
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,
|
|
||||||
}
|
|
||||||
|
|
||||||
charm {
|
local function go(key)
|
||||||
key = "cocacola",
|
---@type { [string]: number }|number
|
||||||
pronouns = "he_they",
|
local value = ability[key]
|
||||||
attributes = {"passive", "tarot", "spectral"},
|
--print(key)
|
||||||
config = {extra = {discard = 2, hand_size = 1, refund = 0}},
|
if not value then
|
||||||
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
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local extra = card.ability.extra
|
if type(value) == "number" then
|
||||||
G.hand:change_size(extra.refund)
|
ability[key] = value + n
|
||||||
extra.refund = 0
|
return
|
||||||
end,
|
|
||||||
}
|
|
||||||
|
|
||||||
local orig_can_discard = G.FUNCS.can_discard
|
|
||||||
|
|
||||||
function G.FUNCS.can_discard(e, ...)
|
|
||||||
if can_discard_zero() then
|
|
||||||
e.config.button, e.config.colour = "Roland_cocacola", G.C.RED
|
|
||||||
else
|
|
||||||
return orig_can_discard(e, ...)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
G.FUNCS.Roland_cocacola = function()
|
if type(value) ~= "table" then
|
||||||
stop_use()
|
return
|
||||||
G.CONTROLLER.interrupt.focus = true
|
end
|
||||||
G.CONTROLLER:save_cardarea_focus "hand"
|
|
||||||
|
|
||||||
f(G.playing_cards):map "ability":each(function(v)
|
local new_value = f(value):map(new):table()
|
||||||
v.forced_selection = nil
|
|
||||||
|
f(new_value):each(function(v, k)
|
||||||
|
ability[k] = v
|
||||||
end)
|
end)
|
||||||
|
|
||||||
G.card_area_focus_reset = (G.CONTROLLER.focused.target or {}).area == G.hand and
|
ability[key] = new_value
|
||||||
{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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local center_key = (card.config or {}).center_key
|
||||||
|
|
||||||
|
if center_key and center_key:sub(1, 2) == "c_" then
|
||||||
|
f {"extra", "consumeable"}:each(go)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
charm {
|
||||||
|
key = "wii",
|
||||||
|
pronouns = "they_them",
|
||||||
|
calculate = function(_, card, context)
|
||||||
|
if not context.skip_blind then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local message = localize {type = "variable", key = "b_Roland_entering_shop"}
|
||||||
|
SMODS.calculate_effect({card = card, message = message, sound = "whoosh1"}, card)
|
||||||
|
|
||||||
|
q(function()
|
||||||
|
G.blind_prompt_box = G.blind_prompt_box and G.blind_prompt_box:remove()
|
||||||
|
G.blind_select = G.blind_select and G.blind_select:remove()
|
||||||
|
G.round_eval = G.round_eval and G.round_eval:remove()
|
||||||
|
G.GAME.current_round.jokers_purchased = 0
|
||||||
|
G.STATE = G.STATES.SHOP
|
||||||
|
G.GAME.shop_free = nil
|
||||||
|
G.GAME.shop_d6ed = nil
|
||||||
G.STATE_COMPLETE = false
|
G.STATE_COMPLETE = false
|
||||||
return true
|
play_sound("whoosh1", 1.33333, 0.8)
|
||||||
|
play_sound("whoosh1", 0.66666, 0.8)
|
||||||
|
end)
|
||||||
end,
|
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
|
end
|
||||||
|
|
||||||
charm {
|
charm {
|
||||||
key = "fat",
|
key = "fat",
|
||||||
pronouns = "he_they",
|
pronouns = "he_they",
|
||||||
attributes = {"passive"},
|
-- config = {extra = {mod = 1}},
|
||||||
config = {extra = {mod = 2}},
|
-- loc_vars = function(_, _, card)
|
||||||
loc_vars = function(_, _, card)
|
-- return {vars = {card.ability.extra.mod}}
|
||||||
return {vars = {card.ability.extra.mod}}
|
-- end,
|
||||||
end,
|
-- equip = function(_, card)
|
||||||
equip = function(_, card)
|
-- SMODS.change_booster_limit(card.ability.extra.mod)
|
||||||
SMODS.change_booster_limit(card.ability.extra.mod)
|
-- end,
|
||||||
end,
|
-- unequip = function(card)
|
||||||
unequip = function(_, card)
|
-- SMODS.change_booster_limit(-card.ability.extra.mod)
|
||||||
SMODS.change_booster_limit(-card.ability.extra.mod)
|
-- end,
|
||||||
end,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
local orig_init = Card.init
|
local orig_init = Card.init
|
||||||
|
|
@ -181,9 +135,7 @@ function Card:init(X, Y, W, H, card, center, params, ...)
|
||||||
return orig_init(self, X, Y, W, H, card, center, params, ...)
|
return orig_init(self, X, Y, W, H, card, center, params, ...)
|
||||||
end
|
end
|
||||||
|
|
||||||
local key = f {"mini", "jumbo", "normal"}:fold(center.key, function(a, v)
|
local key = center.key:gsub("normal", "mega"):gsub("jumbo", "mega"):gsub("mini", "mega")
|
||||||
return a:gsub(v, "mega")
|
|
||||||
end)
|
|
||||||
|
|
||||||
if G.P_CENTERS[key] then
|
if G.P_CENTERS[key] then
|
||||||
return orig_init(self, X, Y, W, H, card, G.P_CENTERS[key], params, ...)
|
return orig_init(self, X, Y, W, H, card, G.P_CENTERS[key], params, ...)
|
||||||
|
|
@ -206,70 +158,48 @@ function Card:init(X, Y, W, H, card, center, params, ...)
|
||||||
end
|
end
|
||||||
|
|
||||||
charm {
|
charm {
|
||||||
key = "flexible",
|
key = "cocacola",
|
||||||
pronouns = "any_all",
|
pronouns = "he_they",
|
||||||
}
|
equip = function()
|
||||||
|
f(G.consumeables.cards):each(add_to_consumable_ability_by(1))
|
||||||
local orig_showman = SMODS.showman
|
end,
|
||||||
|
unequip = function()
|
||||||
function SMODS.showman(...)
|
f(G.consumeables.cards):each(add_to_consumable_ability_by(-1))
|
||||||
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)
|
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
local orig_apply_to_run = Tag.apply_to_run
|
local orig_set_ability = Card.set_ability
|
||||||
|
|
||||||
function Tag:apply_to_run(...)
|
function Card:set_ability(center, initial, delay_sprites, ...)
|
||||||
if G.GAME.Bakery_charm == "BakeryCharm_Roland_wii" and
|
local ret = orig_set_ability(self, center, initial, delay_sprites, ...)
|
||||||
G.Bakery_charm_area.cards[1].ability.extra.active then
|
|
||||||
return
|
if G.GAME.Bakery_charm == "BakeryCharm_Roland_cocacola" then
|
||||||
|
add_to_consumable_ability_by(1)(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
return orig_apply_to_run(self, ...)
|
return ret
|
||||||
end
|
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",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
339
src/edition.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")
|
||||||
|
|
||||||
SMODS.Shader {
|
SMODS.Shader {
|
||||||
key = "frozen",
|
key = "frozen",
|
||||||
|
|
@ -12,14 +12,14 @@ local function frozen_sound(suffix)
|
||||||
end
|
end
|
||||||
|
|
||||||
frozen_sound "_click"
|
frozen_sound "_click"
|
||||||
local frozen_blocklist = {CardSleeve = true}
|
local frozen_sounds = f(4):map(frozen_sound):map("key"):table()
|
||||||
local frozen_sounds = f(4):map(frozen_sound):map "key":table()
|
|
||||||
|
|
||||||
local needs_chip_mult_override = {
|
local needs_chip_mult_override = {
|
||||||
Bull = true,
|
Bull = true,
|
||||||
Erosion = true,
|
Erosion = true,
|
||||||
Misprint = true,
|
Misprint = true,
|
||||||
TierList = true,
|
TierList = true,
|
||||||
|
Bootstraps = true,
|
||||||
["Blue Joker"] = true,
|
["Blue Joker"] = true,
|
||||||
["Abstract Joker"] = true,
|
["Abstract Joker"] = true,
|
||||||
["Fortune Teller"] = true,
|
["Fortune Teller"] = true,
|
||||||
|
|
@ -46,42 +46,17 @@ local function freeze(card)
|
||||||
---@param x T
|
---@param x T
|
||||||
---@return T
|
---@return T
|
||||||
local function copy(x)
|
local function copy(x)
|
||||||
return type(x) == "table" and f(x):map(copy):table() or x
|
return type(x) == "table" and f(x):map(copy):where(function(v, k)
|
||||||
|
return k ~= "Roland_frozen_proxy" and (k ~= "nine_tally" or v ~= 0)
|
||||||
|
end):table() or x
|
||||||
end
|
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.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.ability = card.Roland_frozen_ability and copy(card.Roland_frozen_ability) or card.ability
|
||||||
card.Roland_frozen = card.Roland_frozen or {probability = SMODS.get_probability_vars(card, 1, 1)}
|
local ret = card.Roland_frozen_ability
|
||||||
|
local ability = card.ability
|
||||||
|
|
||||||
if diff then
|
if type(ability) ~= "table" or not ability.name or not G.GAME.current_round 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
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -96,129 +71,23 @@ local function freeze(card)
|
||||||
return ret
|
return ret
|
||||||
end
|
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 {
|
SMODS.Edition {
|
||||||
key = "frozen",
|
key = "frozen",
|
||||||
shader = "frozen",
|
shader = "frozen",
|
||||||
sound = {sound = "Roland_frozen", per = 1, vol = 0.8},
|
sound = {sound = "Roland_frozen", per = 1, vol = 0.8},
|
||||||
attributes = {"passive", "scaling", "mod_chance"},
|
|
||||||
pronouns = "any_all",
|
|
||||||
weight = 8,
|
weight = 8,
|
||||||
extra_cost = 4,
|
extra_cost = 4,
|
||||||
in_shop = true,
|
in_shop = true,
|
||||||
apply_to_float = false,
|
apply_to_float = false,
|
||||||
calculate = function(_, card, context)
|
calculate = function(_, card)
|
||||||
local _ = not context.fix_probability and not context.mod_probability and freeze(card)
|
freeze(card)
|
||||||
end,
|
end,
|
||||||
on_remove = function(card)
|
on_remove = function(card)
|
||||||
card.Roland_frozen,
|
card.Roland_frozen_estate = nil
|
||||||
card.Roland_frozen_base,
|
card.Roland_frozen_ability = nil
|
||||||
card.Roland_frozen_card,
|
|
||||||
card.Roland_frozen_ability,
|
|
||||||
card.Roland_frozen_current_round = nil, nil, nil, nil, nil
|
|
||||||
end,
|
end,
|
||||||
get_weight = function(self)
|
get_weight = function(self)
|
||||||
return self.weight * G.GAME.edition_rate
|
return G.GAME.edition_rate * self.weight
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -250,49 +119,19 @@ function Card:click(...)
|
||||||
return ret
|
return ret
|
||||||
end
|
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
|
local orig_calculate_joker = Card.calculate_joker
|
||||||
|
|
||||||
---@param self Card|{Roland_frozen_ability?: table}
|
---@param self Card|{Roland_frozen_ability?: table}
|
||||||
function Card:calculate_joker(context, ...)
|
function Card:calculate_joker(context, ...)
|
||||||
local is_frozen = self.edition and self.edition.Roland_frozen
|
local is_frozen = self.edition and self.edition.Roland_frozen
|
||||||
|
|
||||||
if is_frozen and self.ability.name == "Loyalty Card" then
|
if is_frozen and self.ability.name == "Turtle Bean" 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
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local ret = {orig_calculate_joker(self, context, ...)}
|
local ret = {orig_calculate_joker(self, context, ...)}
|
||||||
|
|
||||||
if not is_frozen or type(ret[1]) ~= "table" then
|
if not is_frozen or not ret[1] then
|
||||||
return unpack(ret)
|
return unpack(ret)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -302,11 +141,24 @@ function Card:calculate_joker(context, ...)
|
||||||
return unpack(ret)
|
return unpack(ret)
|
||||||
end
|
end
|
||||||
|
|
||||||
return f {mult = "mult_mod", chips = "chip_mod", xmult = "xmult", x_mult = "x_mult"}:map(function(v)
|
ability.Roland_frozen_mult_mod = ability.Roland_frozen_mult_mod or ret[1].mult_mod
|
||||||
local key = "Roland_frozen_" .. v
|
ability.Roland_frozen_chip_mod = ability.Roland_frozen_chip_mod or ret[1].chip_mod
|
||||||
ability[key] = ability[key] or ret[1][v]
|
ability.Roland_frozen_xmult = ability.Roland_frozen_xmult or ret[1].xmult
|
||||||
return ability[key]
|
|
||||||
end):where(f.id):table()
|
return {
|
||||||
|
chip_mod = ability.Roland_frozen_chip_mod,
|
||||||
|
mult_mod = ability.Roland_frozen_mult_mod,
|
||||||
|
xmult = ability.Roland_frozen_xmult,
|
||||||
|
message = localize {
|
||||||
|
type = "variable",
|
||||||
|
key = "a_mult",
|
||||||
|
vars = {
|
||||||
|
ability.Roland_frozen_mult_mod or
|
||||||
|
ability.Roland_frozen_chip_mod or
|
||||||
|
ability.Roland_frozen_xmult,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
local orig_calculate_dollar_bonus = Card.calculate_dollar_bonus
|
local orig_calculate_dollar_bonus = Card.calculate_dollar_bonus
|
||||||
|
|
@ -329,49 +181,106 @@ function Card:calculate_dollar_bonus(...)
|
||||||
return orig_calculate_dollar_bonus(self, ...)
|
return orig_calculate_dollar_bonus(self, ...)
|
||||||
end
|
end
|
||||||
|
|
||||||
function SMODS.current_mod.bootstraps_mult(card)
|
q(function()
|
||||||
local ability = card.Roland_frozen_ability
|
local estate = G.P_CENTERS.j_Bakery_Estate
|
||||||
local ret = math.floor((G.GAME.dollars + (G.GAME.dollar_buffer or 0)) / card.ability.extra.dollars)
|
|
||||||
|
|
||||||
if not ability then
|
if not estate then
|
||||||
return ret
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
ability.Roland_bootstraps_mult = ability.Roland_bootstraps_mult or ret
|
local function estate_pos(card)
|
||||||
return ability.Roland_bootstraps_mult
|
if card.area ~= G.jokers and card.area.config.type ~= "title" then
|
||||||
|
return 1
|
||||||
end
|
end
|
||||||
|
|
||||||
local orig_get_probability_vars = SMODS.get_probability_vars
|
card.Roland_frozen_estate = card.Roland_frozen_estate and
|
||||||
|
card.Roland_frozen_estate or
|
||||||
|
(f(card.area.cards):swap():any(function(_, k)
|
||||||
|
return k == card
|
||||||
|
end) or 1)
|
||||||
|
|
||||||
function SMODS.get_probability_vars(trigger_obj, ...)
|
return card.Roland_frozen_estate
|
||||||
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
|
end
|
||||||
|
|
||||||
q {
|
local orig_calculate = estate.calculate
|
||||||
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
|
---@param card Card|{ Roland_frozen_ability: table, Roland_frozen_estate: integer }
|
||||||
return false
|
function estate:calculate(card, context, ...)
|
||||||
|
if not card or not card.edition or not card.edition.Roland_frozen then
|
||||||
|
return orig_calculate(self, card, context, ...)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Bakery_API.flip_double_sided(card, ...)
|
if not context.joker_main then
|
||||||
if not card.edition or not card.edition.Roland_frozen then
|
return
|
||||||
return orig_flip_double_sided(card, ...)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local _ = G.P_CENTERS.j_Bakery_Estate and hook_estate()
|
local joker_count = estate_pos(card)
|
||||||
local _ = G.P_CENTERS.c_Bakery_Scribe and hook_scribe()
|
local extra = card.ability.extra or {}
|
||||||
local _ = G.P_CENTERS.j_Bakery_Proxy and hook_proxy()
|
return {chips = extra.chips * joker_count, mult = extra.mult * joker_count}
|
||||||
end,
|
end
|
||||||
}
|
|
||||||
|
local orig_loc_vars = estate.loc_vars
|
||||||
|
|
||||||
|
function estate:loc_vars(info_queue, card, ...)
|
||||||
|
if not card or not card.edition or not card.edition.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)
|
||||||
|
|
||||||
|
q(function()
|
||||||
|
local proxy = G.P_CENTERS.j_Bakery_Proxy
|
||||||
|
|
||||||
|
if not proxy then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local function get_proxied_joker(card)
|
||||||
|
if not G.jokers or not G.jokers.cards then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local ability = freeze(card)
|
||||||
|
|
||||||
|
---@param v Card
|
||||||
|
local function eq(v)
|
||||||
|
return v.unique_val == ability.Roland_frozen_proxy
|
||||||
|
end
|
||||||
|
|
||||||
|
ability.Roland_frozen_proxy = (Bakery_API.get_proxied_joker() or card).unique_val
|
||||||
|
return f(G.jokers.cards):any(eq) ---@type Card?
|
||||||
|
end
|
||||||
|
|
||||||
|
local orig_calculate = proxy.calculate
|
||||||
|
|
||||||
|
---@param card Card|{ Roland_frozen_ability: table }
|
||||||
|
function proxy:calculate(card, context, ...)
|
||||||
|
if not card or not card.edition or not card.edition.Roland_frozen then
|
||||||
|
return orig_calculate(self, card, context, ...)
|
||||||
|
end
|
||||||
|
|
||||||
|
return SMODS.blueprint_effect(card, get_proxied_joker(card), context)
|
||||||
|
end
|
||||||
|
|
||||||
|
local orig_loc_vars = proxy.loc_vars
|
||||||
|
|
||||||
|
function proxy:loc_vars(info_queue, card, ...)
|
||||||
|
if not card or not card.edition or not card.edition.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)
|
||||||
|
|
|
||||||
1467
src/joker.lua
|
|
@ -3,227 +3,10 @@
|
||||||
---@license MPL-2.0
|
---@license MPL-2.0
|
||||||
---@version 1.0.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
|
---@class F
|
||||||
local f = {}
|
local f = {}
|
||||||
|
|
||||||
if not f then
|
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
|
---@generic K, V
|
||||||
---@param self F | { [K]: V }
|
---@param self F | { [K]: V }
|
||||||
---@return K?, V?
|
---@return K?, V?
|
||||||
|
|
@ -235,51 +18,35 @@ end
|
||||||
---@type F
|
---@type F
|
||||||
local none
|
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
|
---@generic K, V
|
||||||
---@param tbl table<K, V>
|
---@param tbl table<K, V>
|
||||||
---@param fpairs? fun(t: table<K, V>): (fun(table: table<K, V>, index?: K): 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 fun(tbl: table<K, V>, key: K): K, V
|
||||||
---@return table<K, V>
|
---@return K
|
||||||
---@return V
|
---@return V
|
||||||
---@nodiscard
|
|
||||||
local function autopairs(tbl, fpairs)
|
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
|
end
|
||||||
|
|
||||||
--- Always returns nil.
|
--- Always returns nil.
|
||||||
---@return nil
|
---@return nil
|
||||||
---@nodiscard
|
|
||||||
function f.noop()
|
function f.noop()
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Always returns false.
|
--- Always returns false.
|
||||||
---@return false
|
---@return false
|
||||||
---@nodiscard
|
|
||||||
function f.fals()
|
function f.fals()
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Always returns true.
|
--- Always returns true.
|
||||||
---@return true
|
---@return true
|
||||||
---@nodiscard
|
|
||||||
function f.tru()
|
function f.tru()
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
@ -288,31 +55,10 @@ end
|
||||||
---@generic T
|
---@generic T
|
||||||
---@param ... T
|
---@param ... T
|
||||||
---@return T
|
---@return T
|
||||||
---@nodiscard
|
|
||||||
function f.id(...)
|
function f.id(...)
|
||||||
return ...
|
return ...
|
||||||
end
|
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
|
---@generic T
|
||||||
---@param v T
|
---@param v T
|
||||||
---@return fun(): T
|
---@return fun(): T
|
||||||
|
|
@ -331,200 +77,55 @@ function f.const(v)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param i integer
|
|
||||||
---@return fun(...: any): any
|
|
||||||
---@nodiscard
|
|
||||||
function f.arg(i)
|
|
||||||
return function(...)
|
|
||||||
return ({...})[i]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
---@generic K, V
|
---@generic K, V
|
||||||
---@param v K
|
---@param v K
|
||||||
---@return fun(x: { [K]: V }): V
|
---@return fun(x: { [K]: V }): V
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
function f.index(v)
|
function f.index(v)
|
||||||
return function(x)
|
return function(x)
|
||||||
return type(x) == "table" and x[v] or x
|
return x[v]
|
||||||
end
|
end
|
||||||
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
|
---@generic K, V
|
||||||
---@param fnext? fun(): K?, V?
|
---@param fnext? fun(): K?, V?
|
||||||
---@return F|{ [K]: V }
|
---@return F|{ [K]: V }
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
function f.new(fnext)
|
function f.new(fnext)
|
||||||
-- Iterating over `f` is far easier, but we do this for performance sake.
|
local ret = {next = fnext or f.noop}
|
||||||
return {
|
|
||||||
all = f.all,
|
for k, v in pairs(f) do
|
||||||
any = f.any,
|
ret[k] = v
|
||||||
arg = f.arg,
|
end
|
||||||
call = f.call,
|
|
||||||
chain = f.chain,
|
return ret
|
||||||
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,
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Creates an enumeration.
|
--- Creates an enumeration.
|
||||||
---@type FFrom
|
---@generic K, V
|
||||||
|
---@param iter 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(iter: number, fpairs?: number, step?: number): F | { [number]: number }
|
||||||
|
---@overload fun(iter: string): (fun(table: { [string]: V }): V)
|
||||||
|
---@overload fun(iter: fun(): K, V): F | { [K]: V }
|
||||||
|
---@overload fun(iter: false): fun(): false
|
||||||
|
---@overload fun(iter: true): fun(): true
|
||||||
|
---@overload fun(iter: nil): F
|
||||||
function f.from(iter, fpairs, step)
|
function f.from(iter, fpairs, step)
|
||||||
if iter == nil then
|
if iter == true then
|
||||||
return none
|
|
||||||
elseif iter == true then
|
|
||||||
return f.tru
|
return f.tru
|
||||||
elseif iter == false then
|
elseif iter == false then
|
||||||
return f.fals
|
return f.fals
|
||||||
|
elseif iter == nil then
|
||||||
|
return none
|
||||||
end
|
end
|
||||||
|
|
||||||
local t = type(iter)
|
local t = type(iter)
|
||||||
|
|
||||||
if t == "string" then
|
if t == "string" then
|
||||||
return f.indices(iter)
|
return f.index(iter)
|
||||||
elseif t == "number" then
|
elseif t == "number" then
|
||||||
local ik, is, start = 0, step or 1, fpairs and iter or 1
|
local ik, is, start = 0, step or 1, fpairs and iter or 1
|
||||||
|
|
||||||
|
|
@ -556,10 +157,10 @@ function f.from(iter, fpairs, step)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
else
|
else
|
||||||
local next, tbl, k, v = autopairs(iter, type(fpairs) == "function" and fpairs or nil)
|
local next, context, k, v = autopairs(iter, fpairs)
|
||||||
|
|
||||||
return f.new(function()
|
return f.new(function()
|
||||||
k, v = next(tbl, k)
|
k, v = next(context, k)
|
||||||
return k, v
|
return k, v
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
@ -571,14 +172,12 @@ end
|
||||||
---@return F|{ [K]: V }
|
---@return F|{ [K]: V }
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
function f:concat(...)
|
function f:concat(...)
|
||||||
self = f.isf(self) and self or f.from(self)
|
|
||||||
local fsi = 0
|
local fsi = 0
|
||||||
local fs = {...}
|
local fs = {...}
|
||||||
local sum, last = 0, 0
|
local sum, last = 0, 0
|
||||||
|
|
||||||
for i = 1, #fs do
|
for i = 1, #fs do
|
||||||
local s = fs[i]
|
fs[i] = is_f(fs[i]) and fs[i] or f.from(fs[i])
|
||||||
fs[i] = f.isf(s) and s or f.from(s)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return f.new(function()
|
return f.new(function()
|
||||||
|
|
@ -606,34 +205,14 @@ function f:concat(...)
|
||||||
end)
|
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
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
---@generic K, V, U
|
---@generic K, V, U
|
||||||
---@param self F|{ [K]: V }
|
---@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 }
|
---@return F|{ [K]: U }
|
||||||
---@overload fun(self: F|{ [K]: V }, func: string): F|{ [K]: U }
|
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
|
---@overload fun(self: F|{ [K]: V }, func: string): F|{ [K]: U }
|
||||||
function f:map(func)
|
function f:map(func)
|
||||||
self = f.isf(self) and self or f.from(self)
|
func = type(func) == "string" and f.index(func) or func
|
||||||
func = autofunc(func)
|
|
||||||
|
|
||||||
return f.new(function()
|
return f.new(function()
|
||||||
local k, v = self:next()
|
local k, v = self:next()
|
||||||
|
|
@ -646,20 +225,17 @@ end
|
||||||
|
|
||||||
---@generic K, V, U
|
---@generic K, V, U
|
||||||
---@param self F|{ [K]: V }
|
---@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)
|
---@param fpairs? fun(t: table<K, V>): (fun(table: table<K, V>, index?: K): K, V)
|
||||||
---@return F|{ [K]: U }
|
---@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
|
---@nodiscard
|
||||||
|
---@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 }
|
||||||
function f:flatmap(func, fpairs)
|
function f:flatmap(func, fpairs)
|
||||||
self = f.isf(self) and self or f.from(self)
|
|
||||||
-- local i = 0
|
-- local i = 0
|
||||||
local vt, vk, vp
|
local vt, vk, vv, vp
|
||||||
func = autofunc(func)
|
func = type(func) == "string" and f.index(func) or func
|
||||||
|
|
||||||
return f.new(function()
|
return f.new(function()
|
||||||
local vv
|
|
||||||
|
|
||||||
if vk then
|
if vk then
|
||||||
vk, vv = vp(vt, vk)
|
vk, vv = vp(vt, vk)
|
||||||
|
|
||||||
|
|
@ -699,14 +275,13 @@ end
|
||||||
|
|
||||||
---@generic K, V
|
---@generic K, V
|
||||||
---@param self F|{ [K]: V }
|
---@param self F|{ [K]: V }
|
||||||
---@param func fun(v: V, k: K): boolean
|
---@param func F|fun(v: V, k: K): boolean
|
||||||
---@param is? any
|
---@param is? any
|
||||||
---@return F|{ [K]: V }
|
---@return F|{ [K]: V }
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
---@overload fun(self: F|{ [K]: V }, func: string, is?: any): F|{ [K]: V }
|
---@overload fun(self: F|{ [K]: V }, func: string, is?: any): F|{ [K]: V }
|
||||||
function f:where(func, is)
|
function f:where(func, is)
|
||||||
self = f.isf(self) and self or f.from(self)
|
func = type(func) == "string" and f.index(func) or func
|
||||||
func = autofunc(func)
|
|
||||||
|
|
||||||
return f.new(function()
|
return f.new(function()
|
||||||
local k, v
|
local k, v
|
||||||
|
|
@ -738,7 +313,6 @@ end
|
||||||
---@return F|{ [integer]: K }
|
---@return F|{ [integer]: K }
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
function f:keys()
|
function f:keys()
|
||||||
self = f.isf(self) and self or f.from(self)
|
|
||||||
local i = 0
|
local i = 0
|
||||||
|
|
||||||
return f.new(function()
|
return f.new(function()
|
||||||
|
|
@ -756,7 +330,6 @@ end
|
||||||
---@return F|{ [integer]: V }
|
---@return F|{ [integer]: V }
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
function f:values()
|
function f:values()
|
||||||
self = f.isf(self) and self or f.from(self)
|
|
||||||
local i = 0
|
local i = 0
|
||||||
|
|
||||||
return f.new(function()
|
return f.new(function()
|
||||||
|
|
@ -774,8 +347,6 @@ end
|
||||||
---@return F|{ [V]: K }
|
---@return F|{ [V]: K }
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
function f:swap()
|
function f:swap()
|
||||||
self = f.isf(self) and self or f.from(self)
|
|
||||||
|
|
||||||
return f.new(function()
|
return f.new(function()
|
||||||
local k, v = self:next()
|
local k, v = self:next()
|
||||||
|
|
||||||
|
|
@ -785,28 +356,6 @@ function f:swap()
|
||||||
end)
|
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
|
---@generic K, V
|
||||||
---@param self F|{ [K]: V }
|
---@param self F|{ [K]: V }
|
||||||
---@param skip? integer
|
---@param skip? integer
|
||||||
|
|
@ -814,8 +363,6 @@ end
|
||||||
---@return F|{ [K]: V }
|
---@return F|{ [K]: V }
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
function f:slice(skip, take)
|
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
|
if (not skip or skip <= 0) and not take then
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
@ -847,7 +394,6 @@ end
|
||||||
---@return F|{ [K]: V }
|
---@return F|{ [K]: V }
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
function f:skip(n)
|
function f:skip(n)
|
||||||
self = f.isf(self) and self or f.from(self)
|
|
||||||
return self:slice(n)
|
return self:slice(n)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -857,7 +403,6 @@ end
|
||||||
---@return F|{ [K]: V }
|
---@return F|{ [K]: V }
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
function f:take(n)
|
function f:take(n)
|
||||||
self = f.isf(self) and self or f.from(self)
|
|
||||||
return self:slice(0, n)
|
return self:slice(0, n)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -869,7 +414,6 @@ end
|
||||||
---@overload fun(self: F|{ [K]: V }, seed: fun(a: A, v: V, k: K): A): A
|
---@overload fun(self: F|{ [K]: V }, seed: fun(a: A, v: V, k: K): A): A
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
function f:fold(seed, func)
|
function f:fold(seed, func)
|
||||||
self = f.isf(self) and self or f.from(self)
|
|
||||||
local k, v
|
local k, v
|
||||||
|
|
||||||
if not func then
|
if not func then
|
||||||
|
|
@ -894,13 +438,12 @@ end
|
||||||
|
|
||||||
---@generic K, V
|
---@generic K, V
|
||||||
---@param self F|{ [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
|
---@return boolean|V
|
||||||
---@overload fun(self: F|{ [K]: V }, func: string?): boolean|V
|
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
|
---@overload fun(self: F|{ [K]: V }, func: string): boolean|V
|
||||||
function f:any(func)
|
function f:any(func)
|
||||||
self = f.isf(self) and self or f.from(self)
|
func = type(func) == "string" and f.index(func) or func
|
||||||
func = autofunc(func)
|
|
||||||
|
|
||||||
for k, v in self.next do
|
for k, v in self.next do
|
||||||
if not func or func(v, k) then
|
if not func or func(v, k) then
|
||||||
|
|
@ -913,13 +456,12 @@ end
|
||||||
|
|
||||||
---@generic K, V
|
---@generic K, V
|
||||||
---@param self F|{ [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
|
---@return boolean|V
|
||||||
---@overload fun(self: F|{ [K]: V }, func: string?): boolean|V
|
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
|
---@overload fun(self: F|{ [K]: V }, func: string): boolean|V
|
||||||
function f:all(func)
|
function f:all(func)
|
||||||
self = f.isf(self) and self or f.from(self)
|
func = type(func) == "string" and f.index(func) or func
|
||||||
func = autofunc(func)
|
|
||||||
|
|
||||||
for k, v in self.next do
|
for k, v in self.next do
|
||||||
if not func or not func(v, k) then
|
if not func or not func(v, k) then
|
||||||
|
|
@ -932,14 +474,13 @@ end
|
||||||
|
|
||||||
---@generic K, V
|
---@generic K, V
|
||||||
---@param self F|{ [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
|
---@return integer
|
||||||
---@overload fun(self: F|{ [K]: V }, func: string): integer
|
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
|
---@overload fun(self: F|{ [K]: V }, func: string): integer
|
||||||
function f:count(func)
|
function f:count(func)
|
||||||
self = f.isf(self) and self or f.from(self)
|
|
||||||
func = autofunc(func)
|
|
||||||
local ret = 0
|
local ret = 0
|
||||||
|
func = type(func) == "string" and f.index(func) or func
|
||||||
|
|
||||||
for k, v in self.next do
|
for k, v in self.next do
|
||||||
if not func or func(v, k) then
|
if not func or func(v, k) then
|
||||||
|
|
@ -950,39 +491,11 @@ function f:count(func)
|
||||||
return ret
|
return ret
|
||||||
end
|
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
|
---@generic K, V
|
||||||
---@param self F|{ [K]: V }
|
---@param self F|{ [K]: V }
|
||||||
---@return string
|
---@return string
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
function f:string()
|
function f:string()
|
||||||
self = f.isf(self) and self or f.from(self)
|
|
||||||
local k, v = self:next()
|
local k, v = self:next()
|
||||||
|
|
||||||
if k == nil then
|
if k == nil then
|
||||||
|
|
@ -1007,7 +520,6 @@ end
|
||||||
---@return { [K]: V }
|
---@return { [K]: V }
|
||||||
---@nodiscard
|
---@nodiscard
|
||||||
function f:table()
|
function f:table()
|
||||||
self = f.isf(self) and self or f.from(self)
|
|
||||||
local ret = {}
|
local ret = {}
|
||||||
|
|
||||||
for k, v in self.next do
|
for k, v in self.next do
|
||||||
|
|
@ -1019,10 +531,8 @@ end
|
||||||
|
|
||||||
---@generic K, V
|
---@generic K, V
|
||||||
---@param self F|{ [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)
|
function f:each(func)
|
||||||
self = f.isf(self) and self or f.from(self)
|
|
||||||
|
|
||||||
for k, v in self.next do
|
for k, v in self.next do
|
||||||
if func then
|
if func then
|
||||||
func(v, k)
|
func(v, k)
|
||||||
|
|
@ -1032,11 +542,4 @@ end
|
||||||
|
|
||||||
none = f.new()
|
none = f.new()
|
||||||
|
|
||||||
---@type F|FFrom
|
return f.from
|
||||||
local ret = (setmetatable or f.const(f.from))(f, {
|
|
||||||
__call = function(_, ...)
|
|
||||||
return f.from(...)
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
|
|
||||||
return ret
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
local function protect(fun)
|
||||||
return function()
|
return function()
|
||||||
local res, ret = pcall(fun)
|
local res, ret = pcall(fun)
|
||||||
|
|
@ -92,83 +6,76 @@ local function protect(fun)
|
||||||
sendErrorMessage(tostring(ret), "Roland")
|
sendErrorMessage(tostring(ret), "Roland")
|
||||||
end
|
end
|
||||||
|
|
||||||
return not res or ret ~= false and not (SMODS.current_mod and ret ~= true)
|
return not res or ret ~= false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function protect_ev(fun)
|
local function protect_ev(fun)
|
||||||
if type(fun) == "function" then
|
if type(fun) == "table" then
|
||||||
return Event {func = protect(fun)}
|
fun.func = protect(fun.func)
|
||||||
elseif type(fun) ~= "table" then
|
fun = getmetatable(fun) == Event and fun or Event(fun)
|
||||||
error("Expected a function or table, got a " .. type(fun), 3)
|
elseif type(fun) == "function" then
|
||||||
elseif type(fun.is) == "function" and fun:is(SMODS.GameObject) then
|
fun = Event {func = protect(fun)}
|
||||||
return Event {
|
else
|
||||||
blocking = false,
|
error("Expected a function or event, got a " .. type(fun), 3)
|
||||||
no_delete = true,
|
|
||||||
func = protect(function()
|
|
||||||
if not Bakery_API or not Bakery_API.credit then
|
|
||||||
return false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
Bakery_API.credit(fun)
|
return fun
|
||||||
end),
|
end
|
||||||
}
|
|
||||||
else
|
if false then
|
||||||
fun.func = protect(fun.func or fun[1])
|
-- This allows for better type inference.
|
||||||
return getmetatable(fun) == Event and fun or Event(fun)
|
SMODS.Mods.Roland.config = require "config"
|
||||||
|
|
||||||
|
-- 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
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local f = assert(SMODS.load_file "src/lib/funky.lua")() or require "lib.funky"
|
||||||
|
|
||||||
--- Queues an event to be run.
|
--- Queues an event to be run.
|
||||||
--- Note that events added this way implicitly `return true` unless you explicitly `return false`.
|
--- Note that events added this way implicitly `return true` unless you explicitly `return false`, unlike the vanilla ones.
|
||||||
--- For `front`; boolean `true` to add the event to the front of the queue, rather than the end.
|
--- @param fun (fun():false|nil)|Event The event or a function to run turn into an event.
|
||||||
--- @generic T: fun():boolean?|Event
|
--- @param front boolean|nil `true` to add the event to the front of the queue, rather than the end.
|
||||||
--- @param fun T|Event|{front?: boolean} The table or function to turn into an event.
|
local function q(fun, front)
|
||||||
--- @return T fun
|
G.E_MANAGER:add_event(protect_ev(fun), nil, front)
|
||||||
local function q(fun)
|
|
||||||
local ev = protect_ev(fun)
|
|
||||||
G.E_MANAGER:add_event(ev, nil, ev.front)
|
|
||||||
return fun
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Determines if a center is allowed to be usable.
|
--- Determines if a center is allowed to be usable.
|
||||||
---@return boolean
|
---@return boolean
|
||||||
local function u()
|
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.HAND_PLAYED and
|
||||||
G.STATE ~= G.STATES.DRAW_TO_HAND and
|
G.STATE ~= G.STATES.DRAW_TO_HAND and
|
||||||
G.STATE ~= G.STATES.PLAY_TAROT)
|
G.STATE ~= G.STATES.PLAY_TAROT)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Creates one or more cards.
|
return {f, q, u}
|
||||||
---@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,
|
|
||||||
})}
|
|
||||||
|
|
|
||||||
98
src/main.lua
|
|
@ -1,97 +1,73 @@
|
||||||
local qol = assert(SMODS.load_file "src/lib/shared.lua")() or require "lib.shared"
|
local qol = assert(SMODS.load_file "src/lib/shared.lua")() or require "lib.shared"
|
||||||
local animated = SMODS.current_mod.config.animated_icon
|
local f, q = unpack(qol)
|
||||||
SMODS.current_mod.qol = qol
|
|
||||||
local f, q = qol[1], qol[2]
|
|
||||||
|
|
||||||
q {
|
f {"challenge", "spectral", "edition", "tweaks", "blind", "charm", "joker", "back", "seal"}:each(function(v)
|
||||||
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)
|
|
||||||
assert(SMODS.load_file("src/" .. v .. ".lua"))(qol)
|
assert(SMODS.load_file("src/" .. v .. ".lua"))(qol)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
local _ = Balatest and f {"joker", "blind", "spectral"}:each(function(v)
|
if _G["Balatest"] then
|
||||||
|
f {"joker", "blind", "spectral"}:each(function(v)
|
||||||
assert(SMODS.load_file("src/tests/" .. v .. ".tests.lua"))(qol)
|
assert(SMODS.load_file("src/tests/" .. v .. ".tests.lua"))(qol)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
local function realign(tbl)
|
|
||||||
f(tbl):where(function(v, k)
|
|
||||||
if k == "align" and type(v) == "string" then
|
|
||||||
tbl[k] = "tr"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return k ~= "nodes" and type(v) == "table"
|
q(function()
|
||||||
end):each(realign)
|
---@type table<string, {name: string, fg: table, bg: table}>
|
||||||
|
local contributors, mods = Bakery_API.contributors, SMODS.Mods
|
||||||
|
|
||||||
return tbl
|
contributors.Roland_aster = {
|
||||||
|
name = "asterSSH",
|
||||||
|
fg = HEX "f8f8f2ff",
|
||||||
|
bg = HEX "bd93f9ff",
|
||||||
|
}
|
||||||
|
|
||||||
|
contributors.Roland_char = {
|
||||||
|
name = "char (@irregulester)",
|
||||||
|
fg = HEX "f8f8f2ff",
|
||||||
|
bg = HEX "ff79c6ff",
|
||||||
|
}
|
||||||
|
|
||||||
|
if mods.DebugPlus and mods.Roland.config.import_funky then
|
||||||
|
_G.f, _G.q, _G.u = unpack(qol)
|
||||||
end
|
end
|
||||||
|
end, true)
|
||||||
|
|
||||||
local function toggle(id)
|
local function toggle(id)
|
||||||
return realign(create_toggle {
|
return create_toggle {
|
||||||
label = localize {type = "variable", key = "b_Roland_" .. id},
|
label = localize {type = "variable", key = "b_Roland_" .. id},
|
||||||
ref_table = SMODS.Mods.Roland.config,
|
ref_table = SMODS.Mods.Roland.config,
|
||||||
ref_value = id,
|
ref_value = id,
|
||||||
scale = 1.5,
|
scale = 1.5,
|
||||||
})
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
SMODS.Atlas {
|
SMODS.Atlas {
|
||||||
px = 256,
|
px = 256,
|
||||||
py = 256,
|
py = 256,
|
||||||
key = "modicon",
|
key = "modicon",
|
||||||
fps = animated and 12 or nil,
|
path = "icon.png",
|
||||||
frames = animated and 12 or nil,
|
|
||||||
path = animated and "icon.png" or "unicon.png",
|
|
||||||
atlas_table = animated and "ANIMATION_ATLAS" or "ASSET_ATLAS",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function SMODS.current_mod.config_tab()
|
function SMODS.current_mod.config_tab()
|
||||||
return {
|
return {
|
||||||
n = G.UIT.ROOT,
|
n = G.UIT.ROOT,
|
||||||
config = {minw = 1, minh = 1, align = "tr", padding = 0.1, colour = G.C.BLACK},
|
config = {minw = 1, minh = 1, align = "tl", padding = 0.1, colour = G.C.BLACK},
|
||||||
nodes = {
|
nodes = {{
|
||||||
{
|
|
||||||
n = G.UIT.C,
|
n = G.UIT.C,
|
||||||
config = {minw = 1, minh = 1, align = "tr", padding = 0.1, colour = G.C.CLEAR},
|
config = {minw = 1, minh = 1, align = "tl", padding = 0.1, colour = G.C.CLEAR},
|
||||||
nodes = {
|
nodes = {
|
||||||
toggle "animated_icon",
|
|
||||||
toggle "cool_phones",
|
|
||||||
toggle "vitriol",
|
|
||||||
toggle "equinox_assist",
|
|
||||||
G.P_CENTERS.c_Bakery_Scribe and toggle "scribable_basket",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
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 "illusion_seal",
|
||||||
toggle "no_wild_debuff",
|
toggle "no_wild_debuff",
|
||||||
|
toggle "no_highlight_limit",
|
||||||
|
_G["Talisman"] and toggle "harsh_ante_scaling",
|
||||||
|
toggle "fusable_escapey",
|
||||||
|
toggle "equinox_assist",
|
||||||
SMODS.Mods.DebugPlus and toggle "import_funky",
|
SMODS.Mods.DebugPlus and toggle "import_funky",
|
||||||
Talisman and toggle "harsh_ante_scaling",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
}},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function SMODS.current_mod.optional_features()
|
||||||
|
return {cardareas = {deck = true, unscored = true}}
|
||||||
|
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 {
|
SMODS.Atlas {
|
||||||
px = 71,
|
px = 71,
|
||||||
|
|
@ -11,9 +11,8 @@ SMODS.Seal {
|
||||||
key = "glass",
|
key = "glass",
|
||||||
atlas = "seal",
|
atlas = "seal",
|
||||||
pos = {x = 0, y = 0},
|
pos = {x = 0, y = 0},
|
||||||
attributes = {"destroy_card", "tag"},
|
|
||||||
badge_colour = HEX "a6a6a6ff",
|
badge_colour = HEX "a6a6a6ff",
|
||||||
pronouns = "they_them",
|
pronouns = "he_him",
|
||||||
calculate = function(_, card, context)
|
calculate = function(_, card, context)
|
||||||
local function eq(v)
|
local function eq(v)
|
||||||
return v == card
|
return v == card
|
||||||
|
|
|
||||||
204
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 spectral = (function()
|
||||||
local x = 0
|
local x = 0
|
||||||
|
|
@ -6,13 +8,19 @@ local spectral = (function()
|
||||||
---@param tbl SMODS.Consumable|{artist?: string}
|
---@param tbl SMODS.Consumable|{artist?: string}
|
||||||
---@return SMODS.Consumable
|
---@return SMODS.Consumable
|
||||||
return function(tbl)
|
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.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
|
x = x + 1
|
||||||
return q(SMODS.Consumable(tbl))
|
|
||||||
|
q(function()
|
||||||
|
Bakery_API.credit(ret)
|
||||||
|
end)
|
||||||
|
|
||||||
|
return ret
|
||||||
end
|
end
|
||||||
end)()
|
end)()
|
||||||
|
|
||||||
|
|
@ -30,140 +38,122 @@ SMODS.Sound {
|
||||||
|
|
||||||
spectral {
|
spectral {
|
||||||
key = "afterimage",
|
key = "afterimage",
|
||||||
pronouns = "she_they",
|
pronouns = "he_they",
|
||||||
artist = "aster",
|
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}
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
|
||||||
|
q {
|
||||||
|
delay = 0.1,
|
||||||
|
func = function()
|
||||||
|
G.hand:change_size(card.ability.extra.hand)
|
||||||
|
Bakery_API.unhighlight_all()
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
spectral {
|
||||||
|
key = "coolheaded",
|
||||||
|
config = {extra = {amount = 1}},
|
||||||
|
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)
|
||||||
|
return u() and f(G.jokers.highlighted):concat(Bakery_API.get_highlighted()):count(function(v)
|
||||||
|
return not v.edition
|
||||||
|
end) == card.ability.extra.amount
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
|
||||||
|
spectral {
|
||||||
|
key = "dual",
|
||||||
|
pronouns = "they_them",
|
||||||
config = {extra = {amount = 2}},
|
config = {extra = {amount = 2}},
|
||||||
attributes = {"seal", "modify_card", "spectral"},
|
|
||||||
loc_vars = function(_, _, card)
|
loc_vars = function(_, _, card)
|
||||||
return {vars = {card.ability.extra.amount}}
|
return {vars = {card.ability.extra.amount}}
|
||||||
end,
|
end,
|
||||||
can_use = function()
|
can_use = function()
|
||||||
return next(G.hand.cards) and u()
|
return u() and #G.hand.cards > 0
|
||||||
end,
|
end,
|
||||||
use = function(_, card)
|
use = function(_, card, _)
|
||||||
local cards = f(G.hand.cards):table()
|
local cards = f(G.hand.cards):table()
|
||||||
pseudoshuffle(cards, pseudoseed "RolandDual")
|
pseudoshuffle(cards, pseudoseed "RolandDual")
|
||||||
|
|
||||||
f(cards):take(card.ability.extra.amount):each(function(v)
|
f(cards):take(card.ability.extra.amount):each(function(v)
|
||||||
local seal = SMODS.poll_seal {
|
local seal
|
||||||
guaranteed = true,
|
|
||||||
options = f(G.P_SEALS):keys():where(f.nq "Roland_glass"):values():table(),
|
|
||||||
}
|
|
||||||
|
|
||||||
local _ = not card.Roland_immediate and q {
|
for _ = 1, 31 do
|
||||||
delay = 0.5,
|
seal = SMODS.poll_seal {guaranteed = true}
|
||||||
trigger = "after",
|
|
||||||
func = function()
|
if seal ~= "Roland_glass" then
|
||||||
v:set_seal(seal, nil, true)
|
break
|
||||||
end,
|
end
|
||||||
} or v:set_seal(seal, true, true)
|
end
|
||||||
|
|
||||||
|
v:set_seal(seal == "Roland_glass" and "Red" or seal)
|
||||||
end)
|
end)
|
||||||
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 {
|
spectral {
|
||||||
key = "primal",
|
key = "mirror",
|
||||||
pronouns = "he_him",
|
pronouns = "he_him",
|
||||||
artist = "aster",
|
config = {extra = {amount = 1}},
|
||||||
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"},
|
|
||||||
loc_vars = function(_, info_queue, card)
|
loc_vars = function(_, info_queue, card)
|
||||||
table.insert(info_queue, G.P_SEALS.Roland_glass)
|
table.insert(info_queue, G.P_SEALS.Roland_glass)
|
||||||
return {vars = {card.ability.extra.amount}}
|
return {vars = {card.ability.extra.amount}}
|
||||||
end,
|
end,
|
||||||
can_use = function(_, card)
|
can_use = function(_, card)
|
||||||
local count = #Bakery_API.get_highlighted()
|
return u() and #Bakery_API.get_highlighted() == card.ability.extra.amount
|
||||||
return u() and count > 0 and count <= card.ability.extra.amount
|
|
||||||
end,
|
end,
|
||||||
use = function()
|
use = function(_, _, _)
|
||||||
f(Bakery_API.get_highlighted()):each(function(v)
|
f(Bakery_API.get_highlighted()):each(function(v)
|
||||||
v:set_seal "Roland_glass"
|
v:set_seal "Roland_glass"
|
||||||
end)
|
end)
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
spectral {
|
local void = spectral {
|
||||||
key = "void",
|
key = "void",
|
||||||
pronouns = "it_its",
|
pronouns = "it_its",
|
||||||
artist = "aster",
|
artist = "aster",
|
||||||
hidden = true,
|
|
||||||
soul_rate = 0.003,
|
soul_rate = 0.003,
|
||||||
soul_set = "Spectral",
|
soul_set = "Spectral",
|
||||||
config = {extra = {amount = 2}},
|
config = {extra = {amount = 2}},
|
||||||
attributes = {"destroy_card", "generation", "spectral"},
|
|
||||||
loc_vars = function(_, info_queue, card)
|
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)
|
table.insert(info_queue, G.P_CENTERS.c_cryptid)
|
||||||
return {vars = {card.ability.extra.amount}}
|
return {vars = {card.ability.extra.amount}}
|
||||||
end,
|
end,
|
||||||
can_use = function()
|
can_use = function()
|
||||||
return next(G.playing_cards) and u()
|
return #G.playing_cards > 1 and not not u()
|
||||||
end,
|
end,
|
||||||
use = function(_, card)
|
use = function(_, card)
|
||||||
local function destructible(v)
|
local function destructible(v)
|
||||||
|
|
@ -189,15 +179,25 @@ spectral {
|
||||||
f(cards):each(destroy)
|
f(cards):each(destroy)
|
||||||
f(G.jokers.cards):each(calculate_joker)
|
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")
|
local cryptid = create_card(nil, G.consumeables, nil, nil, nil, nil, "c_cryptid", "void")
|
||||||
cryptid:set_edition({negative = true}, true)
|
cryptid:set_edition({negative = true}, true)
|
||||||
cryptid:add_to_deck()
|
cryptid:add_to_deck()
|
||||||
G.consumeables:emplace(cryptid)
|
G.consumeables:emplace(cryptid)
|
||||||
end)
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
play_sound("Roland_void", 1, 0.7)
|
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,
|
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
|
if not Balatest then
|
||||||
return
|
return
|
||||||
|
|
@ -68,7 +68,8 @@ Balatest.TestPlay {
|
||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
Balatest.wait_for_input(G.STATES.ROUND_EVAL)
|
Balatest.wait_for_input()
|
||||||
|
Balatest.wait()
|
||||||
end,
|
end,
|
||||||
assert = function()
|
assert = function()
|
||||||
Balatest.assert_chips(2720)
|
Balatest.assert_chips(2720)
|
||||||
|
|
@ -191,9 +192,9 @@ Balatest.TestPlay {
|
||||||
}
|
}
|
||||||
|
|
||||||
Balatest.TestPlay {
|
Balatest.TestPlay {
|
||||||
category = {"blind", "mitotic"},
|
category = {"blind", "xerox"},
|
||||||
name = "mitotic",
|
name = "xerox",
|
||||||
blind = "bl_Roland_mitotic",
|
blind = "bl_Roland_xerox",
|
||||||
execute = function()
|
execute = function()
|
||||||
Balatest.discard {"2S"}
|
Balatest.discard {"2S"}
|
||||||
end,
|
end,
|
||||||
|
|
@ -203,9 +204,9 @@ Balatest.TestPlay {
|
||||||
}
|
}
|
||||||
|
|
||||||
Balatest.TestPlay {
|
Balatest.TestPlay {
|
||||||
category = {"blind", "mitotic"},
|
category = {"blind", "xerox"},
|
||||||
name = "mitotic_disabled",
|
name = "xerox_disabled",
|
||||||
blind = "bl_Roland_mitotic",
|
blind = "bl_Roland_xerox",
|
||||||
jokers = {"j_chicot"},
|
jokers = {"j_chicot"},
|
||||||
execute = function()
|
execute = function()
|
||||||
Balatest.discard {"2S"}
|
Balatest.discard {"2S"}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,330 @@ if not Balatest then
|
||||||
return
|
return
|
||||||
end
|
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 {
|
Balatest.TestPlay {
|
||||||
category = {"joker", "martingale"},
|
category = {"joker", "martingale"},
|
||||||
name = "martingale_oops",
|
name = "martingale_oops",
|
||||||
|
|
@ -10,7 +334,7 @@ Balatest.TestPlay {
|
||||||
Balatest.play_hand {"2S"}
|
Balatest.play_hand {"2S"}
|
||||||
end,
|
end,
|
||||||
assert = function()
|
assert = function()
|
||||||
Balatest.assert_chips(7)
|
Balatest.assert_chips(7 * 2)
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -23,6 +347,6 @@ Balatest.TestPlay {
|
||||||
Balatest.play_hand {"2S"}
|
Balatest.play_hand {"2S"}
|
||||||
end,
|
end,
|
||||||
assert = function()
|
assert = function()
|
||||||
Balatest.assert_chips(1 / 0)
|
Balatest.assert_chips(7 * math.pow(2, 32))
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,22 @@ if not Balatest then
|
||||||
return
|
return
|
||||||
end
|
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 {
|
Balatest.TestPlay {
|
||||||
category = {"spectral", "void"},
|
category = {"spectral", "void"},
|
||||||
name = "spectral",
|
name = "spectral",
|
||||||
|
|
|
||||||
144
src/tweaks.lua
|
|
@ -1,40 +1,52 @@
|
||||||
local f, q = (... or require "lib.shared")[1], (... or require "lib.shared")[2]
|
local f, q = unpack(... or require "lib.shared")
|
||||||
SMODS.Joker:take_ownership("joker", {cost = 1}, true)
|
|
||||||
local orig_set_debuff = Card.set_debuff
|
|
||||||
|
|
||||||
function Card:set_debuff(should_debuff, ...)
|
SMODS.Joker:take_ownership("joker", {cost = 1}, true)
|
||||||
if self.ability.Roland_crimson ~= nil then
|
local orig_can_highlight = CardArea.can_highlight
|
||||||
self.ability.Roland_crimson = not not should_debuff
|
local orig_set_debuff = Card.set_debuff
|
||||||
return
|
local orig_highlight = Card.highlight
|
||||||
|
local orig_copy_card = copy_card
|
||||||
|
|
||||||
|
function CardArea:can_highlight(...)
|
||||||
|
if self ~= G.consumeables or not SMODS.Mods.Roland.config.no_highlight_limit then
|
||||||
|
return orig_can_highlight(self, ...)
|
||||||
end
|
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
|
||||||
|
|
||||||
|
function Card:set_debuff(...)
|
||||||
|
if self.config and
|
||||||
|
self.config.center_key == "m_wild" and
|
||||||
|
SMODS.Mods.Roland.config.no_wild_debuff then
|
||||||
self.debuff = false
|
self.debuff = false
|
||||||
else
|
else
|
||||||
orig_set_debuff(self, should_debuff, ...)
|
orig_set_debuff(self, ...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Card:highlight(is_highlighted, ...)
|
||||||
|
self.highlighted = is_highlighted
|
||||||
|
|
||||||
|
if not G.CONTROLLER.HID.controller or not SMODS.Mods.Roland.config.no_highlight_limit then
|
||||||
|
return orig_highlight(self, is_highlighted, ...)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local orig_use_consumeable = Card.use_consumeable
|
local orig_use_consumeable = Card.use_consumeable
|
||||||
|
|
||||||
function Card:use_consumeable(area, copier, ...)
|
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}
|
local seal_spectrals = {["Deja Vu"] = true, Medium = true, Talisman = true, Trance = true}
|
||||||
|
|
||||||
if not seal_spectrals[self.ability.name] then
|
if not seal_spectrals[self.ability.name] then
|
||||||
return orig_use_consumeable(self, area, copier, ...)
|
return orig_use_consumeable(self, area, copier, ...)
|
||||||
end
|
end
|
||||||
|
|
||||||
local card = copier or self
|
|
||||||
|
|
||||||
f(Bakery_API.get_highlighted()):each(function(v)
|
f(Bakery_API.get_highlighted()):each(function(v)
|
||||||
q(function()
|
q(function()
|
||||||
play_sound "tarot1"
|
play_sound "tarot1"
|
||||||
|
local card = (copier or self)
|
||||||
card:juice_up(0.3, 0.5)
|
card:juice_up(0.3, 0.5)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
@ -47,43 +59,42 @@ function Card:use_consumeable(area, copier, ...)
|
||||||
}
|
}
|
||||||
end)
|
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
|
end
|
||||||
|
|
||||||
local orig_use_card = G.FUNCS.use_card
|
function copy_card(other, new_card, ...)
|
||||||
|
local ret = orig_copy_card(other, new_card, ...)
|
||||||
|
|
||||||
function G.FUNCS.use_card(e, ...)
|
if new_card and new_card.edition and new_card.edition.key == "e_negative" then
|
||||||
local ref = e.config.ref_table or {}
|
--- Fixes an issue where using 'c_death' will make negative
|
||||||
local consumeable = (ref.ability or {}).consumeable or {}
|
--- cards do the inverse of what they're supposed to do.
|
||||||
|
local ability = new_card.ability
|
||||||
if not SMODS.Mods.Roland.config.faster_planets or
|
ability.card_limit = math.max(ability.card_limit, 1)
|
||||||
(not consumeable.hand_type and not consumeable.hand_types) then
|
|
||||||
return orig_use_card(e, ...)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local normal = G.STATE == G.STATES.SHOP or
|
return ret
|
||||||
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
|
end
|
||||||
|
|
||||||
G.GAME.pack_choices = G.GAME.pack_choices - 1
|
q(function()
|
||||||
local _ = G.GAME.pack_choices <= 0 and G.FUNCS.end_consumeable()
|
local orig_can_highlight_area = Bakery_API.can_highlight_area
|
||||||
|
|
||||||
|
function Bakery_API.can_highlight_area(area, ...)
|
||||||
|
return (area == G.consumeables and
|
||||||
|
SMODS.Mods.Roland.config.no_highlight_limit) or
|
||||||
|
orig_can_highlight_area(area, ...)
|
||||||
end
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
local orig_create_card_for_shop = create_card_for_shop
|
local orig_create_card_for_shop = create_card_for_shop
|
||||||
|
|
||||||
function create_card_for_shop(...)
|
function create_card_for_shop(...)
|
||||||
|
---@type Card
|
||||||
local ret = orig_create_card_for_shop(...)
|
local ret = orig_create_card_for_shop(...)
|
||||||
|
|
||||||
if not SMODS.Mods.Roland.config.illusion_seal or
|
if not SMODS.Mods.Roland.config.illusion_seal or
|
||||||
|
|
@ -93,7 +104,11 @@ function create_card_for_shop(...)
|
||||||
return ret
|
return ret
|
||||||
end
|
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)
|
ret:set_seal(seal, true, true)
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
@ -101,44 +116,31 @@ end
|
||||||
local orig_get_blind_amount = get_blind_amount
|
local orig_get_blind_amount = get_blind_amount
|
||||||
|
|
||||||
---@param ante number
|
---@param ante number
|
||||||
---@return table|number
|
---@return number
|
||||||
local function blind(ante)
|
local function blind(ante)
|
||||||
return ante == 39 and 1e294 or (to_number or f.id)(orig_get_blind_amount(ante))
|
return ante == 39 and 1e294 or (_G["to_number"] or f().id)(orig_get_blind_amount(ante))
|
||||||
end
|
end
|
||||||
|
|
||||||
local function no_harsh_ante_scaling()
|
local function no_harsh_ante_scaling()
|
||||||
return not Talisman or not SMODS.Mods.Roland.config.harsh_ante_scaling
|
return not _G["Talisman"] or not SMODS.Mods.Roland.config.harsh_ante_scaling
|
||||||
end
|
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, ...)
|
function get_blind_amount(ante, ...)
|
||||||
local offset = 40
|
local loop = 39
|
||||||
|
|
||||||
if ante < offset or no_harsh_ante_scaling() then
|
if ante < loop or no_harsh_ante_scaling() then
|
||||||
return orig_get_blind_amount(ante, ...)
|
return orig_get_blind_amount(ante, ...)
|
||||||
end
|
end
|
||||||
|
|
||||||
local loop = 10
|
if (ante - 9) / 15 >= loop then
|
||||||
|
return 1 / 0
|
||||||
|
end
|
||||||
|
|
||||||
return f(SMODS.Mods.Roland.harsh_ante_scaling, f.revpairs):any(function(_, k)
|
--- @type { constants?: { TEN: table }, new: (fun(self: self, arr?: number[], sign?: number, noNormalize?: boolean): table), pow: (fun(x: number, y: number): number) }
|
||||||
return (ante - offset) / loop + 1 >= k
|
local big, rem = _G["Big"], (ante % loop) + 1
|
||||||
end)((ante - offset) % loop + 1)
|
|
||||||
|
return ante / 15 >= loop and big:new(f(blind(ante - (loop * 15))):map(f().const(10)):table()) or
|
||||||
|
(ante / 9 >= loop and big:new(f(ante / loop - 8):map(f().const(10)):concat {blind(rem)}:table()) or
|
||||||
|
(ante / 2 >= loop and big:new {blind(rem), ante / loop} or
|
||||||
|
(big.constants and big.constants.TEN or big:new {10}):pow(blind(rem))))
|
||||||
end
|
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,
|
|
||||||
}
|
|
||||||