├── .gitignore
├── assets
├── 1x
│ ├── backs.png
│ ├── cines.png
│ ├── icon.png
│ ├── tags.png
│ ├── boosters.png
│ ├── jokers.png
│ ├── sleeves.png
│ └── vouchers.png
├── 2x
│ ├── backs.png
│ ├── cines.png
│ ├── icon.png
│ ├── tags.png
│ ├── boosters.png
│ ├── jokers.png
│ ├── sleeves.png
│ └── vouchers.png
└── shaders
│ ├── ticket.fs
│ ├── ticket_negative.fs
│ └── ticket_polychrome.fs
├── config.lua
├── data
├── shaders.lua
├── consumables.lua
├── atlases.lua
├── jokers.lua
├── backs.lua
├── vouchers.lua
├── sleeves.lua
├── tags.lua
├── boosters.lua
├── joker_display.lua
└── cines.lua
├── README.md
├── Reverie.lua
├── localization
├── ko.lua
└── en-us.lua
├── lovely.toml
└── LICENSE
/.gitignore:
--------------------------------------------------------------------------------
1 | *.aseprite
--------------------------------------------------------------------------------
/assets/1x/backs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dvrp0/reverie/HEAD/assets/1x/backs.png
--------------------------------------------------------------------------------
/assets/1x/cines.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dvrp0/reverie/HEAD/assets/1x/cines.png
--------------------------------------------------------------------------------
/assets/1x/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dvrp0/reverie/HEAD/assets/1x/icon.png
--------------------------------------------------------------------------------
/assets/1x/tags.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dvrp0/reverie/HEAD/assets/1x/tags.png
--------------------------------------------------------------------------------
/assets/2x/backs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dvrp0/reverie/HEAD/assets/2x/backs.png
--------------------------------------------------------------------------------
/assets/2x/cines.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dvrp0/reverie/HEAD/assets/2x/cines.png
--------------------------------------------------------------------------------
/assets/2x/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dvrp0/reverie/HEAD/assets/2x/icon.png
--------------------------------------------------------------------------------
/assets/2x/tags.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dvrp0/reverie/HEAD/assets/2x/tags.png
--------------------------------------------------------------------------------
/assets/1x/boosters.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dvrp0/reverie/HEAD/assets/1x/boosters.png
--------------------------------------------------------------------------------
/assets/1x/jokers.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dvrp0/reverie/HEAD/assets/1x/jokers.png
--------------------------------------------------------------------------------
/assets/1x/sleeves.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dvrp0/reverie/HEAD/assets/1x/sleeves.png
--------------------------------------------------------------------------------
/assets/1x/vouchers.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dvrp0/reverie/HEAD/assets/1x/vouchers.png
--------------------------------------------------------------------------------
/assets/2x/boosters.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dvrp0/reverie/HEAD/assets/2x/boosters.png
--------------------------------------------------------------------------------
/assets/2x/jokers.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dvrp0/reverie/HEAD/assets/2x/jokers.png
--------------------------------------------------------------------------------
/assets/2x/sleeves.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dvrp0/reverie/HEAD/assets/2x/sleeves.png
--------------------------------------------------------------------------------
/assets/2x/vouchers.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dvrp0/reverie/HEAD/assets/2x/vouchers.png
--------------------------------------------------------------------------------
/config.lua:
--------------------------------------------------------------------------------
1 | return {
2 | jokerdisplay_compat = true,
3 | custom_morsel_compat = true,
4 | tag_packs_shop = false,
5 | crazy_packs_shop = false,
6 | cartomancer_compat = true
7 | }
--------------------------------------------------------------------------------
/data/shaders.lua:
--------------------------------------------------------------------------------
1 | Reverie.shaders = {
2 | {
3 | key = "ticket",
4 | path = "ticket.fs"
5 | },
6 | {
7 | key = "ticket_negative",
8 | path = "ticket_negative.fs"
9 | },
10 | {
11 | key = "ticket_polychrome",
12 | path = "ticket_polychrome.fs"
13 | }
14 | }
15 |
16 | for _, v in pairs(Reverie.shaders) do
17 | SMODS.Shader(v)
18 | end
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |

3 |
4 | # Reverie 🎥
5 |
6 | A movie-themed [Balatro](https://store.steampowered.com/app/2379780/Balatro/) expansion that focuses on providing special shops and various contents around it
7 |
8 | [](https://github.com/dvrp0/reverie/releases)
9 |
--------------------------------------------------------------------------------
/data/consumables.lua:
--------------------------------------------------------------------------------
1 | Reverie.consumables = {
2 | {
3 | key = "reverie",
4 | set = "Spectral",
5 | atlas = "Cine",
6 | order = 1,
7 | name = "Reverie",
8 | pos = {
9 | x = 1,
10 | y = 1
11 | },
12 | cost = 4,
13 | hidden = true,
14 | soul_set = "Cine",
15 | can_use = function (self, card)
16 | return G.STATE == G.STATES.SHOP and G.shop
17 | end,
18 | use = Reverie.use_cine
19 | }
20 | }
21 |
22 | for _, v in pairs(Reverie.consumables) do
23 | SMODS.Consumable(v)
24 | end
--------------------------------------------------------------------------------
/Reverie.lua:
--------------------------------------------------------------------------------
1 | --- STEAMODDED HEADER
2 | --- MOD_NAME: Reverie
3 | --- MOD_ID: Reverie
4 | --- MOD_AUTHOR: [DVRP]
5 | --- MOD_DESCRIPTION: A movie-themed expansion that focuses on providing special shops and various contents around it
6 | --- DISPLAY_NAME: Reverie
7 | --- BADGE_COLOUR: 9db95f
8 | --- VERSION: 1.3.0
9 | --- PREFIX: dvrprv
10 |
11 | ----------------------------------------------
12 | ------------MOD CODE -------------------------
13 |
14 | SMODS.load_file("data/main.lua")()
15 | SMODS.load_file("data/jokers.lua")()
16 | SMODS.load_file("data/boosters.lua")()
17 | SMODS.load_file("data/cines.lua")()
18 | SMODS.load_file("data/tags.lua")()
19 | SMODS.load_file("data/backs.lua")()
20 | SMODS.load_file("data/consumables.lua")()
21 | SMODS.load_file("data/vouchers.lua")()
22 | SMODS.load_file("data/atlases.lua")()
23 | SMODS.load_file("data/shaders.lua")()
24 |
25 | if Reverie.find_mod("JokerDisplay") and _G["JokerDisplay"] then
26 | SMODS.load_file("data/joker_display.lua")()
27 | end
28 |
29 | if Reverie.find_mod("CardSleeves") and CardSleeves.Sleeve then
30 | SMODS.load_file("data/sleeves.lua")()
31 | end
--------------------------------------------------------------------------------
/data/atlases.lua:
--------------------------------------------------------------------------------
1 | Reverie.atlases = {
2 | {
3 | key = "modicon",
4 | path = "icon.png",
5 | px = 34,
6 | py = 34
7 | },
8 | {
9 | key = "Cine",
10 | path = "cines.png",
11 | px = 71,
12 | py = 95
13 | },
14 | {
15 | key = "cine_jokers",
16 | path = "jokers.png",
17 | px = 71,
18 | py = 95
19 | },
20 | {
21 | key = "cine_boosters",
22 | path = "boosters.png",
23 | px = 71,
24 | py = 95
25 | },
26 | {
27 | key = "cine_vouchers",
28 | path = "vouchers.png",
29 | px = 71,
30 | py = 95
31 | },
32 | {
33 | key = "cine_tags",
34 | path = "tags.png",
35 | px = 34,
36 | py = 34
37 | },
38 | {
39 | key = "cine_backs",
40 | path = "backs.png",
41 | px = 71,
42 | py = 95
43 | },
44 | {
45 | key = "cine_sleeves",
46 | path = "sleeves.png",
47 | px = 71,
48 | py = 95
49 | }
50 | }
51 |
52 | for _, v in pairs(Reverie.atlases) do
53 | SMODS.Atlas(v)
54 | end
--------------------------------------------------------------------------------
/data/jokers.lua:
--------------------------------------------------------------------------------
1 | local function calculate_dynamic_film(self, card, context)
2 | if context.cine_progress and not context.blueprint then
3 | card.ability.extra.chips = card.ability.extra.chips + card.ability.extra.chip_mod
4 |
5 | card_eval_status_text(card, "extra", nil, nil, nil, {
6 | message = localize("k_upgrade_ex"),
7 | colour = G.C.CHIPS,
8 | card = card
9 | })
10 | elseif context.joker_main and card.ability.extra.chips > 0 then
11 | return {
12 | message = localize{
13 | type = "variable",
14 | key = "a_chips",
15 | vars = {
16 | card.ability.extra.chips
17 | }
18 | },
19 | chip_mod = card.ability.extra.chips
20 | }
21 | end
22 | end
23 |
24 | Reverie.jokers = {
25 | {
26 | key = "dynamic_film",
27 | order = 1,
28 | name = "Dynamic Film",
29 | config = {
30 | extra = {
31 | chips = 0,
32 | chip_mod = 15
33 | }
34 | },
35 | rarity = 1,
36 | cost = 4,
37 | blueprint_compat = true,
38 | loc_vars = function (self, info_queue, center)
39 | return {vars = {center.ability.extra.chips, center.ability.extra.chip_mod}}
40 | end,
41 | calculate = calculate_dynamic_film
42 | }
43 | }
44 |
45 | for _, v in ipairs(Reverie.jokers) do
46 | v.atlas = "cine_jokers"
47 |
48 | SMODS.Joker(v)
49 | end
--------------------------------------------------------------------------------
/data/backs.lua:
--------------------------------------------------------------------------------
1 | local function apply_filmstrip(self)
2 | G.GAME.starting_params.cine_quest_slots = G.GAME.starting_params.cine_quest_slots + self.config.cine_slot
3 | end
4 |
5 | local function trigger_stamp(self, args)
6 | if args.context == "setting_tags" then
7 | G.GAME.round_resets.blind_tags.Small = "tag_dvrprv_jumbo_tag"
8 | G.GAME.round_resets.blind_tags.Big = "tag_dvrprv_jumbo_tag"
9 |
10 | return
11 | end
12 | end
13 |
14 | Reverie.backs = {
15 | {
16 | key = "filmstrip",
17 | order = 1,
18 | name = "Filmstrip Deck",
19 | config = {
20 | cine_slot = 1
21 | },
22 | pos = {
23 | x = 0,
24 | y = 0
25 | },
26 | loc_vars = function (self, info_queue, center)
27 | return {vars = {self.config.cine_slot}}
28 | end,
29 | apply = apply_filmstrip
30 | },
31 | {
32 | key = "stamp",
33 | order = 2,
34 | name = "Stamp Deck",
35 | config = {},
36 | pos = {
37 | x = 1,
38 | y = 0
39 | },
40 | loc_vars = function (self, info_queue, center)
41 | return {vars = {
42 | localize{
43 | type = "name_text",
44 | key = "p_dvrprv_tag_jumbo",
45 | set = "Other"
46 | }
47 | }}
48 | end,
49 | trigger_effect = trigger_stamp
50 | }
51 | }
52 |
53 | for _, v in pairs(Reverie.backs) do
54 | v.atlas = "cine_backs"
55 |
56 | SMODS.Back(v)
57 | end
--------------------------------------------------------------------------------
/data/vouchers.lua:
--------------------------------------------------------------------------------
1 | local function redeem_script(center_table)
2 | if center_table.name == "Script" and G.GAME.current_round.used_cine
3 | and not G.GAME.current_round.cine_temporary_shop_card_limit then
4 | G.GAME.current_round.cine_temporary_shop_card_limit = true
5 | change_shop_size(center_table.config.extra)
6 | end
7 | end
8 |
9 | local function redeem_megaphone(center_table)
10 | if center_table.name == "Megaphone" and G.cine_quests then
11 | G.E_MANAGER:add_event(Event({
12 | func = function()
13 | for _, v in ipairs(G.cine_quests.cards) do
14 | if v.ability.progress then
15 | v.ability.extra.goal = Reverie.halve_cine_quest_goal(v.ability.extra.goal)
16 |
17 | if v.ability.progress >= v.ability.extra.goal then
18 | Reverie.complete_cine_quest(v)
19 | end
20 | end
21 | end
22 |
23 | return true
24 | end
25 | }))
26 | end
27 | end
28 |
29 | Reverie.vouchers = {
30 | {
31 | key = "script",
32 | order = 1,
33 | name = "Script",
34 | config = {
35 | extra = 2
36 | },
37 | pos = {
38 | x = 0,
39 | y = 0
40 | },
41 | redeem = redeem_script,
42 | loc_vars = function (self, info_queue, center)
43 | return {vars = {center.ability.extra}}
44 | end
45 | },
46 | {
47 | key = "megaphone",
48 | order = 2,
49 | name = "Megaphone",
50 | requires = {
51 | "v_dvrprv_script"
52 | },
53 | config = {
54 | extra = 0.5
55 | },
56 | pos = {
57 | x = 0,
58 | y = 1
59 | },
60 | redeem = redeem_megaphone
61 | }
62 | }
63 |
64 | for _, v in pairs(Reverie.vouchers) do
65 | v.atlas = "cine_vouchers"
66 |
67 | SMODS.Voucher(v)
68 | end
--------------------------------------------------------------------------------
/data/sleeves.lua:
--------------------------------------------------------------------------------
1 | local function apply_filmstrip(self)
2 | CardSleeves.Sleeve.apply(self)
3 |
4 | if self.get_current_deck_key() ~= "b_dvrprv_filmstrip" then
5 | G.GAME.starting_params.cine_quest_slots = G.GAME.starting_params.cine_quest_slots + self.config.cine_slot
6 | end
7 | end
8 |
9 | local function trigger_stamp(self, args)
10 | CardSleeves.Sleeve.trigger_effect(self, args)
11 |
12 | if args.context == "setting_tags" then
13 | local tag = self.get_current_deck_key() == "b_dvrprv_stamp" and "tag_dvrprv_mega_tag" or "tag_dvrprv_jumbo_tag"
14 |
15 | G.GAME.round_resets.blind_tags.Small = tag
16 | G.GAME.round_resets.blind_tags.Big = tag
17 | end
18 | end
19 |
20 | Reverie.sleeves = {
21 | {
22 | key = "filmstrip",
23 | order = 1,
24 | name = "Filmstrip Sleeve",
25 | config = {
26 | cine_slot = 1,
27 | odds = 4,
28 | rate = 2
29 | },
30 | pos = {
31 | x = 0,
32 | y = 0
33 | },
34 | unlocked = false,
35 | unlock_condition = { deck = "b_dvrprv_filmstrip", stake = 6 },
36 | loc_vars = function (self)
37 | local key = self.key
38 |
39 | if self.get_current_deck_key() == "b_dvrprv_filmstrip" then
40 | key = key.."_alt"
41 | end
42 |
43 | return {key = key, vars = {self.config.cine_slot, ""..(G.GAME and G.GAME.probabilities.normal or 1), self.config.odds}}
44 | end,
45 | apply = apply_filmstrip
46 | },
47 | {
48 | key = "stamp",
49 | order = 2,
50 | name = "Stamp Sleeve",
51 | config = {},
52 | pos = {
53 | x = 1,
54 | y = 0
55 | },
56 | unlocked = false,
57 | unlock_condition = { deck = "b_dvrprv_stamp", stake = 5 },
58 | loc_vars = function (self)
59 | local key = self.key
60 |
61 | if self.get_current_deck_key() == "b_dvrprv_stamp" then
62 | key = key.."_alt"
63 | end
64 |
65 | return {key = key, vars = {
66 | localize{
67 | type = "name_text",
68 | key = "p_dvrprv_tag_jumbo",
69 | set = "Other"
70 | }
71 | }}
72 | end,
73 | trigger_effect = trigger_stamp
74 | }
75 | }
76 |
77 | for _, v in pairs(Reverie.sleeves) do
78 | v.atlas = "cine_sleeves"
79 |
80 | CardSleeves.Sleeve(v)
81 | end
--------------------------------------------------------------------------------
/data/tags.lua:
--------------------------------------------------------------------------------
1 | local function apply_stub(self, _context)
2 | if _context.type == "new_blind_choice" then
3 | local lock = self.ID
4 | G.CONTROLLER.locks[lock] = true
5 |
6 | self:yep("+", G.C.SECONDARY_SET.Cine, function()
7 | local key = "p_dvrprv_film_normal_"..(math.random(1, 2))
8 | local card = Card(G.play.T.x + G.play.T.w / 2 - G.CARD_W * 1.27 / 2, G.play.T.y + G.play.T.h / 2 - G.CARD_H * 1.27 / 2,
9 | G.CARD_W * 1.27, G.CARD_H * 1.27, G.P_CARDS.empty, G.P_CENTERS[key], {
10 | bypass_discovery_center = true,
11 | bypass_discovery_ui = true
12 | })
13 | card.cost = 0
14 | card.from_tag = true
15 |
16 | G.FUNCS.use_card({
17 | config = {
18 | ref_table = card
19 | }
20 | })
21 | card:start_materialize()
22 | G.CONTROLLER.locks[lock] = nil
23 |
24 | return true
25 | end)
26 | self.triggered = true
27 |
28 | return true
29 | end
30 | end
31 |
32 | local function apply_stamp(self, _context)
33 | if _context.type == "new_blind_choice" then
34 | self:yep("+", G.C.SECONDARY_SET.Tag, function()
35 | local pack_key = "p_dvrprv_tag_jumbo_1"
36 | local card = Card(G.play.T.x + G.play.T.w / 2 - G.CARD_W * 1.27 / 2, G.play.T.y + G.play.T.h / 2 - G.CARD_H * 1.27 / 2,
37 | G.CARD_W * 1.27, G.CARD_H * 1.27, G.P_CARDS.empty, G.P_CENTERS[pack_key], {
38 | bypass_discovery_center = true,
39 | bypass_discovery_ui = true
40 | })
41 | card.cost = 0
42 | card.from_tag = true
43 |
44 | G.FUNCS.use_card({
45 | config = {
46 | ref_table = card
47 | }
48 | })
49 | card:start_materialize()
50 |
51 | if self.name == "Mega Stamp Tag" then
52 | local tag = Tag(get_next_tag_key("mega_stamp"))
53 |
54 | if tag.name == "Orbital Tag" then
55 | local poker_hands = {}
56 | for k, v in pairs(G.GAME.hands) do
57 | if v.visible then
58 | table.insert(poker_hands, k)
59 | end
60 | end
61 |
62 | tag.ability.orbital_hand = pseudorandom_element(poker_hands, pseudoseed("mega_stamp_orbital"))
63 | end
64 |
65 | add_tag(tag)
66 | end
67 |
68 | G.CONTROLLER.locks[self.ID] = nil
69 |
70 | return true
71 | end)
72 | self.triggered = true
73 |
74 | return true
75 | end
76 | end
77 |
78 | Reverie.tags = {
79 | {
80 | key = "cine",
81 | order = 1,
82 | name = "Stub Tag",
83 | config = {
84 | type = "new_blind_choice"
85 | },
86 | pos = {
87 | x = 0,
88 | y = 0
89 | },
90 | loc_vars = function (self, info_queue)
91 | local info = G.P_CENTERS.p_dvrprv_film_normal_1:loc_vars(info_queue)
92 |
93 | info_queue[#info_queue + 1] = {
94 | key = info.key,
95 | set = "Other",
96 | vars = info.vars
97 | }
98 |
99 | return {}
100 | end,
101 | apply = apply_stub
102 | },
103 | {
104 | key = "jumbo_tag",
105 | order = 2,
106 | name = "Stamp Tag",
107 | config = {
108 | type = "new_blind_choice"
109 | },
110 | pos = {
111 | x = 1,
112 | y = 0
113 | },
114 | yes_pool_flag = "tag_tag_available",
115 | loc_vars = function (self, info_queue)
116 | local info = G.P_CENTERS.p_dvrprv_tag_jumbo_1:loc_vars(info_queue)
117 |
118 | info_queue[#info_queue + 1] = {
119 | key = info.key,
120 | set = "Other",
121 | vars = info.vars
122 | }
123 |
124 | return {}
125 | end,
126 | apply = apply_stamp
127 | },
128 | {
129 | key = "mega_tag",
130 | order = 3,
131 | name = "Mega Stamp Tag",
132 | config = {
133 | type = "new_blind_choice"
134 | },
135 | pos = {
136 | x = 2,
137 | y = 0
138 | },
139 | yes_pool_flag = "tag_tag_available",
140 | loc_vars = function (self, info_queue)
141 | local info = G.P_CENTERS.p_dvrprv_tag_jumbo_1:loc_vars(info_queue)
142 |
143 | info_queue[#info_queue + 1] = {
144 | key = info.key,
145 | set = "Other",
146 | vars = info.vars
147 | }
148 |
149 | return {}
150 | end,
151 | apply = apply_stamp,
152 | dependency = "CardSleeves"
153 | }
154 | }
155 |
156 | for _, v in pairs(Reverie.tags) do
157 | v.atlas = "cine_tags"
158 |
159 | if not v.dependency or Reverie.find_mod(v.dependency) then
160 | SMODS.Tag(v)
161 | end
162 | end
--------------------------------------------------------------------------------
/assets/shaders/ticket.fs:
--------------------------------------------------------------------------------
1 | #if defined(VERTEX) || __VERSION__ > 100 || defined(GL_FRAGMENT_PRECISION_HIGH)
2 | #define MY_HIGHP_OR_MEDIUMP highp
3 | #else
4 | #define MY_HIGHP_OR_MEDIUMP mediump
5 | #endif
6 |
7 | extern MY_HIGHP_OR_MEDIUMP vec2 ticket;
8 | extern MY_HIGHP_OR_MEDIUMP number dissolve;
9 | extern MY_HIGHP_OR_MEDIUMP number time;
10 | extern MY_HIGHP_OR_MEDIUMP vec4 texture_details;
11 | extern MY_HIGHP_OR_MEDIUMP vec2 image_details;
12 | extern bool shadow;
13 | extern MY_HIGHP_OR_MEDIUMP vec4 burn_colour_1;
14 | extern MY_HIGHP_OR_MEDIUMP vec4 burn_colour_2;
15 |
16 | vec4 dissolve_mask(vec4 tex, vec2 texture_coords, vec2 uv)
17 | {
18 | if (dissolve < 0.001) {
19 | return vec4(shadow ? vec3(0.,0.,0.) : tex.xyz, shadow ? tex.a*0.3: tex.a);
20 | }
21 |
22 | float adjusted_dissolve = (dissolve*dissolve*(3.-2.*dissolve))*1.02 - 0.01; //Adjusting 0.0-1.0 to fall to -0.1 - 1.1 scale so the mask does not pause at extreme values
23 |
24 | float t = time * 10.0 + 2003.;
25 | vec2 floored_uv = (floor((uv*texture_details.ba)))/max(texture_details.b, texture_details.a);
26 | vec2 uv_scaled_centered = (floored_uv - 0.5) * 2.3 * max(texture_details.b, texture_details.a);
27 |
28 | vec2 field_part1 = uv_scaled_centered + 50.*vec2(sin(-t / 143.6340), cos(-t / 99.4324));
29 | vec2 field_part2 = uv_scaled_centered + 50.*vec2(cos( t / 53.1532), cos( t / 61.4532));
30 | vec2 field_part3 = uv_scaled_centered + 50.*vec2(sin(-t / 87.53218), sin(-t / 49.0000));
31 |
32 | float field = (1.+ (
33 | cos(length(field_part1) / 19.483) + sin(length(field_part2) / 33.155) * cos(field_part2.y / 15.73) +
34 | cos(length(field_part3) / 27.193) * sin(field_part3.x / 21.92) ))/2.;
35 | vec2 borders = vec2(0.2, 0.8);
36 |
37 | float res = (.5 + .5* cos( (adjusted_dissolve) / 82.612 + ( field + -.5 ) *3.14))
38 | - (floored_uv.x > borders.y ? (floored_uv.x - borders.y)*(5. + 5.*dissolve) : 0.)*(dissolve)
39 | - (floored_uv.y > borders.y ? (floored_uv.y - borders.y)*(5. + 5.*dissolve) : 0.)*(dissolve)
40 | - (floored_uv.x < borders.x ? (borders.x - floored_uv.x)*(5. + 5.*dissolve) : 0.)*(dissolve)
41 | - (floored_uv.y < borders.x ? (borders.x - floored_uv.y)*(5. + 5.*dissolve) : 0.)*(dissolve);
42 |
43 | if (tex.a > 0.01 && burn_colour_1.a > 0.01 && !shadow && res < adjusted_dissolve + 0.8*(0.5-abs(adjusted_dissolve-0.5)) && res > adjusted_dissolve) {
44 | if (!shadow && res < adjusted_dissolve + 0.5*(0.5-abs(adjusted_dissolve-0.5)) && res > adjusted_dissolve) {
45 | tex.rgba = burn_colour_1.rgba;
46 | } else if (burn_colour_2.a > 0.01) {
47 | tex.rgba = burn_colour_2.rgba;
48 | }
49 | }
50 |
51 | return vec4(shadow ? vec3(0.,0.,0.) : tex.xyz, res > adjusted_dissolve ? (shadow ? tex.a*0.3: tex.a) : .0);
52 | }
53 |
54 | vec4 effect( vec4 colour, Image texture, vec2 texture_coords, vec2 screen_coords )
55 | {
56 | vec4 tex = Texel( texture, texture_coords);
57 | vec2 uv = (((texture_coords)*(image_details)) - texture_details.xy*texture_details.ba)/texture_details.ba;
58 | vec4 border_1 = vec4(255. / 255., 244. / 255., 180. / 255., 1.);
59 | vec4 border_2 = vec4(189. / 255., 188. / 255., 132. / 255., 1.);
60 | vec4 border_3 = vec4(171. / 255., 170. / 255., 120. / 255., 1.);
61 | vec4 joker_black = vec4(79. / 255., 99. / 255., 103. / 255., 1.);
62 |
63 | if (any(greaterThan(abs(tex.rgb - border_1.rgb), vec3(0.1))) &&
64 | any(greaterThan(abs(tex.rgb - border_2.rgb), vec3(0.1))) &&
65 | any(greaterThan(abs(tex.rgb - border_3.rgb), vec3(0.1))) &&
66 | any(greaterThan(abs(tex.rgb - joker_black.rgb), vec3(0.1))))
67 | {
68 | number low = min(tex.r, min(tex.g, tex.b));
69 | number high = max(tex.r, max(tex.g, tex.b));
70 | number delta = max(high-low, low*0.7);
71 |
72 | number fac = 0.8 + 0.9*sin(13.*uv.x+5.32*uv.y + ticket.r*12. + cos(ticket.r*5.3 + uv.y*4.2 - uv.x*4.));
73 | number fac2 = 0.5 + 0.5*sin(10.*uv.x+2.32*uv.y + ticket.r*5. - cos(ticket.r*2.3 + uv.x*8.2));
74 | number fac3 = 0.5 + 0.5*sin(12.*uv.x+6.32*uv.y + ticket.r*6.111 + sin(ticket.r*5.3 + uv.y*3.2));
75 | number fac4 = 0.5 + 0.5*sin(4.*uv.x+2.32*uv.y + ticket.r*8.111 + sin(ticket.r*1.3 + uv.y*13.2));
76 | number fac5 = sin(0.5*16.*uv.x+5.32*uv.y + ticket.r*12. + cos(ticket.r*5.3 + uv.y*4.2 - uv.x*4.));
77 |
78 | number maxfac = 0.6*max(max(fac, max(fac2, max(fac3,0.0))) + (fac+fac2+fac3*fac4), 0.);
79 |
80 | tex.rgb = tex.rgb*0.5 + vec3(0.4, 0.4, 0.8);
81 |
82 | tex.r = tex.r-delta + delta*maxfac*(0.7 + fac5*0.07) - 0.1;
83 | tex.g = tex.g-delta + delta*maxfac*(0.7 - fac5*0.17) - 0.1;
84 | tex.b = tex.b-delta + delta*maxfac*0.7 - 0.1;
85 | tex.a = tex.a*(0.8*max(min(1., max(0.,0.3*max(low*0.2, delta)+ min(max(maxfac*0.1,0.), 0.4)) ), 0.) + 0.15*maxfac*(0.1+delta));
86 |
87 | tex.a *= 0.6;
88 | }
89 |
90 | return dissolve_mask(tex*colour, texture_coords, uv);
91 | }
92 |
93 | extern MY_HIGHP_OR_MEDIUMP vec2 mouse_screen_pos;
94 | extern MY_HIGHP_OR_MEDIUMP float hovering;
95 | extern MY_HIGHP_OR_MEDIUMP float screen_scale;
96 |
97 | #ifdef VERTEX
98 | vec4 position( mat4 transform_projection, vec4 vertex_position )
99 | {
100 | if (hovering <= 0.){
101 | return transform_projection * vertex_position;
102 | }
103 | float mid_dist = length(vertex_position.xy - 0.5*love_ScreenSize.xy)/length(love_ScreenSize.xy);
104 | vec2 mouse_offset = (vertex_position.xy - mouse_screen_pos.xy)/screen_scale;
105 | float scale = 0.2*(-0.03 - 0.3*max(0., 0.3-mid_dist))
106 | *hovering*(length(mouse_offset)*length(mouse_offset))/(2. -mid_dist);
107 |
108 | return transform_projection * vertex_position + vec4(0,0,0,scale);
109 | }
110 | #endif
111 |
--------------------------------------------------------------------------------
/assets/shaders/ticket_negative.fs:
--------------------------------------------------------------------------------
1 | #if defined(VERTEX) || __VERSION__ > 100 || defined(GL_FRAGMENT_PRECISION_HIGH)
2 | #define MY_HIGHP_OR_MEDIUMP highp
3 | #else
4 | #define MY_HIGHP_OR_MEDIUMP mediump
5 | #endif
6 |
7 | extern MY_HIGHP_OR_MEDIUMP vec2 ticket_negative;
8 | extern MY_HIGHP_OR_MEDIUMP number dissolve;
9 | extern MY_HIGHP_OR_MEDIUMP number time;
10 | extern MY_HIGHP_OR_MEDIUMP vec4 texture_details;
11 | extern MY_HIGHP_OR_MEDIUMP vec2 image_details;
12 | extern bool shadow;
13 | extern MY_HIGHP_OR_MEDIUMP vec4 burn_colour_1;
14 | extern MY_HIGHP_OR_MEDIUMP vec4 burn_colour_2;
15 |
16 | vec4 dissolve_mask(vec4 tex, vec2 texture_coords, vec2 uv)
17 | {
18 | if (dissolve < 0.001) {
19 | return vec4(shadow ? vec3(0.,0.,0.) : tex.xyz, shadow ? tex.a*0.3: tex.a);
20 | }
21 |
22 | float adjusted_dissolve = (dissolve*dissolve*(3.-2.*dissolve))*1.02 - 0.01; //Adjusting 0.0-1.0 to fall to -0.1 - 1.1 scale so the mask does not pause at extreme values
23 |
24 | float t = time * 10.0 + 2003.;
25 | vec2 floored_uv = (floor((uv*texture_details.ba)))/max(texture_details.b, texture_details.a);
26 | vec2 uv_scaled_centered = (floored_uv - 0.5) * 2.3 * max(texture_details.b, texture_details.a);
27 |
28 | vec2 field_part1 = uv_scaled_centered + 50.*vec2(sin(-t / 143.6340), cos(-t / 99.4324));
29 | vec2 field_part2 = uv_scaled_centered + 50.*vec2(cos( t / 53.1532), cos( t / 61.4532));
30 | vec2 field_part3 = uv_scaled_centered + 50.*vec2(sin(-t / 87.53218), sin(-t / 49.0000));
31 |
32 | float field = (1.+ (
33 | cos(length(field_part1) / 19.483) + sin(length(field_part2) / 33.155) * cos(field_part2.y / 15.73) +
34 | cos(length(field_part3) / 27.193) * sin(field_part3.x / 21.92) ))/2.;
35 | vec2 borders = vec2(0.2, 0.8);
36 |
37 | float res = (.5 + .5* cos( (adjusted_dissolve) / 82.612 + ( field + -.5 ) *3.14))
38 | - (floored_uv.x > borders.y ? (floored_uv.x - borders.y)*(5. + 5.*dissolve) : 0.)*(dissolve)
39 | - (floored_uv.y > borders.y ? (floored_uv.y - borders.y)*(5. + 5.*dissolve) : 0.)*(dissolve)
40 | - (floored_uv.x < borders.x ? (borders.x - floored_uv.x)*(5. + 5.*dissolve) : 0.)*(dissolve)
41 | - (floored_uv.y < borders.x ? (borders.x - floored_uv.y)*(5. + 5.*dissolve) : 0.)*(dissolve);
42 |
43 | if (tex.a > 0.01 && burn_colour_1.a > 0.01 && !shadow && res < adjusted_dissolve + 0.8*(0.5-abs(adjusted_dissolve-0.5)) && res > adjusted_dissolve) {
44 | if (!shadow && res < adjusted_dissolve + 0.5*(0.5-abs(adjusted_dissolve-0.5)) && res > adjusted_dissolve) {
45 | tex.rgba = burn_colour_1.rgba;
46 | } else if (burn_colour_2.a > 0.01) {
47 | tex.rgba = burn_colour_2.rgba;
48 | }
49 | }
50 |
51 | return vec4(shadow ? vec3(0.,0.,0.) : tex.xyz, res > adjusted_dissolve ? (shadow ? tex.a*0.3: tex.a) : .0);
52 | }
53 |
54 | number hue(number s, number t, number h)
55 | {
56 | number hs = mod(h, 1.)*6.;
57 | if (hs < 1.) return (t-s) * hs + s;
58 | if (hs < 3.) return t;
59 | if (hs < 4.) return (t-s) * (4.-hs) + s;
60 | return s;
61 | }
62 |
63 | vec4 RGB(vec4 c)
64 | {
65 | if (c.y < 0.0001)
66 | return vec4(vec3(c.z), c.a);
67 |
68 | number t = (c.z < .5) ? c.y*c.z + c.z : -c.y*c.z + (c.y+c.z);
69 | number s = 2.0 * c.z - t;
70 | return vec4(hue(s,t,c.x + 1./3.), hue(s,t,c.x), hue(s,t,c.x - 1./3.), c.w);
71 | }
72 |
73 | vec4 HSL(vec4 c)
74 | {
75 | number low = min(c.r, min(c.g, c.b));
76 | number high = max(c.r, max(c.g, c.b));
77 | number delta = high - low;
78 | number sum = high+low;
79 |
80 | vec4 hsl = vec4(.0, .0, .5 * sum, c.a);
81 | if (delta == .0)
82 | return hsl;
83 |
84 | hsl.y = (hsl.z < .5) ? delta / sum : delta / (2.0 - sum);
85 |
86 | if (high == c.r)
87 | hsl.x = (c.g - c.b) / delta;
88 | else if (high == c.g)
89 | hsl.x = (c.b - c.r) / delta + 2.0;
90 | else
91 | hsl.x = (c.r - c.g) / delta + 4.0;
92 |
93 | hsl.x = mod(hsl.x / 6., 1.);
94 | return hsl;
95 | }
96 |
97 | vec4 effect( vec4 colour, Image texture, vec2 texture_coords, vec2 screen_coords )
98 | {
99 | vec4 tex = Texel(texture, texture_coords);
100 | vec2 uv = (((texture_coords)*(image_details)) - texture_details.xy*texture_details.ba)/texture_details.ba;
101 | vec4 border_1 = vec4(255. / 255., 244. / 255., 180. / 255., 1.);
102 | vec4 border_2 = vec4(189. / 255., 188. / 255., 132. / 255., 1.);
103 | vec4 border_3 = vec4(171. / 255., 170. / 255., 120. / 255., 1.);
104 |
105 | if (any(greaterThan(abs(tex.rgb - border_1.rgb), vec3(0.1))) &&
106 | any(greaterThan(abs(tex.rgb - border_2.rgb), vec3(0.1))) &&
107 | any(greaterThan(abs(tex.rgb - border_3.rgb), vec3(0.1))))
108 | {
109 | vec4 SAT = HSL(tex);
110 |
111 | if (ticket_negative.g > 0.0 || ticket_negative.g < 0.0) {
112 | SAT.b = (1.-SAT.b);
113 | }
114 | SAT.r = -SAT.r+0.2;
115 |
116 | tex = RGB(SAT) + 0.8*vec4(79./255., 99./255.,103./255.,0.);
117 | }
118 |
119 | if (tex[3] < 0.7)
120 | tex[3] = tex[3]/3.;
121 | return dissolve_mask(tex*colour, texture_coords, uv);
122 | }
123 |
124 | extern MY_HIGHP_OR_MEDIUMP vec2 mouse_screen_pos;
125 | extern MY_HIGHP_OR_MEDIUMP float hovering;
126 | extern MY_HIGHP_OR_MEDIUMP float screen_scale;
127 |
128 | #ifdef VERTEX
129 | vec4 position( mat4 transform_projection, vec4 vertex_position )
130 | {
131 | if (hovering <= 0.){
132 | return transform_projection * vertex_position;
133 | }
134 | float mid_dist = length(vertex_position.xy - 0.5*love_ScreenSize.xy)/length(love_ScreenSize.xy);
135 | vec2 mouse_offset = (vertex_position.xy - mouse_screen_pos.xy)/screen_scale;
136 | float scale = 0.2*(-0.03 - 0.3*max(0., 0.3-mid_dist))
137 | *hovering*(length(mouse_offset)*length(mouse_offset))/(2. -mid_dist);
138 |
139 | return transform_projection * vertex_position + vec4(0,0,0,scale);
140 | }
141 | #endif
142 |
--------------------------------------------------------------------------------
/assets/shaders/ticket_polychrome.fs:
--------------------------------------------------------------------------------
1 | #if defined(VERTEX) || __VERSION__ > 100 || defined(GL_FRAGMENT_PRECISION_HIGH)
2 | #define MY_HIGHP_OR_MEDIUMP highp
3 | #else
4 | #define MY_HIGHP_OR_MEDIUMP mediump
5 | #endif
6 |
7 | extern MY_HIGHP_OR_MEDIUMP vec2 ticket_polychrome;
8 | extern MY_HIGHP_OR_MEDIUMP number dissolve;
9 | extern MY_HIGHP_OR_MEDIUMP number time;
10 | extern MY_HIGHP_OR_MEDIUMP vec4 texture_details;
11 | extern MY_HIGHP_OR_MEDIUMP vec2 image_details;
12 | extern bool shadow;
13 | extern MY_HIGHP_OR_MEDIUMP vec4 burn_colour_1;
14 | extern MY_HIGHP_OR_MEDIUMP vec4 burn_colour_2;
15 |
16 | vec4 dissolve_mask(vec4 tex, vec2 texture_coords, vec2 uv)
17 | {
18 | if (dissolve < 0.001) {
19 | return vec4(shadow ? vec3(0.,0.,0.) : tex.xyz, shadow ? tex.a*0.3: tex.a);
20 | }
21 |
22 | float adjusted_dissolve = (dissolve*dissolve*(3.-2.*dissolve))*1.02 - 0.01; //Adjusting 0.0-1.0 to fall to -0.1 - 1.1 scale so the mask does not pause at extreme values
23 |
24 | float t = time * 10.0 + 2003.;
25 | vec2 floored_uv = (floor((uv*texture_details.ba)))/max(texture_details.b, texture_details.a);
26 | vec2 uv_scaled_centered = (floored_uv - 0.5) * 2.3 * max(texture_details.b, texture_details.a);
27 |
28 | vec2 field_part1 = uv_scaled_centered + 50.*vec2(sin(-t / 143.6340), cos(-t / 99.4324));
29 | vec2 field_part2 = uv_scaled_centered + 50.*vec2(cos( t / 53.1532), cos( t / 61.4532));
30 | vec2 field_part3 = uv_scaled_centered + 50.*vec2(sin(-t / 87.53218), sin(-t / 49.0000));
31 |
32 | float field = (1.+ (
33 | cos(length(field_part1) / 19.483) + sin(length(field_part2) / 33.155) * cos(field_part2.y / 15.73) +
34 | cos(length(field_part3) / 27.193) * sin(field_part3.x / 21.92) ))/2.;
35 | vec2 borders = vec2(0.2, 0.8);
36 |
37 | float res = (.5 + .5* cos( (adjusted_dissolve) / 82.612 + ( field + -.5 ) *3.14))
38 | - (floored_uv.x > borders.y ? (floored_uv.x - borders.y)*(5. + 5.*dissolve) : 0.)*(dissolve)
39 | - (floored_uv.y > borders.y ? (floored_uv.y - borders.y)*(5. + 5.*dissolve) : 0.)*(dissolve)
40 | - (floored_uv.x < borders.x ? (borders.x - floored_uv.x)*(5. + 5.*dissolve) : 0.)*(dissolve)
41 | - (floored_uv.y < borders.x ? (borders.x - floored_uv.y)*(5. + 5.*dissolve) : 0.)*(dissolve);
42 |
43 | if (tex.a > 0.01 && burn_colour_1.a > 0.01 && !shadow && res < adjusted_dissolve + 0.8*(0.5-abs(adjusted_dissolve-0.5)) && res > adjusted_dissolve) {
44 | if (!shadow && res < adjusted_dissolve + 0.5*(0.5-abs(adjusted_dissolve-0.5)) && res > adjusted_dissolve) {
45 | tex.rgba = burn_colour_1.rgba;
46 | } else if (burn_colour_2.a > 0.01) {
47 | tex.rgba = burn_colour_2.rgba;
48 | }
49 | }
50 |
51 | return vec4(shadow ? vec3(0.,0.,0.) : tex.xyz, res > adjusted_dissolve ? (shadow ? tex.a*0.3: tex.a) : .0);
52 | }
53 |
54 | number hue(number s, number t, number h)
55 | {
56 | number hs = mod(h, 1.)*6.;
57 | if (hs < 1.) return (t-s) * hs + s;
58 | if (hs < 3.) return t;
59 | if (hs < 4.) return (t-s) * (4.-hs) + s;
60 | return s;
61 | }
62 |
63 | vec4 RGB(vec4 c)
64 | {
65 | if (c.y < 0.0001)
66 | return vec4(vec3(c.z), c.a);
67 |
68 | number t = (c.z < .5) ? c.y*c.z + c.z : -c.y*c.z + (c.y+c.z);
69 | number s = 2.0 * c.z - t;
70 | return vec4(hue(s,t,c.x + 1./3.), hue(s,t,c.x), hue(s,t,c.x - 1./3.), c.w);
71 | }
72 |
73 | vec4 HSL(vec4 c)
74 | {
75 | number low = min(c.r, min(c.g, c.b));
76 | number high = max(c.r, max(c.g, c.b));
77 | number delta = high - low;
78 | number sum = high+low;
79 |
80 | vec4 hsl = vec4(.0, .0, .5 * sum, c.a);
81 | if (delta == .0)
82 | return hsl;
83 |
84 | hsl.y = (hsl.z < .5) ? delta / sum : delta / (2.0 - sum);
85 |
86 | if (high == c.r)
87 | hsl.x = (c.g - c.b) / delta;
88 | else if (high == c.g)
89 | hsl.x = (c.b - c.r) / delta + 2.0;
90 | else
91 | hsl.x = (c.r - c.g) / delta + 4.0;
92 |
93 | hsl.x = mod(hsl.x / 6., 1.);
94 | return hsl;
95 | }
96 |
97 | vec4 effect( vec4 colour, Image texture, vec2 texture_coords, vec2 screen_coords )
98 | {
99 | vec4 tex = Texel(texture, texture_coords);
100 | vec2 uv = (((texture_coords)*(image_details)) - texture_details.xy*texture_details.ba)/texture_details.ba;
101 | vec4 border_1 = vec4(255. / 255., 244. / 255., 180. / 255., 1.);
102 | vec4 border_2 = vec4(189. / 255., 188. / 255., 132. / 255., 1.);
103 | vec4 border_3 = vec4(171. / 255., 170. / 255., 120. / 255., 1.);
104 | vec4 joker_black = vec4(79. / 255., 99. / 255., 103. / 255., 1.);
105 |
106 | if (any(greaterThan(abs(tex.rgb - border_1.rgb), vec3(0.1))) &&
107 | any(greaterThan(abs(tex.rgb - border_2.rgb), vec3(0.1))) &&
108 | any(greaterThan(abs(tex.rgb - border_3.rgb), vec3(0.1))) &&
109 | any(greaterThan(abs(tex.rgb - joker_black.rgb), vec3(0.1))))
110 | {
111 | number low = min(tex.r, min(tex.g, tex.b));
112 | number high = max(tex.r, max(tex.g, tex.b));
113 | number delta = high - low;
114 |
115 | number saturation_fac = 1. - max(0., 0.05*(1.1-delta));
116 |
117 | vec4 hsl = HSL(vec4(tex.r*saturation_fac, tex.g*saturation_fac, tex.b, tex.a));
118 |
119 | float t = ticket_polychrome.y*2.221 + time;
120 | vec2 floored_uv = (floor((uv*texture_details.ba)))/texture_details.ba;
121 | vec2 uv_scaled_centered = (floored_uv - 0.5) * 50.;
122 |
123 | vec2 field_part1 = uv_scaled_centered + 50.*vec2(sin(-t / 143.6340), cos(-t / 99.4324));
124 | vec2 field_part2 = uv_scaled_centered + 50.*vec2(cos( t / 53.1532), cos( t / 61.4532));
125 | vec2 field_part3 = uv_scaled_centered + 50.*vec2(sin(-t / 87.53218), sin(-t / 49.0000));
126 |
127 | float field = (1.+ (
128 | cos(length(field_part1) / 19.483) + sin(length(field_part2) / 33.155) * cos(field_part2.y / 15.73) +
129 | cos(length(field_part3) / 27.193) * sin(field_part3.x / 21.92) ))/2.;
130 |
131 | float res = (.5 + .5* cos( (ticket_polychrome.x) * 2.612 + ( field + -.5 ) *3.14));
132 | hsl.x = hsl.x+ res + ticket_polychrome.y*0.04;
133 | hsl.y = min(0.6,hsl.y+0.5);
134 |
135 | tex.rgb = RGB(hsl).rgb;
136 | }
137 |
138 | if (tex[3] < 0.7)
139 | tex[3] = tex[3]/3.;
140 | return dissolve_mask(tex*colour, texture_coords, uv);
141 | }
142 |
143 | extern MY_HIGHP_OR_MEDIUMP vec2 mouse_screen_pos;
144 | extern MY_HIGHP_OR_MEDIUMP float hovering;
145 | extern MY_HIGHP_OR_MEDIUMP float screen_scale;
146 |
147 | #ifdef VERTEX
148 | vec4 position( mat4 transform_projection, vec4 vertex_position )
149 | {
150 | if (hovering <= 0.){
151 | return transform_projection * vertex_position;
152 | }
153 | float mid_dist = length(vertex_position.xy - 0.5*love_ScreenSize.xy)/length(love_ScreenSize.xy);
154 | vec2 mouse_offset = (vertex_position.xy - mouse_screen_pos.xy)/screen_scale;
155 | float scale = 0.2*(-0.03 - 0.3*max(0., 0.3-mid_dist))
156 | *hovering*(length(mouse_offset)*length(mouse_offset))/(2. -mid_dist);
157 |
158 | return transform_projection * vertex_position + vec4(0,0,0,scale);
159 | }
160 | #endif
161 |
--------------------------------------------------------------------------------
/data/boosters.lua:
--------------------------------------------------------------------------------
1 | local crazy_pack_sparkles = {
2 | timer = 0.05,
3 | scale = 0.1,
4 | lifespan = 2.5,
5 | speed = 0.7,
6 | padding = -3,
7 | colours = {G.C.WHITE, lighten(Reverie.badge_colour, 0.4), lighten(G.C.RED, 0.2)}
8 | }
9 | local film_pack_meteors = {
10 | timer = 0.035,
11 | scale = 0.1,
12 | lifespan = 1.5,
13 | speed = 4,
14 | colours = {lighten(Reverie.badge_colour, 0.2), G.C.WHITE}
15 | }
16 |
17 | local function create_tag_pack_card(self, card)
18 | return Reverie.create_tag_as_card(G.pack_cards or G.jokers, true, Reverie.booster_excludes)
19 | end
20 |
21 | local function ease_tag_pack_colour(self)
22 | ease_colour(G.C.DYN_UI.MAIN, mix_colours(G.C.SECONDARY_SET.Tag, G.C.BLACK, 0.9))
23 | ease_background_colour{new_colour = G.C.SECONDARY_SET.Tag, special_colour = G.C.BLACK, contrast = 2}
24 | end
25 |
26 | local function create_crazy_pack_card(self, card)
27 | return Reverie.create_crazy_random_card(G.pack_cards or G.jokers, Reverie.booster_excludes)
28 | end
29 |
30 | local function ease_crazy_pack_colour(self)
31 | ease_colour(G.C.DYN_UI.MAIN, mix_colours(G.C.SECONDARY_SET.Cine, G.C.BLACK, 0.9))
32 | ease_background_colour{new_colour = darken(G.C.RED, 0.2), special_colour = darken(G.C.SECONDARY_SET.Cine, 0.4), tertiary_colour = darken(G.C.BLACK, 0.2), contrast = 3}
33 | end
34 |
35 | local function create_film_pack_card(self, card)
36 | return create_card(card.ability.name:find("Mega") and "Cine" or "Cine_Quest", G.pack_cards, nil, nil, true, true, nil, "film")
37 | end
38 |
39 | local function ease_film_pack_colour(self)
40 | ease_colour(G.C.DYN_UI.MAIN, mix_colours(G.C.SECONDARY_SET.Cine, G.C.BLACK, 0.9))
41 | ease_background_colour{new_colour = G.C.SECONDARY_SET.Cine, special_colour = G.C.BLACK, contrast = 2}
42 | end
43 |
44 | local function loc_vars(self, info_queue, center)
45 | local key = nil
46 |
47 | if self.name == "Tag Pack" then key = "p_dvrprv_tag_normal"
48 | elseif self.name == "Jumbo Tag Pack" then key = "p_dvrprv_tag_jumbo"
49 | elseif self.name == "Mega Tag Pack" then key = "p_dvrprv_tag_mega"
50 | elseif self.name == "Pack" then key = "p_dvrprv_crazy_lucky"
51 | elseif self.name == "Film Pack" then key = "p_dvrprv_film_normal"
52 | elseif self.name == "Jumbo Film Pack" then key = "p_dvrprv_film_jumbo"
53 | elseif self.name == "Mega Film Pack" then key = "p_dvrprv_film_mega"
54 | end
55 |
56 | return {
57 | vars = {Reverie.get_var_object(center, self).choose, Reverie.get_var_object(center, self).extra},
58 | key = key
59 | }
60 | end
61 |
62 | local function generate_ui(self, info_queue, card, desc_nodes, specific_vars, full_UI_table)
63 | local info = self:loc_vars(info_queue, card)
64 |
65 | if not full_UI_table.name then
66 | full_UI_table.name = localize{type = "name", set = "Other", key = info.key, nodes = full_UI_table.name}
67 | end
68 |
69 | localize{type = "other", key = info.key, nodes = desc_nodes, vars = info.vars}
70 | end
71 |
72 | local function generate_detailed_tooltip(self, info_queue, card, desc_nodes)
73 | desc_nodes.name = localize{type = "name_text", set = "Other", key = self:loc_vars(info_queue, card).key}
74 | end
75 |
76 | Reverie.boosters = {
77 | {
78 | key = "tag_normal_1",
79 | group_key = "k_dvrprv_tag_pack",
80 | order = 1,
81 | name = "Tag Pack",
82 | config = {
83 | extra = 2,
84 | choose = 1
85 | },
86 | weight = 1,
87 | kind = "Tag",
88 | cost = 4,
89 | yes_pool_flag = "Tag or Die",
90 | pos = {
91 | x = 0,
92 | y = 0
93 | },
94 | create_card = create_tag_pack_card,
95 | ease_background_colour = ease_tag_pack_colour
96 | },
97 | {
98 | key = "tag_normal_2",
99 | group_key = "k_dvrprv_tag_pack",
100 | order = 2,
101 | name = "Tag Pack",
102 | config = {
103 | extra = 2,
104 | choose = 1
105 | },
106 | weight = 1,
107 | kind = "Tag",
108 | cost = 4,
109 | yes_pool_flag = "Tag or Die",
110 | pos = {
111 | x = 1,
112 | y = 0
113 | },
114 | create_card = create_tag_pack_card,
115 | ease_background_colour = ease_tag_pack_colour
116 | },
117 | {
118 | key = "tag_jumbo_1",
119 | group_key = "k_dvrprv_tag_pack",
120 | order = 3,
121 | name = "Jumbo Tag Pack",
122 | config = {
123 | extra = 4,
124 | choose = 1
125 | },
126 | weight = 1,
127 | kind = "Tag",
128 | cost = 6,
129 | yes_pool_flag = "Tag or Die",
130 | pos = {
131 | x = 2,
132 | y = 0
133 | },
134 | create_card = create_tag_pack_card,
135 | ease_background_colour = ease_tag_pack_colour
136 | },
137 | {
138 | key = "tag_mega_1",
139 | group_key = "k_dvrprv_tag_pack",
140 | order = 4,
141 | name = "Mega Tag Pack",
142 | config = {
143 | extra = 4,
144 | choose = 2
145 | },
146 | weight = 0.25,
147 | kind = "Tag",
148 | cost = 8,
149 | yes_pool_flag = "Tag or Die",
150 | pos = {
151 | x = 3,
152 | y = 0
153 | },
154 | create_card = create_tag_pack_card,
155 | ease_background_colour = ease_tag_pack_colour
156 | },
157 | {
158 | key = "crazy_lucky_1",
159 | group_key = "k_dvrprv_crazy_pack",
160 | order = 6,
161 | name = "Pack",
162 | config = {
163 | extra = 4,
164 | choose = 1,
165 | weights = {
166 | ["Joker"] = 1,
167 | ["Consumeables"] = 0.75,
168 | ["Playing"] = 1,
169 | ["Tag"] = 0.15,
170 | ["Voucher"] = 0.05,
171 | ["Cine"] = 0.01
172 | }
173 | },
174 | weight = 1,
175 | kind = "Crazy",
176 | cost = 6,
177 | yes_pool_flag = "Crazy Lucky",
178 | pos = {
179 | x = 4,
180 | y = 0
181 | },
182 | create_card = create_crazy_pack_card,
183 | ease_background_colour = ease_crazy_pack_colour,
184 | sparkles = crazy_pack_sparkles
185 | },
186 | {
187 | key = "film_normal_1",
188 | group_key = "k_dvrprv_film_pack",
189 | order = 7,
190 | name = "Film Pack",
191 | config = {
192 | extra = 2,
193 | choose = 1
194 | },
195 | weight = 1,
196 | kind = "Cine",
197 | cost = 4,
198 | pos = {
199 | x = 1,
200 | y = 1
201 | },
202 | create_card = create_film_pack_card,
203 | ease_background_colour = ease_film_pack_colour,
204 | meteors = film_pack_meteors
205 | },
206 | {
207 | key = "film_normal_2",
208 | group_key = "k_dvrprv_film_pack",
209 | order = 8,
210 | name = "Film Pack",
211 | config = {
212 | extra = 2,
213 | choose = 1
214 | },
215 | weight = 1,
216 | kind = "Cine",
217 | cost = 4,
218 | pos = {
219 | x = 2,
220 | y = 1
221 | },
222 | create_card = create_film_pack_card,
223 | ease_background_colour = ease_film_pack_colour,
224 | meteors = film_pack_meteors
225 | },
226 | {
227 | key = "film_jumbo_1",
228 | group_key = "k_dvrprv_film_pack",
229 | order = 9,
230 | name = "Jumbo Film Pack",
231 | config = {
232 | extra = 4,
233 | choose = 1
234 | },
235 | weight = 0.6,
236 | kind = "Cine",
237 | cost = 6,
238 | pos = {
239 | x = 3,
240 | y = 1
241 | },
242 | create_card = create_film_pack_card,
243 | ease_background_colour = ease_film_pack_colour,
244 | meteors = film_pack_meteors
245 | },
246 | {
247 | key = "film_mega_1",
248 | group_key = "k_dvrprv_film_pack",
249 | order = 10,
250 | name = "Mega Film Pack",
251 | config = {
252 | extra = 2,
253 | choose = 1
254 | },
255 | weight = 0.07,
256 | kind = "Cine",
257 | cost = 8,
258 | pos = {
259 | x = 4,
260 | y = 1
261 | },
262 | create_card = create_film_pack_card,
263 | ease_background_colour = ease_film_pack_colour,
264 | meteors = film_pack_meteors
265 | }
266 | }
267 |
268 | for _, v in pairs(Reverie.boosters) do
269 | v.atlas = "cine_boosters"
270 | v.loc_vars = loc_vars
271 | v.generate_ui = generate_ui
272 | v.generate_detailed_tooltip = generate_detailed_tooltip
273 |
274 | SMODS.Booster(v)
275 | end
--------------------------------------------------------------------------------
/data/joker_display.lua:
--------------------------------------------------------------------------------
1 | -- JokerDisplay by nh6574
2 | -- https://github.com/nh6574/JokerDisplay/blob/main/src/display_functions.lua
3 |
4 | local progress_text = {
5 | { ref_table = "card.ability", ref_value = "progress", colour = Reverie.badge_colour },
6 | { text = "/" },
7 | { ref_table = "card.ability.extra", ref_value = "goal" }
8 | }
9 |
10 | function Card:update_cine_display(force_update, force_reload, _from)
11 | if self.ability and self.ability.set == "Cine" then
12 | if not self.children.joker_display then
13 | self.joker_display_values = {}
14 | self.joker_display_values.disabled = JokerDisplay.config.hide_by_default
15 | self.joker_display_values.small = false
16 |
17 | --Regular Display
18 | self.children.joker_display = JokerDisplayBox(self, "joker_display_disable", { type = "NORMAL" })
19 | self.children.joker_display_small = JokerDisplayBox(self, "joker_display_small_enable", { type = "SMALL" })
20 | self.children.joker_display_debuff = JokerDisplayBox(self, "joker_display_debuff", { type = "DEBUFF" })
21 | self:initialize_joker_display()
22 |
23 | --Perishable Display
24 | self.config.joker_display_perishable = {
25 | n = G.UIT.ROOT,
26 | config = {
27 | minh = 0.5,
28 | maxh = 0.5,
29 | minw = 0.75,
30 | maxw = 0.75,
31 | r = 0.001,
32 | padding = 0.1,
33 | align = 'cm',
34 | colour = adjust_alpha(darken(G.C.BLACK, 0.2), 0.8),
35 | shadow = false,
36 | func = 'joker_display_perishable',
37 | ref_table = self
38 | },
39 | nodes = {
40 | {
41 | n = G.UIT.R,
42 | config = { align = "cm" },
43 | nodes = { { n = G.UIT.R, config = { align = "cm" }, nodes = { JokerDisplay.create_display_text_object({ ref_table = self.joker_display_values, ref_value = "perishable", colour = lighten(G.C.PERISHABLE, 0.35), scale = 0.35 }) } } }
44 | }
45 |
46 | }
47 | }
48 |
49 | self.config.joker_display_perishable_config = {
50 | align = "tl",
51 | bond = 'Strong',
52 | parent = self,
53 | offset = { x = 0.8, y = 0 },
54 | }
55 | if self.config.joker_display_perishable then
56 | self.children.joker_display_perishable = UIBox {
57 | definition = self.config.joker_display_perishable,
58 | config = self.config.joker_display_perishable_config,
59 | }
60 | self.children.joker_display_perishable.states.collide.can = true
61 | self.children.joker_display_perishable.name = "JokerDisplay"
62 | end
63 |
64 | --Rental Display
65 | self.config.joker_display_rental = {
66 | n = G.UIT.ROOT,
67 | config = {
68 | minh = 0.5,
69 | maxh = 0.5,
70 | minw = 0.75,
71 | maxw = 0.75,
72 | r = 0.001,
73 | padding = 0.1,
74 | align = 'cm',
75 | colour = adjust_alpha(darken(G.C.BLACK, 0.2), 0.8),
76 | shadow = false,
77 | func = 'joker_display_rental',
78 | ref_table = self
79 | },
80 | nodes = {
81 | {
82 | n = G.UIT.R,
83 | config = { align = "cm" },
84 | nodes = { { n = G.UIT.R, config = { align = "cm" }, nodes = { JokerDisplay.create_display_text_object({ ref_table = self.joker_display_values, ref_value = "rental", colour = G.C.GOLD, scale = 0.35 }) } } }
85 | }
86 |
87 | }
88 | }
89 |
90 | self.config.joker_display_rental_config = {
91 | align = "tr",
92 | bond = 'Strong',
93 | parent = self,
94 | offset = { x = -0.8, y = 0 },
95 | }
96 | if self.config.joker_display_rental then
97 | self.children.joker_display_rental = UIBox {
98 | definition = self.config.joker_display_rental,
99 | config = self.config.joker_display_rental_config,
100 | }
101 | self.children.joker_display_rental.states.collide.can = true
102 | self.children.joker_display_rental.name = "JokerDisplay"
103 | end
104 | else
105 | if force_update or (JokerDisplay.config.enabled and
106 | (self:joker_display_has_info() or not JokerDisplay.config.hide_empty)
107 | and (not self.joker_display_values.disabled)) then
108 | if force_reload then
109 | self:initialize_joker_display()
110 | else
111 | self:calculate_joker_display()
112 | end
113 | end
114 | end
115 | end
116 | end
117 |
118 | local card_update_ref = Card.update
119 | function Card:update(dt)
120 | card_update_ref(self, dt)
121 |
122 | if JokerDisplay.config.enabled and Reverie.config.jokerdisplay_compat and G.cine_quests and self.area == G.cine_quests then
123 | if not self.joker_display_last_update_time then
124 | self.joker_display_last_update_time = 0
125 | self.joker_display_update_time_variance = math.random()
126 | local joker_number_delta_variance = math.max(0.2, #G.jokers.cards / 20)
127 | self.joker_display_next_update_time = joker_number_delta_variance / 2 +
128 | joker_number_delta_variance / 2 * self.joker_display_update_time_variance
129 | elseif self.joker_display_values and G.real_dt > 0.05 and #G.jokers.cards > 20 then
130 | self.joker_display_values.disabled = true
131 | else
132 | self.joker_display_last_update_time = self.joker_display_last_update_time + dt
133 | if self.joker_display_last_update_time > self.joker_display_next_update_time then
134 | self.joker_display_last_update_time = 0
135 | local joker_number_delta_variance = math.max(0.2, #G.jokers.cards / 20)
136 | self.joker_display_next_update_time = joker_number_delta_variance / 2 +
137 | joker_number_delta_variance / 2 * self.joker_display_update_time_variance
138 | self:update_cine_display(false, false, "Card:update")
139 | end
140 | end
141 | end
142 | end
143 |
144 | Reverie.joker_display_definitions = {
145 | c_dvrprv_ive_no_shape_quest = {
146 | text = progress_text,
147 | reminder_text = {
148 | { text = "(" },
149 | { text = "X", colour = G.C.ORANGE },
150 | { ref_table = "card.ability.extra", ref_value = "chips", colour = G.C.ORANGE },
151 | { text = " Chips)" }
152 | }
153 | },
154 | c_dvrprv_unseen_quest = {
155 | text = progress_text,
156 | reminder_text = {
157 | { text = "(" },
158 | { ref_table = "card.ability.extra", ref_value = "slots", colour = G.C.ORANGE },
159 | { text = " Joker slot", colour = G.C.ORANGE },
160 | { text = ")" }
161 | }
162 | },
163 | c_dvrprv_gem_heist_quest = {
164 | text = progress_text,
165 | reminder_text = {
166 | { text = "(" },
167 | { text = "Editioned Joker", colour = G.C.DARK_EDITION },
168 | { text = ")" }
169 | }
170 | },
171 | c_dvrprv_crazy_lucky_quest = {
172 | text = progress_text,
173 | reminder_text = {
174 | { text = "(" },
175 | { text = "Booster Pack", colour = G.C.ORANGE },
176 | { text = ")" }
177 | }
178 | },
179 | c_dvrprv_tag_or_die_quest = {
180 | text = progress_text,
181 | reminder_text = {
182 | { text = "(" },
183 | { text = "Skip Blind", colour = G.C.ORANGE },
184 | { text = ")" }
185 | }
186 | },
187 | c_dvrprv_let_it_moon_quest = {
188 | text = progress_text,
189 | reminder_text = {
190 | { text = "(" },
191 | { text = "Planet", colour = G.C.SECONDARY_SET.Planet },
192 | { text = "/" },
193 | { text = "Tarot", colour = G.C.SECONDARY_SET.Tarot },
194 | { text = ")" }
195 | }
196 | },
197 | c_dvrprv_poker_face_quest = {
198 | text = progress_text,
199 | reminder_text = {
200 | { text = "(" },
201 | { text = "Enhance", colour = G.C.ORANGE },
202 | { text = ")" }
203 | }
204 | },
205 | c_dvrprv_eerie_inn_quest = {
206 | text = progress_text,
207 | reminder_text = {
208 | { text = "(" },
209 | { text = "Destroy", colour = G.C.ORANGE },
210 | { text = ")" }
211 | }
212 | },
213 | c_dvrprv_adrifting_quest = {
214 | text = progress_text,
215 | reminder_text = {
216 | { text = "(" },
217 | { text = "Debuffed", colour = G.C.ORANGE },
218 | { text = "/" },
219 | { text = "Flipped", colour = G.C.ORANGE },
220 | { text = ")" }
221 | }
222 | },
223 | c_dvrprv_morsel_quest = {
224 | text = progress_text,
225 | reminder_text = {
226 | { text = "(" },
227 | { text = "Food Joker", colour = G.C.ORANGE },
228 | { text = ")" }
229 | }
230 | },
231 | c_dvrprv_alchemist_quest = {
232 | text = progress_text,
233 | reminder_text = {
234 | { text = "(" },
235 | { text = "Alchemical", colour = G.C.ORANGE },
236 | { text = ")" }
237 | }
238 | },
239 | c_dvrprv_every_hue_quest = {
240 | text = progress_text,
241 | reminder_text = {
242 | { text = "(" },
243 | { text = "Colour", colour = G.C.ORANGE },
244 | { text = ")" }
245 | }
246 | },
247 | c_dvrprv_radioactive_quest = {
248 | text = progress_text,
249 | reminder_text = {
250 | { text = "(" },
251 | { text = "Fusion", colour = G.C.GOLD },
252 | { text = ")" }
253 | }
254 | },
255 | c_dvrprv_jovial_m_quest = {
256 | text = progress_text,
257 | reminder_text = {
258 | { text = "(" },
259 | { ref_table = "card.joker_display_values", ref_value = "localized_text", colour = G.C.ORANGE },
260 | { text = ")" }
261 | },
262 | calc_function = function (card)
263 | card.joker_display_values.localized_text = localize{
264 | type = "name_text",
265 | set = "Joker",
266 | key = "j_jolly"
267 | }
268 | end
269 | }
270 | }
271 |
272 | for k, v in pairs(Reverie.joker_display_definitions) do
273 | JokerDisplay.Definitions[k] = v
274 | end
--------------------------------------------------------------------------------
/localization/ko.lua:
--------------------------------------------------------------------------------
1 | return {
2 | descriptions = {
3 | Cine = {
4 | c_ive_no_shape_quest = {
5 | name = "교환권",
6 | text = {
7 | "필요한 칩의 {C:attention}#1#{}배 이상을 획득해",
8 | "{C:attention}#2#{}개의 {C:attention}블라인드{}에서 승리하면",
9 | "{C:cine}허무한 허무함을 보라{}로 바뀝니다",
10 | "{C:inactive}(현재 {C:attention}#3#{C:inactive}/#2#)"
11 | }
12 | },
13 | c_ive_no_shape = {
14 | name = "허무한 허무함을 보라",
15 | text = {
16 | "이번 상점 동안에는",
17 | "보유 중인 {C:attention}조커{}만",
18 | "나타납니다",
19 | "새로고침 비용 {C:red}+$#1#"
20 | }
21 | },
22 | c_unseen_quest = {
23 | name = "교환권",
24 | text = {
25 | "{C:attention}#2#{} 라운드 동안 {C:attention}조커{} 슬롯 {C:attention}#1#{}개를",
26 | "비워 두면 {C:cine}불가시{}로 바뀝니다",
27 | "{C:inactive}(현재 {C:attention}#3#{C:inactive}/#2#)"
28 | }
29 | },
30 | c_unseen = {
31 | name = "불가시",
32 | text = {
33 | "이번 상점 동안에는",
34 | "모든 {C:attention}조커{}와 {C:attention}소모품{}이",
35 | "{C:dark_edition}네거티브{}가 됩니다",
36 | "새로고침 비용 {C:red}#1#{}배",
37 | "{s:0.8}카드 새로고침"
38 | }
39 | },
40 | c_gem_heist_quest = {
41 | name = "교환권",
42 | text = {
43 | "{C:attention}에디션{} 있는 {C:attention}조커 #1#{}장을 판매하면",
44 | "{C:cine}보석 강탈 사건{}으로 바뀝니다",
45 | "{C:inactive}(현재 {C:attention}#2#{C:inactive}/#1#)"
46 | }
47 | },
48 | c_gem_heist = {
49 | name = "보석 강탈 사건",
50 | text = {
51 | "이번 상점 동안에는",
52 | "모든 카드가 {C:dark_edition}홀로그래픽{}이",
53 | "되고 {C:attention}25%{} 할인됩니다",
54 | "{s:0.8}카드 새로고침"
55 | }
56 | },
57 | c_crazy_lucky_quest = {
58 | name = "교환권",
59 | text = {
60 | "{C:attention}부스터 팩 #1#{}개를 열면",
61 | "{C:cine}크레이지 럭키{}로 바뀝니다",
62 | "{C:inactive}(현재 {C:attention}#2#{C:inactive}/#1#)"
63 | }
64 | },
65 | c_crazy_lucky = {
66 | name = "크레이지 럭키",
67 | text = {
68 | "이번 상점 동안에는",
69 | "{C:attention}팩{}만 나타납니다",
70 | "{s:0.8,C:attention}부스터 팩 {s:0.8}새로고침"
71 | }
72 | },
73 | c_tag_or_die_quest = {
74 | name = "교환권",
75 | text = {
76 | "{C:attention}블라인드 #1#{}개를 건너뛰면",
77 | "{C:cine}위기일발{}로 바뀝니다",
78 | "{C:inactive}(현재 {C:attention}#2#{C:inactive}/#1#)"
79 | }
80 | },
81 | c_tag_or_die = {
82 | name = "위기일발",
83 | text = {
84 | "이번 상점 동안에는",
85 | "{C:money}$#1#{}로 구매 가능한",
86 | "{C:attention}태그{}만 나타납니다",
87 | "{s:0.8,C:attention}부스터 팩 {s:0.8}새로고침"
88 | }
89 | },
90 | c_let_it_moon_quest = {
91 | name = "교환권",
92 | text = {
93 | "{C:planet}행성{} 또는 {C:tarot}타로{} 카드를 {C:attention}#1#{}장",
94 | "사용하면 {C:cine}렛 잇 문{}으로 바뀝니다",
95 | "{C:inactive}(현재 {C:attention}#2#{C:inactive}/#1#)"
96 | }
97 | },
98 | c_let_it_moon = {
99 | name = "렛 잇 문",
100 | text = {
101 | "이번 상점 동안에는",
102 | "{C:planet}행성{}과 {C:tarot}타로{} 카드만",
103 | "나타납니다",
104 | "{s:0.8,C:attention}부스터 팩 {s:0.8}새로고침"
105 | }
106 | },
107 | c_poker_face_quest = {
108 | name = "교환권",
109 | text = {
110 | "{C:attention}플레잉 카드 #1#{}장을 {C:attention}강화{}하면",
111 | "{C:cine}포커 페이스{}로 바뀝니다",
112 | "{C:inactive}(현재 {C:attention}#2#{C:inactive}/#1#)"
113 | }
114 | },
115 | c_poker_face = {
116 | name = "포커 페이스",
117 | text = {
118 | "이번 상점 동안에는",
119 | "덱에 있는 {C:attention}플레잉 카드{}만",
120 | "나타납니다",
121 | "{s:0.8,C:attention}부스터 팩 {s:0.8}새로고침"
122 | }
123 | },
124 | c_eerie_inn_quest = {
125 | name = "교환권",
126 | text = {
127 | "카드를 {C:attention}#1#{}장 파괴하면",
128 | "{C:cine}오싹한 여관{}으로 바뀝니다",
129 | "{C:inactive}(현재 {C:attention}#2#{C:inactive}/#1#)"
130 | }
131 | },
132 | c_eerie_inn = {
133 | name = "오싹한 여관",
134 | text = {
135 | "이번 상점 동안에는",
136 | "{C:spectral}유령 팩{}만 나타납니다",
137 | "새로고침 비용 {C:red}#1#{}배",
138 | "{s:0.8,C:attention}부스터 팩 {s:0.8}새로고침"
139 | }
140 | },
141 | c_adrifting_quest = {
142 | name = "교환권",
143 | text = {
144 | "{C:attention}디버프{}됐거나 {C:attention}뒤집힌{} 카드 {C:attention}#1#{}장을",
145 | "플레이하면 {C:cine}파랑 끝에서{}로 바뀝니다",
146 | "{C:inactive}(현재 {C:attention}#2#{C:inactive}/#1#)"
147 | }
148 | },
149 | c_adrifting = {
150 | name = "파랑 끝에서",
151 | text = {
152 | "이번 상점 동안에는",
153 | "모든 것이 {C:attention}무료{}지만",
154 | "{C:attention}뒤집혀서{} 나타납니다",
155 | "카드 및 {s:0.8,C:attention}부스터 팩 {s:0.8}새로고침"
156 | }
157 | },
158 | c_morsel_quest = {
159 | name = "교환권",
160 | text = {
161 | "{C:attention}음식 조커 #1#{}장을 획득하면",
162 | "{C:cine}식탁의 길이{}로 바뀝니다",
163 | "{C:inactive}(현재 {C:attention}#2#{C:inactive}/#1#)"
164 | }
165 | },
166 | c_morsel = {
167 | name = "식탁의 길이",
168 | text = {
169 | "이번 상점 동안에는",
170 | "모든 능력치가 {C:attention}두 배{}가 된",
171 | "{C:attention}음식 조커{}만 나타납니다",
172 | "{s:0.8,C:attention}부스터 팩 {s:0.8}새로고침"
173 | }
174 | },
175 | c_alchemist_quest = {
176 | name = "교환권",
177 | text = {
178 | "{C:alchemical}연금술{} 카드를 {C:attention}#1#{}장 사용하면",
179 | "{C:cine}풀 메탈 알케미스트{}로 바뀝니다",
180 | "{C:inactive}(현재 {C:attention}#2#{C:inactive}/#1#)"
181 | }
182 | },
183 | c_alchemist = {
184 | name = "풀 메탈 알케미스트",
185 | text = {
186 | "이번 상점 동안에는",
187 | "소모품 슬롯이 {C:attention}+#1#{}개 증가하고",
188 | "{C:alchemical}연금술{} 카드만 나타납니다",
189 | "{s:0.8,C:attention}부스터 팩 {s:0.8}새로고침"
190 | }
191 | },
192 | c_every_hue_quest = {
193 | name = "교환권",
194 | text = {
195 | "{C:colourcard}색상{} 카드를 {C:attention}#1#{}장 사용하면",
196 | "{C:cine}모든 빛깔의{}로 바뀝니다",
197 | "{C:inactive}(현재 {C:attention}#2#{C:inactive}/#1#)"
198 | }
199 | },
200 | c_every_hue = {
201 | name = "모든 빛깔의",
202 | text = {
203 | "이번 상점 동안에는",
204 | "{C:attention}#1# 라운드{}가 추가된",
205 | "{C:colourcard}색상{} 카드만 나타납니다",
206 | "{s:0.8,C:attention}부스터 팩 {s:0.8}새로고침"
207 | }
208 | },
209 | c_radioactive_quest = {
210 | name = "교환권",
211 | text = {
212 | "{C:colourcard}융합{} 조커를 {C:attention}#1#{}장 획득하면",
213 | "{C:cine}라디오액티브{}로 바뀝니다",
214 | "{C:inactive}(현재 {C:attention}#2#{C:inactive}/#1#)"
215 | }
216 | },
217 | c_radioactive = {
218 | name = "라디오액티브",
219 | text = {
220 | "이번 상점 동안에는",
221 | "{C:attention}융합{}에 사용될 수 있는",
222 | "{C:attention}조커{}만 나타납니다",
223 | "{s:0.8,C:attention}부스터 팩 {s:0.8}새로고침"
224 | }
225 | }
226 | },
227 | Joker = {
228 | j_diet_cola_morsel_alternative = {
229 | text = {
230 | ".",
231 | ".",
232 | "두 개 생성합니다",
233 | }
234 | },
235 | j_dynamic_film = {
236 | name = "역동적인 필름",
237 | text = {
238 | "이 조커는 {C:cine}교환권{}에",
239 | "진척도가 쌓일 때마다",
240 | "칩 획득량이 {C:chips}+#2#{}개 증가합니다",
241 | "{C:inactive}(현재 칩 {C:chips}+#1#{C:inactive}개)"
242 | }
243 | }
244 | },
245 | Back = {
246 | b_filmstrip = {
247 | name = "필름스트립 덱",
248 | text = {
249 | "{C:cine}영화{} 카드가 중첩될 수 있습니다",
250 | "영화 슬롯 {C:attention}+#1#{}개"
251 | }
252 | },
253 | b_stamp = {
254 | name = "스탬프 덱",
255 | text = {
256 | "{C:attention}블라인드{}를 건너뛰면",
257 | "{C:attention,T:p_tag_jumbo_1}#1#{}을 대신 획득합니다"
258 | }
259 | }
260 | },
261 | Tag = {
262 | tag_cine = {
263 | name = "반쪽 태그",
264 | text = {
265 | "무료 {C:cine}영화 팩{}을",
266 | "획득합니다"
267 | }
268 | },
269 | tag_tag = {
270 | name = "기호 태그",
271 | text = {
272 | "무료 {C:attention}태그 팩{}을",
273 | "획득합니다"
274 | }
275 | },
276 | tag_mega_tag = {
277 | name = "도장 태그",
278 | text = {
279 | "무료 {C:attention}점보 태그 팩{}을",
280 | "획득합니다"
281 | }
282 | }
283 | },
284 | Spectral = {
285 | c_reverie = {
286 | name = "몽상",
287 | text = {
288 | "이번 상점에",
289 | "모든 {C:cine,E:1}영화 카드{}를",
290 | "적용합니다"
291 | }
292 | }
293 | },
294 | Voucher = {
295 | v_script = {
296 | name = "각본",
297 | text = {
298 | "{C:cine}영화{} 카드가 활성화된 동안",
299 | "상점의 카드 판매 슬롯이",
300 | "{C:attention}+#1#{}개 증가합니다"
301 | }
302 | },
303 | v_megaphone = {
304 | name = "확성기",
305 | text = {
306 | "{C:cine}교환권{} 달성 목표가",
307 | "절반으로 줄어듭니다"
308 | }
309 | }
310 | },
311 | Edition = {
312 | e_negative_cine = {
313 | name = "네거티브",
314 | text = {
315 | "영화 슬롯 {C:dark_edition}+#1#{}개"
316 | }
317 | }
318 | },
319 | Other = {
320 | p_tag_normal = {
321 | name = "태그 팩",
322 | text = {
323 | "최대 {C:attention}#2#{}개의 {C:attention}태그{} 중",
324 | "{C:attention}#1#{}개를 선택합니다"
325 | }
326 | },
327 | p_tag_jumbo = {
328 | name = "점보 태그 팩",
329 | text = {
330 | "최대 {C:attention}#2#{}개의 {C:attention}태그{} 중",
331 | "{C:attention}#1#{}개를 선택합니다"
332 | }
333 | },
334 | p_tag_mega = {
335 | name = "메가 태그 팩",
336 | text = {
337 | "최대 {C:attention}#2#{}개의 {C:attention}태그{} 중",
338 | "{C:attention}#1#{}개를 선택합니다"
339 | }
340 | },
341 | p_crazy_lucky = {
342 | name = "팩",
343 | text = {
344 | "최대 {C:attention}#2#{}개의 {C:attention,E:1}아무거나{} 중",
345 | "{C:attention}#1#{}개를 선택해 보유합니다"
346 | }
347 | },
348 | p_adrifting = {
349 | name = "뒤집힌 팩",
350 | text = {
351 | "{C:attention}무언가{} 중",
352 | "{C:attention}몇 개{}를 선택합니다"
353 | }
354 | },
355 | p_film_normal = {
356 | name = "영화 팩",
357 | text = {
358 | "최대 {C:attention}#2#{}개의 {C:cine}교환권{} 중",
359 | "{C:attention}#1#{}개를 선택해 보유합니다"
360 | }
361 | },
362 | p_film_jumbo = {
363 | name = "점보 영화 팩",
364 | text = {
365 | "최대 {C:attention}#2#{}개의 {C:cine}교환권{} 중",
366 | "{C:attention}#1#{}개를 선택해 보유합니다"
367 | }
368 | },
369 | p_film_mega = {
370 | name = "메가 영화 팩",
371 | text = {
372 | "최대 {C:attention}#2#{}개의 {C:cine}영화{} 카드 중",
373 | "{C:attention}#1#{}개를 선택해 보유합니다"
374 | }
375 | },
376 | undiscovered_cine = {
377 | name = "발견되지 않음",
378 | text = {
379 | "시드를 설정하지 않은",
380 | "런에서 이 카드를",
381 | "구매하거나 사용하여",
382 | "기능을 알아보세요",
383 | }
384 | },
385 | undiscovered_cine_quest = {
386 | name = "발견되지 않음",
387 | text = {
388 | "시드를 설정하지 않은",
389 | "런에서 이 카드를",
390 | "구매하거나 사용하여",
391 | "기능을 알아보세요",
392 | }
393 | },
394 | morseled = {
395 | name = "식탁의 길이",
396 | text = {
397 | "모든 능력치가",
398 | "{C:attention}두 배{}로 증가했습니다"
399 | }
400 | },
401 | }
402 | },
403 | misc = {
404 | dictionary = {
405 | k_cine = "영화",
406 | k_tag = "태그",
407 | k_tag_pack = "태그 팩",
408 | k_crazy_pack = "팩",
409 | k_film_pack = "영화 팩",
410 | b_cine_cards = "영화 카드"
411 | }
412 | }
413 | }
--------------------------------------------------------------------------------
/lovely.toml:
--------------------------------------------------------------------------------
1 | [manifest]
2 | version = "1.0.0"
3 | dump_lua = true
4 | priority = 0
5 |
6 | [[patches]]
7 | [patches.pattern]
8 | target = "functions/common_events.lua"
9 | pattern = '''local _area = G.P_CENTERS[joker].consumeable and G.consumeables or G.jokers'''
10 | position = "after"
11 | payload = '''
12 | if G.P_CENTERS[joker].set == "Cine" then
13 | _area = G.cine_quests
14 | end
15 | '''
16 | match_indent = true
17 |
18 | [[patches]]
19 | [patches.pattern]
20 | target = "functions/common_events.lua"
21 | pattern = '''elseif G.consumeables then G.consumeables:emplace(card) end'''
22 | position = "before"
23 | payload = '''
24 | elseif G.cine_quests and card.ability.set == "Cine" then
25 | G.cine_quests:emplace(card)
26 | '''
27 | match_indent = true
28 |
29 | [[patches]]
30 | [patches.pattern]
31 | target = "game.lua"
32 | pattern = '''G.playing_cards = {}'''
33 | position = "before"
34 | payload = '''
35 | self.cine_quests = CardArea(0, 0, CAI.deck_W, CAI.deck_H, {
36 | card_limit = self.GAME.starting_params.cine_quest_slots,
37 | type = "joker",
38 | highlight_limit = 1
39 | })
40 | '''
41 | match_indent = true
42 |
43 | [[patches]]
44 | [patches.pattern]
45 | target = "main.lua"
46 | pattern = '''not c.ending_shop and not c.reroll_shop and not c.selling_card and not c.selling_self and not c.buying_card and'''
47 | position = "after"
48 | payload = '''
49 | not c.cine_progress and not c.joker_added and not c.enhancing_card
50 | and not c.debuff_or_flipped_played and not c.any_card_destroyed and
51 | '''
52 | match_indent = true
53 |
54 | [[patches]]
55 | [patches.pattern]
56 | target = "functions/common_events.lua"
57 | pattern = '''for _, v in ipairs(info_queue) do'''
58 | position = "after"
59 | payload = '''
60 | if v.key == "e_negative_consumable" and _c.set == "Cine" then
61 | v.key = "e_negative_cine"
62 | end
63 | '''
64 | match_indent = true
65 |
66 | [[patches]]
67 | [patches.pattern]
68 | target = "tag.lua"
69 | pattern = '''tag_sprite.ability_UIBox_table = generate_card_ui(G.P_TAGS[self.key], nil, loc_vars, (self.hide_ability) and 'Undiscovered' or 'Tag', nil, (self.hide_ability))'''
70 | position = "before"
71 | payload = '''
72 | if self.ability.as_card and name_to_check == "Skip Tag" then
73 | loc_vars[2] = self.config.skip_bonus * (G.GAME.skips or 0)
74 | end
75 | '''
76 | match_indent = true
77 |
78 | # Add fallback for Cine card
79 | [[patches]]
80 | [patches.pattern]
81 | target = "functions/common_events.lua"
82 | pattern = '''elseif _type == 'Tag' then _pool[#_pool + 1] = "tag_handy"'''
83 | position = "after"
84 | payload = '''
85 | elseif _type == "Cine" then _pool[#_pool + 1] = "c_dvrprv_gem_heist"
86 | elseif _type == "Cine_Quest" then _pool[#_pool + 1] = "c_dvrprv_gem_heist_quest"'''
87 | match_indent = true
88 |
89 | # Make the card uses Tags' sprite atlas
90 | [[patches]]
91 | [patches.pattern]
92 | target = "card.lua"
93 | pattern = '''self.children.center = Sprite(self.T.x, self.T.y, self.T.w, self.T.h, G.ASSET_ATLAS[_center.set], self.config.center.pos)'''
94 | position = "after"
95 | payload = '''
96 | elseif _center.set == "Tag" then
97 | self.children.center = Sprite(self.T.x, self.T.y, self.T.w, self.T.h, G.ASSET_ATLAS[_center.atlas or "tags"], self.config.center.pos)
98 | '''
99 | match_indent = true
100 |
101 | # Disable buy space check for Tags
102 | [[patches]]
103 | [patches.pattern]
104 | target = "functions/button_callbacks.lua"
105 | pattern = '''card.ability.set ~= 'Default' and'''
106 | position = "before"
107 | payload = '''
108 | card.ability.set ~= "Tag" and
109 | '''
110 | match_indent = true
111 |
112 | # Prevent Tags from being added to the deck
113 | [[patches]]
114 | [patches.pattern]
115 | target = "functions/button_callbacks.lua"
116 | pattern = '''c1:add_to_deck()'''
117 | position = "after"
118 | payload = '''
119 | ::reverie_buy_from_shop_tag_skip::'''
120 | match_indent = true
121 |
122 | [[patches]]
123 | [patches.pattern]
124 | target = "functions/button_callbacks.lua"
125 | pattern = '''c1:add_to_deck()'''
126 | position = "before"
127 | payload = '''
128 | if c1.ability.set == "Tag" then
129 | goto reverie_buy_from_shop_tag_skip
130 | end'''
131 | match_indent = true
132 |
133 | # When Tags are purchased, properly add them to the game and remove from the shop
134 | # Applying immediate tags is handled in injected update_shop()
135 | [[patches]]
136 | [patches.pattern]
137 | target = "functions/button_callbacks.lua"
138 | pattern = '''elseif e.config.id ~= 'buy_and_use' then'''
139 | position = "before"
140 | payload = '''
141 | elseif c1.ability.set == "Tag" then
142 | add_tag(c1.ability.tag)
143 | c1:remove()
144 |
145 | play_sound("generic1", 0.9 + math.random() * 0.1, 0.8)
146 | play_sound("holo1", 1.2 + math.random() * 0.1, 0.4)
147 | '''
148 | match_indent = true
149 |
150 | [[patches]]
151 | [patches.regex]
152 | target = "card.lua"
153 | pattern = '''(?\s{20})elseif self.ability.name:find.'Buffoon'. then(\n.*?)*?\n\s{20}end'''
154 | position = "after"
155 | line_prepend = "$indent"
156 | payload = '''
157 |
158 | ::reverie_skip_create_card::
159 | '''
160 |
161 | [[patches]]
162 | [patches.pattern]
163 | target = "card.lua"
164 | pattern = '''card = create_card((pseudorandom(pseudoseed('stdset'..G.GAME.round_resets.ante)) > 0.6)*'''
165 | position = "before"
166 | payload = '''
167 | if Reverie.find_used_cine("Poker Face") then
168 | card = Reverie.create_poker_face_card(G.pack_cards)
169 | goto reverie_skip_create_card
170 | end
171 | '''
172 | match_indent = true
173 |
174 | [[patches]]
175 | [patches.pattern]
176 | target = "card.lua"
177 | pattern = '''card = create_card("Joker", G.pack_cards, nil, nil, true, true, nil, 'buf')'''
178 | position = "before"
179 | payload = '''
180 | card = Reverie.create_special_joker(G.pack_cards)
181 |
182 | if card then
183 | goto reverie_skip_create_card
184 | end
185 | '''
186 | match_indent = true
187 |
188 | [[patches]]
189 | [patches.pattern]
190 | target = "functions/button_callbacks.lua"
191 | pattern = '''e.config.ref_table:redeem()'''
192 | position = "after"
193 | payload = '''
194 | elseif card.ability.set == "Tag" then
195 | add_tag(card.ability.tag)
196 | card:remove()
197 |
198 | play_sound("generic1", 0.9 + math.random() * 0.1, 0.8)
199 | play_sound("holo1", 1.2 + math.random() * 0.1, 0.4)
200 |
201 | for _, v in ipairs(G.GAME.tags) do
202 | v:apply_to_run({type = "immediate"})
203 | end
204 |
205 | dont_dissolve = true
206 | delay_fac = 0.2'''
207 | match_indent = true
208 |
209 | [[patches]]
210 | [patches.pattern]
211 | target = "card.lua"
212 | pattern = '''(self.ability.set == 'Spectral' and {G.C.SECONDARY_SET.Spectral}) or'''
213 | position = "after"
214 | payload = '''
215 | (self.ability.set == 'Cine' and {G.C.SECONDARY_SET.Cine}) or'''
216 | match_indent = true
217 |
218 | [[patches]]
219 | [patches.pattern]
220 | target = "card.lua"
221 | pattern = '''if self.ability.name == 'Invisible Joker' and (self.config.center.discovered or self.bypass_discovery_center) then'''
222 | position = "before"
223 | payload = '''
224 | if self.ability.set == "Cine" and (not self.edition or not self.edition.negative) then
225 | if self.ability.name == "The Unseen" and (self.config.center.discovered or self.bypass_discovery_center) then
226 | self.children.center:draw_shader("dvrprv_ticket_negative", nil, self.ARGS.send_to_shader)
227 | self.children.center:draw_shader("negative_shine", nil, self.ARGS.send_to_shader)
228 |
229 | if self.children.front then
230 | self.children.front:draw_shader("dvrprv_ticket_negative", nil, self.ARGS.send_to_shader)
231 | end
232 | elseif self.ability.name == "I Sing, I've No Shape" and self.config.center.discovered then
233 | self.children.center:draw_shader("dvrprv_ticket_polychrome", nil, self.ARGS.send_to_shader)
234 | else
235 | self.children.center:draw_shader("dvrprv_ticket", nil, self.ARGS.send_to_shader)
236 | end
237 | end
238 | '''
239 | match_indent = true
240 |
241 | [[patches]]
242 | [patches.pattern]
243 | target = "functions/button_callbacks.lua"
244 | pattern = '''elseif card.ability.set == 'Enhanced' or card.ability.set == 'Default'*'''
245 | position = "before"
246 | payload = '''
247 | ::reverie_use_card_consumable_skip::'''
248 | match_indent = true
249 |
250 | [[patches]]
251 | [patches.pattern]
252 | target = "functions/button_callbacks.lua"
253 | pattern = '''if card.area then card.area:remove_card(card) end'''
254 | position = "before"
255 | payload = '''
256 | local is_pack_card = card.area and card.area == G.pack_cards'''
257 | match_indent = true
258 |
259 | [[patches]]
260 | [patches.pattern]
261 | target = "functions/button_callbacks.lua"
262 | pattern = '''if card.ability.consumeable then'''
263 | position = "after"
264 | payload = '''
265 | local is_cine = Reverie.is_cine_or_reverie(card)
266 | if is_pack_card and (Reverie.is_in_reverie_pack() or is_cine) then
267 | (is_cine and G.cine_quests or G.consumeables):emplace(card)
268 | card:add_to_deck()
269 | play_sound('card1', 0.8, 0.6)
270 | play_sound('generic1')
271 | dont_dissolve = true
272 | delay_fac = 0.2
273 |
274 | goto reverie_use_card_consumable_skip
275 | end'''
276 | match_indent = true
277 |
278 | [[patches]]
279 | [patches.regex]
280 | target = "card.lua"
281 | pattern = '''(?[ \t]*)(?bot_dynatext = DynaText\(\{string = localize\('k_redeemed_ex'\).*(\n.*?)*)(?play_sound\('coin1'\))'''
282 | position = "at"
283 | line_prepend = "$indent"
284 | payload = '''
285 | $capture
286 | if self.cost > 0 then
287 | $target
288 | end
289 | '''
290 |
291 | [[patches]]
292 | [patches.pattern]
293 | target = "functions/common_events.lua"
294 | pattern = '''elseif card.area == G.hand then'''
295 | position = "before"
296 | payload = '''
297 | elseif card.area == G.cine_quests then
298 | y_off = 0.05 * card.T.h'''
299 | match_indent = true
300 |
301 | [[patches]]
302 | [patches.regex]
303 | target = "functions/button_callbacks.lua"
304 | pattern = '''ease_background_colour_blind\(G.GAME.PACK_INTERRUPT\)\n.*\n.*\n.*\n(?[ \t]*)for i = 1, #G\.GAME\.tags do\n'''
305 | position = "after"
306 | line_prepend = "$indent"
307 | payload = '''
308 | if G.shop then
309 | break -- blocking newly gained new_blind_choice tags from triggering in shop
310 | end
311 |
312 | '''
313 |
314 | [[patches]]
315 | [patches.pattern]
316 | target = "card.lua"
317 | pattern = '''self.ability_UIBox_table = self:generate_UIBox_ability_table()'''
318 | position = "after"
319 | payload = '''
320 |
321 | if self.ability.morseled then
322 | Reverie.morselize_UI(self)
323 | end
324 | '''
325 | match_indent = true
326 |
327 | [[patches]]
328 | [patches.regex]
329 | target = "card.lua"
330 | pattern = '''Card:add_to_deck\(from_debuff.*(\n.*?)*(?[\t ]*)G.jokers.config.card_limit = G.jokers.config.card_limit \+ 1'''
331 | position = "after"
332 | line_prepend = "$indent"
333 | payload = '''
334 |
335 | if Reverie.is_cine_or_reverie(self) then
336 | G.consumeables.config.card_limit = G.consumeables.config.card_limit - self.edition.card_limit
337 | G.cine_quests.config.card_limit = G.cine_quests.config.card_limit + self.edition.card_limit
338 | end
339 | '''
340 |
341 | [[patches]]
342 | [patches.regex]
343 | target = "card.lua"
344 | pattern = '''self.edition = \{\}\n.*if self.added_to_deck then.*\n(?[\t ]*)if self.ability.consumeable then(\n.*?)*end'''
345 | position = "after"
346 | line_prepend = "$indent"
347 | payload = '''
348 |
349 | if Reverie.is_cine_or_reverie(self) then
350 | G.consumeables.config.card_limit = G.consumeables.config.card_limit - 1
351 | G.cine_quests.config.card_limit = G.cine_quests.config.card_limit + 1
352 | end
353 | '''
354 |
355 | [[patches]]
356 | [patches.regex]
357 | target = "card.lua"
358 | pattern = '''Card:remove_from_deck\(from_debuff.*(\n.*?)*(?[\t ]*)G.jokers.config.card_limit = G.jokers.config.card_limit - 1'''
359 | position = "after"
360 | line_prepend = "$indent"
361 | payload = '''
362 |
363 | if Reverie.is_cine_or_reverie(self) then
364 | G.consumeables.config.card_limit = G.consumeables.config.card_limit + self.edition.card_limit
365 | G.cine_quests.config.card_limit = G.cine_quests.config.card_limit - self.edition.card_limit
366 | end
367 | '''
368 |
369 | [[patches]]
370 | [patches.regex]
371 | target = "card.lua"
372 | pattern = '''Card:remove\(\).*(\n.*?)*(?[\t ]*)G.jokers.config.card_limit = G.jokers.config.card_limit - 1'''
373 | position = "after"
374 | line_prepend = "$indent"
375 | payload = '''
376 |
377 | if Reverie.is_cine_or_reverie(self) then
378 | G.consumeables.config.card_limit = G.consumeables.config.card_limit + self.edition.card_limit
379 | G.cine_quests.config.card_limit = G.cine_quests.config.card_limit - self.edition.card_limit
380 | end
381 | '''
382 |
383 | [[patches]]
384 | [patches.regex]
385 | target = "functions/button_callbacks.lua"
386 | pattern = '''G\.FUNCS\.reroll_shop.*(\n.*?)*?(?[ \t]*)for i = 1, G\.GAME\.shop\.joker_max - #G\.shop_jokers\.cards do.*(\n.*?)*?.+create_card_for_shop'''
387 | position = "after"
388 | root_capture = "$indent"
389 | line_prepend = "$indent"
390 | payload = '''
391 |
392 | if G.GAME.current_round.used_cine then
393 | for i = 1, G.GAME.shop.joker_max - #G.shop_jokers.cards do
394 | local new_shop_card = Reverie.create_card_for_cine_shop(G.shop_jokers)
395 | G.shop_jokers:emplace(new_shop_card)
396 | new_shop_card:juice_up()
397 | end
398 |
399 | return true
400 | end
401 |
402 | '''
403 |
404 | [[patches]]
405 | [patches.pattern]
406 | target = "functions/common_events.lua"
407 | pattern = '''if v.name == 'Black Hole' or v.name == 'The Soul' then'''
408 | position = "before"
409 | payload = '''
410 | if v.set == "Spectral" and v.name == "Reverie" then
411 | add = false
412 | end
413 | '''
414 | match_indent = true
415 |
416 | [[patches]]
417 | [patches.pattern]
418 | target = "functions/button_callbacks.lua"
419 | pattern = '''e.config.ref_table:use_consumeable(area)'''
420 | position = "after"
421 | payload = '''
422 | e.config.ref_table.ability.not_destroyed = true
423 | '''
424 | match_indent = true
425 |
426 | [[patches]]
427 | [patches.pattern]
428 | target = "functions/button_callbacks.lua"
429 | pattern = '''G.CONTROLLER:recall_cardarea_focus('jokers')'''
430 | position = "after"
431 | payload = '''
432 | ::reverie_buy_from_shop_tag_focus_skip::
433 | '''
434 | match_indent = true
435 |
436 | [[patches]]
437 | [patches.pattern]
438 | target = "functions/button_callbacks.lua"
439 | pattern = '''G.CONTROLLER:save_cardarea_focus('jokers')'''
440 | position = "before"
441 | payload = '''
442 | if c1.ability.set == "Tag" then
443 | G.CONTROLLER:save_cardarea_focus("shop_jokers")
444 | G.CONTROLLER:recall_cardarea_focus("shop_jokers")
445 |
446 | goto reverie_buy_from_shop_tag_focus_skip
447 | end
448 | '''
449 | match_indent = true
450 |
451 | [[patches]]
452 | [patches.pattern]
453 | target = "card.lua"
454 | pattern = '''pack_cards[i] = card'''
455 | position = "after"
456 | payload = '''
457 |
458 | if self.config.center.key:find(Reverie.prefix) then
459 | if not Reverie.booster_excludes then
460 | Reverie.booster_excludes = {}
461 | end
462 |
463 | table.insert(Reverie.booster_excludes, card.config.center.key)
464 | end
465 | '''
466 | match_indent = true
467 |
468 | [[patches]]
469 | [patches.pattern]
470 | target = "functions/common_events.lua"
471 | pattern = '''desc_nodes.name = localize{type = 'name_text', key = name_override or _c.key, set = name_override and 'Other' or _c.set}*'''
472 | position = "after"
473 | payload = '''
474 | if _c.generate_detailed_tooltip and type(_c.generate_detailed_tooltip) == "function" then
475 | _c:generate_detailed_tooltip(info_queue, card, desc_nodes)
476 | end'''
477 | match_indent = true
478 |
479 | [[patches]]
480 | [patches.pattern]
481 | target = "functions/UI_definitions.lua"
482 | pattern = '''pinned_left = G.C.ORANGE,'''
483 | position = "before"
484 | payload = '''
485 | morseled = HEX("b0aa9f"),'''
486 | match_indent = true
487 |
488 | [[patches]]
489 | [patches.pattern]
490 | target = "functions/button_callbacks.lua"
491 | pattern = '''calculate_reroll_cost(final_free)'''
492 | position = "after"
493 | payload = '''
494 | Reverie.calculate_reroll_cost()
495 | '''
496 | match_indent = true
497 |
498 | [[patches]]
499 | [patches.pattern]
500 | target = "functions/UI_definitions.lua"
501 | pattern = '''if polled_rate > check_rate and polled_rate <= check_rate + v.val then'''
502 | position = "before"
503 | payload = '''
504 | if _ == 1 and G.GAME.selected_sleeve and G.GAME.selected_sleeve == "sleeve_dvrprv_filmstrip" and G.GAME.selected_back.name == "Filmstrip Deck" then
505 | local rate = CardSleeves.Sleeve:get_obj(G.GAME.selected_sleeve).config.rate
506 | table.insert(rates, {
507 | type = "Cine_Quest",
508 | val = rate
509 | })
510 | total_rate = total_rate + rate
511 | polled_rate = pseudorandom(pseudoseed("cdt"..G.GAME.round_resets.ante)) * total_rate
512 | end
513 | '''
514 | match_indent = true
--------------------------------------------------------------------------------
/data/cines.lua:
--------------------------------------------------------------------------------
1 | SMODS.UndiscoveredSprite{
2 | key = "Cine",
3 | atlas = "Cine",
4 | pos = {
5 | x = 0,
6 | y = 1
7 | }
8 | }
9 |
10 | local function your_collection_cine_page(args)
11 | if not args or not args.cycle_config then
12 | return
13 | end
14 |
15 | for j = 1, #G.your_collection do
16 | for i = #G.your_collection[j].cards, 1, -1 do
17 | local c = G.your_collection[j]:remove_card(G.your_collection[j].cards[i])
18 | c:remove()
19 | c = nil
20 | end
21 | end
22 |
23 | local cines = {}
24 | for _, v in pairs(G.P_CENTER_POOLS.Cine) do
25 | table.insert(cines, v)
26 | end
27 | for _, v in pairs(G.P_CENTER_POOLS.Cine_Quest) do
28 | table.insert(cines, v)
29 | end
30 |
31 | table.sort(cines, function (a, b) return a.order < b.order end)
32 |
33 | for j = 1, #G.your_collection do
34 | for i = 1, (1 + j) * 2 do
35 | local center = cines[i + (j - 1) * 4 + (10 * (args.cycle_config.current_option - 1))]
36 | if not center then
37 | break
38 | end
39 |
40 | local card = Card(G.your_collection[j].T.x + G.your_collection[j].T.w / 2, G.your_collection[j].T.y, G.CARD_W, G.CARD_H, G.P_CARDS.empty, center)
41 | card:start_materialize(nil, i > 1 or j > 1)
42 | G.your_collection[j]:emplace(card)
43 | end
44 | end
45 |
46 | INIT_COLLECTION_CARD_ALERTS()
47 | end
48 |
49 | local function create_UIBox_your_collection_cines(self)
50 | local deck_tables = {}
51 |
52 | G.your_collection = {}
53 | for j = 1, 2 do
54 | G.your_collection[j] = CardArea(G.ROOM.T.x + 0.2 * G.ROOM.T.w / 2, G.ROOM.T.h, (4.25 + (j == 2 and 2 or 0)) * G.CARD_W, 1 * G.CARD_H, {
55 | card_limit = (1 + j) * 2,
56 | type = "voucher",
57 | highlight_limit = 0,
58 | collection = true
59 | })
60 | table.insert(deck_tables, {
61 | n = G.UIT.R,
62 | config = {
63 | align = "cm",
64 | padding = 0,
65 | no_fill = true
66 | },
67 | nodes = {
68 | {
69 | n = G.UIT.O,
70 | config = {
71 | object = G.your_collection[j]
72 | }
73 | }
74 | }
75 | })
76 | end
77 |
78 | local cines = {}
79 | for _, v in pairs(G.P_CENTER_POOLS.Cine) do
80 | table.insert(cines, v)
81 | end
82 | for _, v in pairs(G.P_CENTER_POOLS.Cine_Quest) do
83 | table.insert(cines, v)
84 | end
85 |
86 | table.sort(cines, function (a, b) return a.order < b.order end)
87 |
88 | local cine_options = {}
89 | for i = 1, math.ceil(#cines / (5 * #G.your_collection)) do
90 | table.insert(cine_options, localize("k_page").." "..tostring(i).."/"..tostring(math.ceil(#cines / (5 * #G.your_collection))))
91 | end
92 |
93 | for j = 1, #G.your_collection do
94 | for i = 1, (1 + j) * 2 do
95 | local center = cines[i + (j - 1) * 4]
96 | local card = Card(G.your_collection[j].T.x + G.your_collection[j].T.w / 2, G.your_collection[j].T.y, G.CARD_W, G.CARD_H, nil, center)
97 | card.ability.order = i + (j - 1) * 4
98 |
99 | card:start_materialize(nil, i > 1 or j > 1)
100 | G.your_collection[j]:emplace(card)
101 | end
102 | end
103 |
104 | INIT_COLLECTION_CARD_ALERTS()
105 |
106 | local option_nodes = {
107 | create_option_cycle({
108 | options = cine_options,
109 | w = 4.5,
110 | cycle_shoulders = true,
111 | opt_callback = "your_collection_cine_page",
112 | focus_args = {
113 | snap_to = true,
114 | nav = "wide"
115 | },
116 | current_option = 1,
117 | colour = G.C.RED,
118 | no_pips = true
119 | })
120 | }
121 | local type_buf = {}
122 |
123 | if G.ACTIVE_MOD_UI then
124 | for _, v in ipairs(SMODS.ConsumableType.obj_buffer) do
125 | if modsCollectionTally(G.P_CENTER_POOLS[v]).of > 0 then type_buf[#type_buf + 1] = v end
126 | end
127 | else
128 | type_buf = SMODS.ConsumableType.obj_buffer
129 | end
130 |
131 | local t = create_UIBox_generic_options({
132 | back_func = #type_buf>3 and 'your_collection_consumables' or G.ACTIVE_MOD_UI and "openModUI_"..G.ACTIVE_MOD_UI.id or 'your_collection',
133 | contents = {
134 | { n = G.UIT.R, config = { align = "cm", minw = 2.5, padding = 0.1, r = 0.1, colour = G.C.BLACK, emboss = 0.05 }, nodes = deck_tables },
135 | { n = G.UIT.R, config = { align = "cm", padding = 0 }, nodes = option_nodes },
136 | }
137 | })
138 |
139 | return t
140 | end
141 |
142 | SMODS.ConsumableType{
143 | key = "Cine",
144 | collection_rows = { 4, 6 },
145 | primary_colour = G.C.SET.Joker,
146 | secondary_colour = Reverie.badge_colour,
147 | loc_txt = {
148 | collection = "Cine Cards",
149 | name = "Cine",
150 | label = "Cine"
151 | },
152 | create_UIBox_your_collection = create_UIBox_your_collection_cines,
153 | inject = function (self)
154 | SMODS.ConsumableType.inject(self)
155 |
156 | G.P_CENTER_POOLS.Cine = {}
157 | G.P_CENTER_POOLS.Cine_Quest = {}
158 | G.C.SECONDARY_SET.Tag = HEX("a6b8ce")
159 | G.FUNCS.your_collection_cine_page = your_collection_cine_page
160 | end,
161 | inject_card = function (self, center)
162 | SMODS.ConsumableType.inject_card(self, center)
163 |
164 | if center.reward then
165 | SMODS.remove_pool(G.P_CENTER_POOLS.Cine, center.key)
166 | SMODS.insert_pool(G.P_CENTER_POOLS.Cine_Quest, center)
167 | end
168 | end,
169 | delete_card = function (self, center)
170 | SMODS.ConsumableType.delete_card(self, center)
171 | SMODS.remove_pool(G.P_CENTER_POOLS[center.reward and "Cine_Quest" or "Cine"], center.key)
172 | end
173 | }
174 |
175 | local function can_use(self, card)
176 | if card.config.center.reward then
177 | return false
178 | else
179 | return G.STATE == G.STATES.SHOP and G.shop
180 | end
181 | end
182 |
183 | local function loc_vars(self, info_queue, center)
184 | local vars = nil
185 |
186 | if center and center.config.center.reward and center.ability.progress then
187 | info_queue[#info_queue + 1] = G.P_CENTERS[center.config.center.reward]
188 |
189 | if center.config.center.reward == "c_dvrprv_unseen" then
190 | vars = {center.ability.extra.slots, center.ability.extra.goal, center.ability.progress}
191 | elseif center.config.center.reward == "c_dvrprv_ive_no_shape" then
192 | vars = {center.ability.extra.chips, center.ability.extra.goal, center.ability.progress}
193 | elseif center.config.center.reward == "c_dvrprv_jovial_m" then
194 | info_queue[#info_queue + 1] = {
195 | key = "j_jolly",
196 | set = "Joker",
197 | specific_vars = {G.P_CENTERS.j_jolly.config.t_mult, G.P_CENTERS.j_jolly.config.type}
198 | }
199 | vars = {center.ability.extra.goal, center.ability.progress, localize{
200 | type = "name_text",
201 | set = "Joker",
202 | key = "j_jolly"
203 | }}
204 | else
205 | vars = {center.ability.extra.goal, center.ability.progress}
206 | end
207 | else
208 | if self.name == "Tag or Die" then
209 | vars = {Reverie.get_var_object(center, self).extra.cost}
210 | elseif self.name == "The Unseen" or self.name == "Eerie Inn" then
211 | vars = {Reverie.get_var_object(center, self).extra.mult}
212 | elseif self.name == "I Sing, I've No Shape" then
213 | vars = {Reverie.get_var_object(center, self).extra.add}
214 | elseif self.name == "Crazy Lucky" then
215 | local info = G.P_CENTERS.p_dvrprv_crazy_lucky_1:loc_vars(info_queue)
216 |
217 | info_queue[#info_queue + 1] = {
218 | key = info.key,
219 | set = "Other",
220 | vars = info.vars
221 | }
222 | elseif self.name == "Fool Metal Alchemist" then
223 | vars = {Reverie.get_var_object(center, self).extra.slot}
224 | elseif self.name == "Every Hue" then
225 | vars = {Reverie.get_var_object(center, self).extra.rounds}
226 | else
227 | vars = {Reverie.get_var_object(center, self).extra}
228 | end
229 | end
230 |
231 | return {vars = vars}
232 | end
233 |
234 | local function inject(self)
235 | local order_cache = self.order
236 | local reward_cache = self.reward
237 |
238 | SMODS.Consumable.inject(self)
239 | self.order = order_cache
240 | self.reward = reward_cache
241 | end
242 |
243 | Reverie.cines = {
244 | {
245 | key = "ive_no_shape",
246 | order = 20,
247 | name = "I Sing, I've No Shape",
248 | config = {
249 | extra = {
250 | add = 20
251 | }
252 | },
253 | cost = 4,
254 | pos = {
255 | x = 6,
256 | y = 0
257 | }
258 | },
259 | {
260 | key = "ive_no_shape_quest",
261 | order = 19,
262 | name = "I Sing, I've No Shape Exchange Coupon",
263 | reward = "c_dvrprv_ive_no_shape",
264 | config = {
265 | extra = {
266 | chips = 2,
267 | goal = 3
268 | }
269 | },
270 | cost = 4,
271 | pos = {
272 | x = 8,
273 | y = 1
274 | }
275 | },
276 | {
277 | key = "unseen",
278 | order = 18,
279 | name = "The Unseen",
280 | config = {
281 | extra = {
282 | mult = 5
283 | }
284 | },
285 | cost = 4,
286 | pos = {
287 | x = 2,
288 | y = 0
289 | }
290 | },
291 | {
292 | key = "unseen_quest",
293 | order = 17,
294 | name = "The Unseen Exchange Coupon",
295 | reward = "c_dvrprv_unseen",
296 | config = {
297 | extra = {
298 | slots = 1,
299 | goal = 5
300 | }
301 | },
302 | cost = 4,
303 | pos = {
304 | x = 4,
305 | y = 1
306 | }
307 | },
308 | {
309 | key = "gem_heist",
310 | order = 2,
311 | name = "Gem Heist",
312 | config = {
313 | extra = 25
314 | },
315 | cost = 4,
316 | pos = {
317 | x = 1,
318 | y = 0
319 | }
320 | },
321 | {
322 | key = "gem_heist_quest",
323 | order = 1,
324 | name = "Gem Heist Exchange Coupon",
325 | reward = "c_dvrprv_gem_heist",
326 | config = {
327 | extra = {
328 | goal = 2
329 | }
330 | },
331 | cost = 4,
332 | pos = {
333 | x = 3,
334 | y = 1
335 | }
336 | },
337 | {
338 | key = "crazy_lucky",
339 | order = 12,
340 | name = "Crazy Lucky",
341 | config = {
342 | extra = {
343 | mult = 1,
344 | kind = {
345 | "p_dvrprv_crazy_lucky"
346 | }
347 | }
348 | },
349 | cost = 4,
350 | pos = {
351 | x = 7,
352 | y = 0
353 | }
354 | },
355 | {
356 | key = "crazy_lucky_quest",
357 | order = 11,
358 | name = "Crazy Lucky Exchange Coupon",
359 | reward = "c_dvrprv_crazy_lucky",
360 | config = {
361 | extra = {
362 | goal = 6
363 | }
364 | },
365 | cost = 4,
366 | pos = {
367 | x = 9,
368 | y = 1
369 | }
370 | },
371 | {
372 | key = "tag_or_die",
373 | order = 4,
374 | name = "Tag or Die",
375 | config = {
376 | extra = {
377 | cost = 8,
378 | kind = {
379 | "p_dvrprv_tag_"
380 | }
381 | }
382 | },
383 | cost = 4,
384 | pos = {
385 | x = 3,
386 | y = 0
387 | }
388 | },
389 | {
390 | key = "tag_or_die_quest",
391 | order = 3,
392 | name = "Tag or Die Exchange Coupon",
393 | reward = "c_dvrprv_tag_or_die",
394 | config = {
395 | extra = {
396 | goal = 4
397 | }
398 | },
399 | cost = 4,
400 | pos = {
401 | x = 5,
402 | y = 1
403 | }
404 | },
405 | {
406 | key = "let_it_moon",
407 | order = 8,
408 | name = "Let It Moon",
409 | config = {
410 | extra = {
411 | kind = {
412 | "p_arcana_",
413 | "p_celestial_"
414 | }
415 | }
416 | },
417 | cost = 4,
418 | pos = {
419 | x = 0,
420 | y = 0
421 | }
422 | },
423 | {
424 | key = "let_it_moon_quest",
425 | order = 7,
426 | name = "Let It Moon Exchange Coupon",
427 | reward = "c_dvrprv_let_it_moon",
428 | config = {
429 | extra = {
430 | goal = 10
431 | }
432 | },
433 | cost = 4,
434 | pos = {
435 | x = 2,
436 | y = 1
437 | }
438 | },
439 | {
440 | key = "poker_face",
441 | order = 10,
442 | name = "Poker Face",
443 | config = {
444 | extra = {
445 | kind = {
446 | "p_standard_"
447 | }
448 | }
449 | },
450 | cost = 4,
451 | pos = {
452 | x = 4,
453 | y = 0
454 | }
455 | },
456 | {
457 | key = "poker_face_quest",
458 | order = 9,
459 | name = "Poker Face Exchange Coupon",
460 | reward = "c_dvrprv_poker_face",
461 | config = {
462 | extra = {
463 | goal = 8
464 | }
465 | },
466 | cost = 4,
467 | pos = {
468 | x = 6,
469 | y = 1
470 | }
471 | },
472 | {
473 | key = "eerie_inn",
474 | order = 6,
475 | name = "Eerie Inn",
476 | config = {
477 | extra = {
478 | mult = 2,
479 | kind = {
480 | "p_spectral_"
481 | }
482 | }
483 | },
484 | cost = 4,
485 | pos = {
486 | x = 5,
487 | y = 0
488 | }
489 | },
490 | {
491 | key = "eerie_inn_quest",
492 | order = 5,
493 | name = "Eerie Inn Exchange Coupon",
494 | reward = "c_dvrprv_eerie_inn",
495 | config = {
496 | extra = {
497 | goal = 5
498 | }
499 | },
500 | cost = 4,
501 | pos = {
502 | x = 7,
503 | y = 1
504 | }
505 | },
506 | {
507 | key = "adrifting",
508 | order = 14,
509 | name = "Adrifting",
510 | config = {
511 | extra = 1
512 | },
513 | cost = 4,
514 | pos = {
515 | x = 8,
516 | y = 0
517 | }
518 | },
519 | {
520 | key = "adrifting_quest",
521 | order = 13,
522 | name = "Adrifting Exchange Coupon",
523 | reward = "c_dvrprv_adrifting",
524 | config = {
525 | extra = {
526 | goal = 5
527 | }
528 | },
529 | cost = 4,
530 | pos = {
531 | x = 0,
532 | y = 2
533 | }
534 | },
535 | {
536 | key = "morsel",
537 | order = 16,
538 | name = "Morsel",
539 | config = {
540 | extra = {
541 | kind = {
542 | "p_buffoon_"
543 | }
544 | }
545 | },
546 | cost = 4,
547 | pos = {
548 | x = 9,
549 | y = 0
550 | }
551 | },
552 | {
553 | key = "morsel_quest",
554 | order = 15,
555 | name = "Morsel Exchange Coupon",
556 | reward = "c_dvrprv_morsel",
557 | config = {
558 | extra = {
559 | goal = 2
560 | }
561 | },
562 | cost = 4,
563 | pos = {
564 | x = 1,
565 | y = 2
566 | }
567 | },
568 | {
569 | key = "alchemist",
570 | order = 22,
571 | name = "Fool Metal Alchemist",
572 | config = {
573 | extra = {
574 | slot = 2,
575 | kind = {
576 | "p_alchemy_"
577 | }
578 | }
579 | },
580 | cost = 4,
581 | pos = {
582 | x = 2,
583 | y = 2
584 | },
585 | dependency = "CodexArcanum"
586 | },
587 | {
588 | key = "alchemist_quest",
589 | order = 21,
590 | name = "Fool Metal Alchemist Exchange Coupon",
591 | reward = "c_dvrprv_alchemist",
592 | config = {
593 | extra = {
594 | goal = 5
595 | }
596 | },
597 | cost = 4,
598 | pos = {
599 | x = 3,
600 | y = 2
601 | },
602 | dependency = "CodexArcanum"
603 | },
604 | {
605 | key = "every_hue",
606 | order = 24,
607 | name = "Every Hue",
608 | config = {
609 | extra = {
610 | rounds = 3,
611 | kind = {
612 | "p_mf_colour_"
613 | }
614 | }
615 | },
616 | cost = 4,
617 | pos = {
618 | x = 4,
619 | y = 2
620 | },
621 | dependency = "MoreFluff"
622 | },
623 | {
624 | key = "every_hue_quest",
625 | order = 23,
626 | name = "Every Hue Exchange Coupon",
627 | reward = "c_dvrprv_every_hue",
628 | config = {
629 | extra = {
630 | goal = 2
631 | }
632 | },
633 | cost = 4,
634 | pos = {
635 | x = 5,
636 | y = 2
637 | },
638 | dependency = "MoreFluff"
639 | },
640 | {
641 | key = "radioactive",
642 | order = 26,
643 | name = "Radioactive",
644 | config = {
645 | extra = {
646 | kind = {
647 | "p_buffoon_"
648 | }
649 | }
650 | },
651 | cost = 4,
652 | pos = {
653 | x = 6,
654 | y = 2
655 | },
656 | dependency = "FusionJokers"
657 | },
658 | {
659 | key = "radioactive_quest",
660 | order = 25,
661 | name = "Radioactive Exchange Coupon",
662 | reward = "c_dvrprv_radioactive",
663 | config = {
664 | extra = {
665 | goal = 1
666 | }
667 | },
668 | cost = 4,
669 | pos = {
670 | x = 7,
671 | y = 2
672 | },
673 | dependency = "FusionJokers"
674 | },
675 | {
676 | key = "jovial_m",
677 | order = 28,
678 | name = "Jovial M",
679 | config = {
680 | extra = {
681 | kind = {
682 | "p_buffoon_"
683 | }
684 | }
685 | },
686 | cost = 4,
687 | pos = {
688 | x = 8,
689 | y = 2
690 | },
691 | dependency = "Cryptid"
692 | },
693 | {
694 | key = "jovial_m_quest",
695 | order = 27,
696 | name = "Jovial M Exchange Coupon",
697 | reward = "c_dvrprv_jovial_m",
698 | config = {
699 | extra = {
700 | goal = 3
701 | }
702 | },
703 | cost = 4,
704 | pos = {
705 | x = 9,
706 | y = 2
707 | },
708 | dependency = "Cryptid"
709 | }
710 | }
711 |
712 | table.sort(Reverie.cines, function (a, b) return a.order < b.order end)
713 |
714 | for _, v in pairs(Reverie.cines) do
715 | v.set = "Cine"
716 | v.atlas = "Cine"
717 | v.can_use = can_use
718 | v.loc_vars = loc_vars
719 | v.inject = inject
720 | v.use = not v.reward and Reverie.use_cine or nil
721 |
722 | if not v.dependency or Reverie.find_mod(v.dependency) then
723 | SMODS.Consumable(v)
724 | end
725 | end
--------------------------------------------------------------------------------
/localization/en-us.lua:
--------------------------------------------------------------------------------
1 | return {
2 | descriptions = {
3 | Cine = {
4 | c_dvrprv_ive_no_shape_quest = {
5 | name = "Exchange Coupon",
6 | text = {
7 | "Converts to {C:cine}I Sing, I've No Shape",
8 | "after scoring more than {C:attention}X#1#{} of",
9 | "required Chips in {C:attention}#2# Blinds",
10 | "{C:inactive}(Currently {C:attention}#3#{C:inactive}/#2#)"
11 | }
12 | },
13 | c_dvrprv_ive_no_shape = {
14 | name = "I Sing, I've No Shape",
15 | text = {
16 | "During this shop,",
17 | "only owned {C:attention}Jokers{} appear",
18 | "{C:red}+$#1#{} reroll cost"
19 | }
20 | },
21 | c_dvrprv_unseen_quest = {
22 | name = "Exchange Coupon",
23 | text = {
24 | "Converts to {C:cine}The Unseen{}",
25 | "after having {C:attention}#1#{} empty",
26 | "{C:attention}Joker{} slot for {C:attention}#2#{} rounds",
27 | "{C:inactive}(Currently {C:attention}#3#{C:inactive}/#2#)"
28 | }
29 | },
30 | c_dvrprv_unseen = {
31 | name = "The Unseen",
32 | text = {
33 | "During this shop,",
34 | "all {C:attention}Jokers{} and {C:attention}consumables",
35 | "become {C:dark_edition}Negative",
36 | "{C:red}X#1#{} reroll cost",
37 | "{s:0.8}Rerolls cards"
38 | }
39 | },
40 | c_dvrprv_gem_heist_quest = {
41 | name = "Exchange Coupon",
42 | text = {
43 | "Converts to {C:cine}Gem Heist{}",
44 | "after selling",
45 | "{C:attention}#1# Editioned Jokers{}",
46 | "{C:inactive}(Currently {C:attention}#2#{C:inactive}/#1#)"
47 | }
48 | },
49 | c_dvrprv_gem_heist = {
50 | name = "Gem Heist",
51 | text = {
52 | "During this shop,",
53 | "all cards become",
54 | "{C:dark_edition}Polychrome{} and {C:attention}25%{} off",
55 | "{s:0.8}Rerolls cards"
56 | }
57 | },
58 | c_dvrprv_crazy_lucky_quest = {
59 | name = "Exchange Coupon",
60 | text = {
61 | "Converts to {C:cine}Crazy Lucky{}",
62 | "after opening {C:attention}#1# Booster Packs",
63 | "{C:inactive}(Currently {C:attention}#2#{C:inactive}/#1#)"
64 | }
65 | },
66 | c_dvrprv_crazy_lucky = {
67 | name = "Crazy Lucky",
68 | text = {
69 | "During this shop,",
70 | "everything becomes {C:attention}Pack",
71 | "{s:0.8}Rerolls {s:0.8,C:attention}Booster Packs"
72 | }
73 | },
74 | c_dvrprv_tag_or_die_quest = {
75 | name = "Exchange Coupon",
76 | text = {
77 | "Converts to {C:cine}Tag or Die{}",
78 | "after skipping {C:attention}#1# Blinds",
79 | "{C:inactive}(Currently {C:attention}#2#{C:inactive}/#1#)"
80 | }
81 | },
82 | c_dvrprv_tag_or_die = {
83 | name = "Tag or Die",
84 | text = {
85 | "During this shop,",
86 | "only {C:attention}Tags{} that",
87 | "cost {C:money}$#1#{} appear",
88 | "{s:0.8}Rerolls {s:0.8,C:attention}Booster Packs"
89 | }
90 | },
91 | c_dvrprv_let_it_moon_quest = {
92 | name = "Exchange Coupon",
93 | text = {
94 | "Converts to {C:cine}Let It Moon{}",
95 | "after using {C:attention}#1# {C:planet}Planet",
96 | "or {C:tarot}Tarot{} cards",
97 | "{C:inactive}(Currently {C:attention}#2#{C:inactive}/#1#)"
98 | }
99 | },
100 | c_dvrprv_let_it_moon = {
101 | name = "Let It Moon",
102 | text = {
103 | "During this shop,",
104 | "only {C:planet}Planet{} and",
105 | "{C:tarot}Tarot{} cards appear",
106 | "{s:0.8}Rerolls {s:0.8,C:attention}Booster Packs"
107 | }
108 | },
109 | c_dvrprv_poker_face_quest = {
110 | name = "Exchange Coupon",
111 | text = {
112 | "Converts to {C:cine}Poker Face{}",
113 | "after enhancing {C:attention}#1#",
114 | "{C:attention}Playing cards",
115 | "{C:inactive}(Currently {C:attention}#2#{C:inactive}/#1#)"
116 | }
117 | },
118 | c_dvrprv_poker_face = {
119 | name = "Poker Face",
120 | text = {
121 | "During this shop,",
122 | "only {C:attention}Playing cards",
123 | "from your deck appear",
124 | "{s:0.8}Rerolls {s:0.8,C:attention}Booster Packs"
125 | }
126 | },
127 | c_dvrprv_eerie_inn_quest = {
128 | name = "Exchange Coupon",
129 | text = {
130 | "Converts to {C:cine}Eerie Inn{}",
131 | "after destroying {C:attention}#1#{} cards",
132 | "{C:inactive}(Currently {C:attention}#2#{C:inactive}/#1#)"
133 | }
134 | },
135 | c_dvrprv_eerie_inn = {
136 | name = "Eerie Inn",
137 | text = {
138 | "During this shop,",
139 | "only {C:spectral}Spectral Packs",
140 | "appear",
141 | "{C:red}X#1#{} reroll cost",
142 | "{s:0.8}Rerolls {s:0.8,C:attention}Booster Packs"
143 | }
144 | },
145 | c_dvrprv_adrifting_quest = {
146 | name = "Exchange Coupon",
147 | text = {
148 | "Converts to {C:cine}Adrifting{}",
149 | "after playing {C:attention}#1# debuffed{}",
150 | "or {C:attention}faced down{} cards",
151 | "{C:inactive}(Currently {C:attention}#2#{C:inactive}/#1#)"
152 | }
153 | },
154 | c_dvrprv_adrifting = {
155 | name = "Adrifting",
156 | text = {
157 | "During this shop,",
158 | "everything is {C:attention}faced",
159 | "{C:attention}down{} and costs {C:money}$#1#",
160 | "{s:0.8}Rerolls cards and {s:0.8,C:attention}Booster Packs"
161 | }
162 | },
163 | c_dvrprv_morsel_quest = {
164 | name = "Exchange Coupon",
165 | text = {
166 | "Converts to {C:cine}Morsel{}",
167 | "after getting {C:attention}#1#",
168 | "{C:attention}Food Jokers{}",
169 | "{C:inactive}(Currently {C:attention}#2#{C:inactive}/#1#)"
170 | }
171 | },
172 | c_dvrprv_morsel = {
173 | name = "Morsel",
174 | text = {
175 | "During this shop,",
176 | "only {C:attention}Food Jokers",
177 | "with {C:attention}doubled{} ability",
178 | "values appear",
179 | "{s:0.8}Rerolls {s:0.8,C:attention}Booster Packs"
180 | }
181 | },
182 | c_dvrprv_alchemist_quest = {
183 | name = "Exchange Coupon",
184 | text = {
185 | "Converts to {C:cine}Fool Metal",
186 | "{C:cine}Alchemist{} after using",
187 | "{C:attention}#1# {C:alchemical}Alchemical{} cards",
188 | "{C:inactive}(Currently {C:attention}#2#{C:inactive}/#1#)"
189 | }
190 | },
191 | c_dvrprv_alchemist = {
192 | name = "Fool Metal Alchemist",
193 | text = {
194 | "During this shop,",
195 | "{C:attention}+#1#{} consumable slot and",
196 | "only {C:alchemical}Alchemical{} cards appear",
197 | "{s:0.8}Rerolls {s:0.8,C:attention}Booster Packs"
198 | }
199 | },
200 | c_dvrprv_every_hue_quest = {
201 | name = "Exchange Coupon",
202 | text = {
203 | "Converts to {C:cine}Every Hue",
204 | "after using {C:attention}#1# {C:colourcard}Colour{} cards",
205 | "{C:inactive}(Currently {C:attention}#2#{C:inactive}/#1#)"
206 | }
207 | },
208 | c_dvrprv_every_hue = {
209 | name = "Every Hue",
210 | text = {
211 | "During this shop,",
212 | "only {C:colourcard}Colour{} cards that",
213 | "already have {C:attention}#1# rounds{}",
214 | "appear",
215 | "{s:0.8}Rerolls {s:0.8,C:attention}Booster Packs"
216 | }
217 | },
218 | c_dvrprv_radioactive_quest = {
219 | name = "Exchange Coupon",
220 | text = {
221 | "Converts to {C:cine}Radioactive",
222 | "after getting {C:attention}#1#",
223 | "{C:attention}Fusion Joker",
224 | "{C:inactive}(Currently {C:attention}#2#{C:inactive}/#1#)"
225 | }
226 | },
227 | c_dvrprv_radioactive = {
228 | name = "Radioactive",
229 | text = {
230 | "During this shop,",
231 | "only {C:attention}Jokers{} that",
232 | "can be used in {C:attention}Fusions",
233 | "appear",
234 | "{s:0.8}Rerolls {s:0.8,C:attention}Booster Packs"
235 | }
236 | },
237 | c_dvrprv_jovial_m_quest = {
238 | name = "Exchange Coupon",
239 | text = {
240 | "Converts to {C:cine}Jovial M",
241 | "after selling {C:attention}#1#",
242 | "{C:attention}#3#",
243 | "{C:inactive}(Currently {C:attention}#2#{C:inactive}/#1#)"
244 | }
245 | },
246 | c_dvrprv_jovial_m = {
247 | name = "Jovial M",
248 | text = {
249 | "During this shop,",
250 | "only {C:cry_epic}Epic{} or {C:cry_exotic}Exotic",
251 | "{C:attention}Jokers{} appear",
252 | "{s:0.8}Rerolls {s:0.8,C:attention}Booster Packs"
253 | }
254 | }
255 | },
256 | Joker = {
257 | j_diet_cola_morsel_alternative = {
258 | text = {
259 | ".", -- Blank strings are ignored, so putting random character to preserve index info
260 | "create two free"
261 | }
262 | },
263 | j_olab_fine_wine_morsel_alternative = {
264 | text = {
265 | "{C:red}+#1#{} discards, gains {C:red}+2{} discards",
266 | }
267 | },
268 | j_olab_mystery_soda_morsel_alternative = {
269 | text = {
270 | ".",
271 | "four free {C:attention}tags"
272 | }
273 | },
274 | j_mf_tonersoup_morsel_alternative = {
275 | text = {
276 | "Create two {C:tarot}Tarot{} cards"
277 | }
278 | },
279 | j_bunc_fondue_morsel_alternative = {
280 | text = {
281 | ".",
282 | "{C:attention}first and second hand{} of round are"
283 | }
284 | },
285 | j_evo_full_sugar_cola_morsel_alternative = {
286 | text = {
287 | ".",
288 | "create {C:attention}4{} free"
289 | }
290 | },
291 | j_kcva_swiss_morsel_alternative = {
292 | text = {
293 | "{C:mult}+20{} Mult for each"
294 | }
295 | },
296 | j_jank_cut_the_cheese_morsel_alternative = {
297 | text = {
298 | ".",
299 | "create two random {C:attention}Food Jokers"
300 | }
301 | },
302 | j_pape_ghost_cola_morsel_alternative = {
303 | text = {
304 | "Sell this card to create two {C:attention}#1#{}",
305 | "and two random {C:dark_edition}Negative{} {C:spectral}Spectral{} cards"
306 | }
307 | },
308 | j_twewy_candleService_morsel_alternative = {
309 | text = {
310 | "Every eighth scoring"
311 | }
312 | },
313 | j_dvrprv_dynamic_film = {
314 | name = "Dynamic Film",
315 | text = {
316 | "This Joker gains {C:chips}+#2#{} Chips",
317 | "every time an {C:cine}Exchange Coupon",
318 | "progresses",
319 | "{C:inactive}(Currently +{C:chips}#1#{C:inactive} Chips)"
320 | }
321 | }
322 | },
323 | Back = {
324 | b_dvrprv_filmstrip = {
325 | name = "Filmstrip Deck",
326 | text = {
327 | "{C:cine}Cine{} cards can stack",
328 | "{C:attention}+#1#{} Cine slot"
329 | }
330 | },
331 | b_dvrprv_stamp = {
332 | name = "Stamp Deck",
333 | text = {
334 | "Skipping {C:attention}Blind{} gives",
335 | "{C:attention,T:p_dvrprv_tag_jumbo_1}#1#{} instead"
336 | }
337 | }
338 | },
339 | Sleeve = {
340 | sleeve_dvrprv_filmstrip = {
341 | name = "Filmstrip Sleeve",
342 | text = {
343 | "{C:cine}Cine{} cards can stack",
344 | "{C:attention}+#1#{} Cine slot"
345 | }
346 | },
347 | sleeve_dvrprv_filmstrip_alt = {
348 | name = "Filmstrip Sleeve",
349 | text = {
350 | "{C:cine}Exchange Coupons{} may appear",
351 | "in the shop and has {C:green}#2# in #3#",
352 | "chance for being {C:dark_edition}Negative"
353 | }
354 | },
355 | sleeve_dvrprv_stamp = {
356 | name = "Stamp Sleeve",
357 | text = {
358 | "Skipping {C:attention}Blind{} gives",
359 | "{C:attention,T:p_dvrprv_tag_jumbo_1}#1#{} instead"
360 | }
361 | },
362 | sleeve_dvrprv_stamp_alt = {
363 | name = "Stamp Sleeve",
364 | text = {
365 | "Skipping {C:attention}Blind{} also",
366 | "gives a {C:attention}random Tag{}"
367 | }
368 | }
369 | },
370 | Tag = {
371 | tag_dvrprv_cine = {
372 | name = "Stub Tag",
373 | text = {
374 | "Gives a free",
375 | "{C:cine}Film Pack"
376 | }
377 | },
378 | tag_dvrprv_jumbo_tag = {
379 | name = "Stamp Tag",
380 | text = {
381 | "Gives a free",
382 | "{C:attention}Jumbo Tag Pack"
383 | }
384 | },
385 | tag_dvrprv_mega_tag = {
386 | name = "Mega Stamp Tag",
387 | text = {
388 | "Gives a free",
389 | "{C:attention}Jumbo Tag Pack",
390 | "and a {C:attention}random Tag"
391 | }
392 | }
393 | },
394 | Spectral = {
395 | c_dvrprv_reverie = {
396 | name = "Reverie",
397 | text = {
398 | "Applies every",
399 | "{C:cine,E:1}Cine cards",
400 | "to this shop"
401 | }
402 | }
403 | },
404 | Voucher = {
405 | v_dvrprv_script = {
406 | name = "Script",
407 | text = {
408 | "{C:attention}+#1#{} card slot",
409 | "available in shop",
410 | "while {C:cine}Cine{} card is",
411 | "active"
412 | }
413 | },
414 | v_dvrprv_megaphone = {
415 | name = "Megaphone",
416 | text = {
417 | "Requirements of",
418 | "{C:cine}Exchange Coupons{} are",
419 | "halved"
420 | }
421 | }
422 | },
423 | Edition = {
424 | e_negative_cine = {
425 | name = "Negative",
426 | text = {
427 | "{C:dark_edition}+#1#{} Cine slot"
428 | }
429 | }
430 | },
431 | Other = {
432 | p_dvrprv_tag_normal = {
433 | name = "Tag Pack",
434 | text = {
435 | "Choose {C:attention}#1#{} of up to",
436 | "{C:attention}#2# Tags"
437 | }
438 | },
439 | p_dvrprv_tag_jumbo = {
440 | name = "Jumbo Tag Pack",
441 | text = {
442 | "Choose {C:attention}#1#{} of up to",
443 | "{C:attention}#2# Tags"
444 | }
445 | },
446 | p_dvrprv_tag_mega = {
447 | name = "Mega Tag Pack",
448 | text = {
449 | "Choose {C:attention}#1#{} of up to",
450 | "{C:attention}#2# Tags"
451 | }
452 | },
453 | p_dvrprv_luxe_mega = {
454 | name = "Mega Luxe Pack",
455 | text = {
456 | "Choose {C:attention}#1#{} of up to",
457 | "{C:attention}#2# Vouchers"
458 | }
459 | },
460 | p_dvrprv_crazy_lucky = {
461 | name = "Pack",
462 | text = {
463 | "Choose {C:attention}#1#{} of up to",
464 | "{C:attention}#2# {C:attention,E:1}anything{} to add",
465 | "to your possession"
466 | }
467 | },
468 | p_dvrprv_film_normal = {
469 | name = "Film Pack",
470 | text = {
471 | "Choose {C:attention}#1#{} of up to",
472 | "{C:attention}#2#{} {C:cine}Exchange Coupon{} cards",
473 | "to add to your possession"
474 | }
475 | },
476 | p_dvrprv_film_jumbo = {
477 | name = "Jumbo Film Pack",
478 | text = {
479 | "Choose {C:attention}#1#{} of up to",
480 | "{C:attention}#2# {C:cine}Exchange Coupon{} cards",
481 | "to add to your possession"
482 | }
483 | },
484 | p_dvrprv_film_mega = {
485 | name = "Mega Film Pack",
486 | text = {
487 | "Choose {C:attention}#1#{} of up to",
488 | "{C:attention}#2# {C:cine}Cine{} cards to add",
489 | "to your possession"
490 | }
491 | },
492 | undiscovered_cine = {
493 | name = "Not Discovered",
494 | text = {
495 | "Purchase or use",
496 | "this card in an",
497 | "unseeded run to",
498 | "learn what it does"
499 | }
500 | },
501 | morseled = {
502 | name = "Morsel",
503 | text = {
504 | "Ability is {C:attention}doubled"
505 | }
506 | },
507 | }
508 | },
509 | misc = {
510 | dictionary = {
511 | k_dvrprv_title = "Reverie",
512 | k_dvrprv_description = "Prepare Your Tickets",
513 | k_dvrprv_cine = "Cine",
514 | k_dvrprv_tag = "Tag",
515 | k_dvrprv_tag_pack = "Tag Pack",
516 | k_dvrprv_crazy_pack = "Pack",
517 | k_dvrprv_film_pack = "Film Pack",
518 | b_dvrprv_cine_cards = "Cine Cards",
519 | b_dvrprv_jokerdisplay_compat = "JokerDisplay compatibility",
520 | b_dvrprv_jokerdisplay_compat_info = {
521 | "Enable JokerDisplay compatibility for",
522 | "Exchange Coupons"
523 | },
524 | b_dvrprv_tag_packs_shop = "Tag Packs in shop",
525 | b_dvrprv_tag_packs_shop_info = {
526 | "Allow Tag Packs to normally appear",
527 | "in the shop"
528 | },
529 | b_dvrprv_crazy_packs_shop = "Crazy Packs in shop",
530 | b_dvrprv_crazy_packs_shop_info = {
531 | "Allow Crazy Packs to normally appear",
532 | "in the shop"
533 | },
534 | b_dvrprv_custom_morsel_compat = "Morsel for modded Jokers",
535 | b_dvrprv_custom_morsel_compat_info =
536 | {
537 | "Enable custom Morsel compatibilities for Modded Jokers",
538 | "(e.g. TWEWJ's Candle Service: Every forth scoring >>>",
539 | "Every eighth scoring)"
540 | },
541 | b_dvrprv_cartomancer_compat = "Cartomancer compatibility",
542 | b_dvrprv_cartomancer_compat_info = {
543 | "Enable Cartomancer compatibility for",
544 | "zooming Cine cards in your possesion"
545 | }
546 | },
547 | labels = {
548 | morseled = "Morsel"
549 | }
550 | }
551 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 |
635 | Copyright (C)
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | Copyright (C)
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------