Add new art, modernize, nerf invisible tag
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 170 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 845 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 44 KiB |
|
|
@ -403,7 +403,12 @@ return {
|
|||
},
|
||||
tag_Roland_invisible = {
|
||||
name = "Invisible Tag",
|
||||
text = {"{C:attention}Duplicate {}a random Joker", "{C:inactive}(Must have room)"},
|
||||
text = {
|
||||
"{C:attention}Duplicate {}a random",
|
||||
"Joker after {C:attention}#1#{} rounds",
|
||||
"{C:inactive}(Must have room)",
|
||||
"{C:inactive}(Currently {C:attention}#2#{C:inactive}/#1#)",
|
||||
},
|
||||
},
|
||||
},
|
||||
Tarot = {
|
||||
|
|
|
|||
|
|
@ -3,20 +3,20 @@
|
|||
"id": "Roland",
|
||||
"name": "Roland",
|
||||
"prefix": "Roland",
|
||||
"author": [
|
||||
"Emik"
|
||||
],
|
||||
"version": "2.7.5",
|
||||
"version": "2.8.0",
|
||||
"badge_colour": "8BE9FD",
|
||||
"display_name": "Roland",
|
||||
"main_file": "src/main.lua",
|
||||
"badge_text_colour": "44475A",
|
||||
"display_name": "Roland",
|
||||
"description": "Adds mechanics that are meant to have interesting interactions with the base game. Not meant to be balanced, but not entirely broken either.",
|
||||
"provides": [],
|
||||
"conflicts": [],
|
||||
"author": [
|
||||
"Emik"
|
||||
],
|
||||
"dependencies": [
|
||||
"Steamodded (>=1.0~*)",
|
||||
"Steamodded (>=1.0.0~BETA-1606b)",
|
||||
"Lovely (>=0.6)",
|
||||
"Bakery (>=0.1.26~*)"
|
||||
"Bakery (>=3.2.0~*)"
|
||||
]
|
||||
}
|
||||
|
|
@ -22,6 +22,7 @@ local back = (function()
|
|||
return (calculate and G.GAME.selected_sleeve ~= "sleeve_Roland_" .. key) and calculate(self, ...) or nil
|
||||
end
|
||||
|
||||
tbl.artist = tbl.artist and "Roland_" .. tbl.artist or nil
|
||||
tbl.pos = {x = x, y = 0}
|
||||
tbl.atlas = "back"
|
||||
|
||||
|
|
@ -91,7 +92,7 @@ local _ = _G["CardSleeves"] and SMODS.Atlas {
|
|||
back {
|
||||
key = "blossom",
|
||||
pronouns = "any_all",
|
||||
artist = "Roland_bakersdozenbagels",
|
||||
artist = "bakersdozenbagels",
|
||||
config = {extra = {alt_times = 4, times = 2}},
|
||||
attributes = {"boss_blind"},
|
||||
loc_vars = function(self, _, _)
|
||||
|
|
@ -133,7 +134,7 @@ back {
|
|||
back {
|
||||
key = "swapper",
|
||||
pronouns = "he_him",
|
||||
artist = "Roland_bakersdozenbagels",
|
||||
artist = "bakersdozenbagels",
|
||||
attributes = {"spectral", "tarot"},
|
||||
apply = function(self)
|
||||
local modifiers = G.GAME.modifiers
|
||||
|
|
|
|||
|
|
@ -347,6 +347,11 @@ function SMODS.current_mod:calculate(context)
|
|||
local _ = type(G.calc) == "function" and G.calc(f(context):keys():string())
|
||||
local improbable, orig = G.GAME.modifiers.Roland_improbable, G.GAME.probabilities
|
||||
|
||||
local _ = context.end_of_round and
|
||||
context.main_eval and
|
||||
not context.blueprint and
|
||||
G.P_TAGS.tag_Roland_invisible.increment()
|
||||
|
||||
-- Normally unreachable since we set it to nil ourselves,
|
||||
-- but other mods may want to use this modifier.
|
||||
if improbable == false then
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ SMODS.Challenge {
|
|||
key = "Eternally_Amber",
|
||||
rules = {custom = {{id = "Roland_Eternally_Amber"}, {id = "Roland_Showdown_Amber"}}},
|
||||
restrictions = amber,
|
||||
pronouns = "they_them",
|
||||
calculate = function(_, context)
|
||||
local function slide(pitch)
|
||||
q(function()
|
||||
|
|
@ -132,6 +133,7 @@ SMODS.Challenge {
|
|||
key = "Eternally_Cerulean",
|
||||
rules = {custom = {{id = "Roland_Eternally_Cerulean"}, {id = "Roland_Showdown_Cerulean"}}},
|
||||
restrictions = cerulean,
|
||||
pronouns = "she_her",
|
||||
calculate = function(_, context)
|
||||
if not context.hand_drawn then
|
||||
return
|
||||
|
|
@ -157,6 +159,7 @@ SMODS.Challenge {
|
|||
key = "Eternally_Crimson",
|
||||
rules = {custom = {{id = "Roland_Eternally_Crimson"}, {id = "Roland_Showdown_Crimson"}}},
|
||||
restrictions = crimson,
|
||||
pronouns = "she_her",
|
||||
calculate = function(_, context)
|
||||
local _ = context.blind_defeated and f(G.jokers.cards):each(function(v)
|
||||
v.ability.Roland_crimson_heart_chosen = nil
|
||||
|
|
@ -216,6 +219,7 @@ SMODS.Challenge {
|
|||
key = "Eternally_Verdant",
|
||||
rules = {custom = {{id = "Roland_Eternally_Verdant"}, {id = "Roland_Showdown_Verdant"}}},
|
||||
restrictions = verdant,
|
||||
pronouns = "she_her",
|
||||
calculate = function(_, context)
|
||||
if context.setting_blind then
|
||||
G.GAME.modifiers.Roland_Eternally_Verdant = true
|
||||
|
|
@ -237,6 +241,7 @@ SMODS.Challenge {
|
|||
key = "Eternally_Violet",
|
||||
rules = {custom = {{id = "Roland_Eternally_Violet"}, {id = "Roland_Showdown_Violet"}}},
|
||||
restrictions = violet,
|
||||
pronouns = "she_they",
|
||||
calculate = function(_, context)
|
||||
if context.setting_blind then
|
||||
G.GAME.blind.chips = G.GAME.blind.chips * 6
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ charm {
|
|||
G.STATE = G.STATES.SHOP
|
||||
G.GAME.shop_free = nil
|
||||
G.GAME.shop_d6ed = nil
|
||||
G.STATE_COMPLETE = false
|
||||
-- G.STATE_COMPLETE = false
|
||||
play_sound("whoosh1", 1.33333, 0.8)
|
||||
play_sound("whoosh1", 0.66666, 0.8)
|
||||
end)
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ SMODS.Edition {
|
|||
shader = "frozen",
|
||||
sound = {sound = "Roland_frozen", per = 1, vol = 0.8},
|
||||
attributes = {"passive", "scaling", "mod_chance"},
|
||||
pronouns = "any_all",
|
||||
weight = 8,
|
||||
extra_cost = 4,
|
||||
in_shop = true,
|
||||
|
|
|
|||
|
|
@ -69,6 +69,21 @@ local function localize_card(card, fallback)
|
|||
}
|
||||
end
|
||||
|
||||
---@param card Card
|
||||
---@return boolean
|
||||
local function has_rank_and_suit(card)
|
||||
return not SMODS.has_no_rank(card) and not SMODS.has_no_suit(card)
|
||||
end
|
||||
|
||||
---@param value table
|
||||
---@return fun(other: table): boolean
|
||||
local function ranksuitnq(value)
|
||||
return function(other)
|
||||
local v, o = value.base or value, other.base or other
|
||||
return value == other or v.suit ~= o.suit or v.value ~= o.value
|
||||
end
|
||||
end
|
||||
|
||||
SMODS.Atlas {
|
||||
key = "joker",
|
||||
path = "joker.png",
|
||||
|
|
@ -157,7 +172,7 @@ joker {
|
|||
|
||||
joker {
|
||||
key = "sunny",
|
||||
pronouns = "they_them",
|
||||
pronouns = "it_its",
|
||||
artist = "char",
|
||||
attributes = {"food", "on_sell"},
|
||||
cost = 2,
|
||||
|
|
@ -192,7 +207,7 @@ joker {
|
|||
|
||||
joker {
|
||||
key = "hardboiled",
|
||||
pronouns = "they_them",
|
||||
pronouns = "it_its",
|
||||
attributes = {"food", "editions", "modify_card", "on_sell"},
|
||||
cost = 5,
|
||||
rarity = 2,
|
||||
|
|
@ -386,7 +401,7 @@ joker {
|
|||
|
||||
joker {
|
||||
key = "snowsquall",
|
||||
pronouns = "they_them",
|
||||
pronouns = "he_they",
|
||||
config = {extra = {mult_gain = 1, mult = 0}},
|
||||
attributes = {"mult", "scaling", "hand_type"},
|
||||
cost = 6,
|
||||
|
|
@ -420,7 +435,7 @@ joker {
|
|||
|
||||
joker {
|
||||
key = "arctic",
|
||||
pronouns = "it_its",
|
||||
pronouns = "they_them",
|
||||
cost = 10,
|
||||
rarity = 3,
|
||||
config = {extra = {frozen = 2, non_frozen = 1}},
|
||||
|
|
@ -529,7 +544,7 @@ joker {
|
|||
|
||||
joker {
|
||||
key = "bulldozer",
|
||||
pronouns = "it_its",
|
||||
pronouns = "she_her",
|
||||
attributes = {"xmult"},
|
||||
cost = 6,
|
||||
rarity = 2,
|
||||
|
|
@ -592,7 +607,7 @@ joker {
|
|||
key = "nilly",
|
||||
pronouns = "any_all",
|
||||
config = {extra = {flipped = false}},
|
||||
attributes = {"xmult"},
|
||||
attributes = {"xmult", "bakery_double_sided"},
|
||||
cost = 0,
|
||||
rarity = 2,
|
||||
eternal_compat = true,
|
||||
|
|
@ -602,10 +617,6 @@ joker {
|
|||
local key = card.ability.extra.flipped and "b_Roland_enabled" or "b_Roland_disabled"
|
||||
return {vars = {localize {type = "variable", key = key}}}
|
||||
end,
|
||||
inject = function(...)
|
||||
SMODS.Joker.inject(...)
|
||||
Bakery_API.double_sided_jokers.j_Roland_nilly = true
|
||||
end,
|
||||
calculate = function(_, card, context)
|
||||
if (not context.joker_main or not card.ability.extra.flipped) and not context.forcetrigger then
|
||||
return
|
||||
|
|
@ -628,7 +639,7 @@ joker {
|
|||
|
||||
joker {
|
||||
key = "amber",
|
||||
pronouns = "he_they",
|
||||
pronouns = "they_them",
|
||||
config = {extra = {xmult = 3}},
|
||||
pixel_size = {w = 68, h = 68},
|
||||
attributes = {"xmult"},
|
||||
|
|
@ -709,7 +720,7 @@ joker {
|
|||
|
||||
joker {
|
||||
key = "idle",
|
||||
pronouns = "they_them",
|
||||
pronouns = "any_all",
|
||||
rarity = 2,
|
||||
Roland_idle_capacity = 6,
|
||||
cost = G.P_CENTERS.j_idol.cost,
|
||||
|
|
@ -749,28 +760,39 @@ joker {
|
|||
end):any(f().eq(context.other_card)) and {xmult = card.ability.extra.xmult} or nil
|
||||
end,
|
||||
Bakery_can_use = function(self, card)
|
||||
local key = self:Roland_idle_status(card)
|
||||
local new_cards = G.hand.highlighted
|
||||
local extra = card.ability.extra
|
||||
|
||||
if extra.last_text ~= key then
|
||||
extra.last_text = key
|
||||
Bakery_API.rehighlight(card)
|
||||
end
|
||||
|
||||
local function all_cards()
|
||||
return f(new_cards):concat(extra.cards or {})
|
||||
end
|
||||
|
||||
return not card.debuff and
|
||||
next(G.hand.highlighted) and
|
||||
self.Roland_idle_capacity - #card.ability.extra.cards - #G.hand.highlighted >= 0 and
|
||||
f(G.hand.highlighted):all(function(v)
|
||||
return not SMODS.has_no_rank(v) and
|
||||
not SMODS.has_no_suit(v) and
|
||||
f(card.ability.extra.cards or {}):all(function(o)
|
||||
return v.base.suit ~= o.suit or v.base.value ~= o.value
|
||||
end)
|
||||
next(new_cards) and
|
||||
self.Roland_idle_capacity - #extra.cards - #new_cards >= 0 and
|
||||
f(new_cards):all(has_rank_and_suit) and
|
||||
all_cards():all(function(v)
|
||||
return all_cards():all(ranksuitnq(v))
|
||||
end)
|
||||
end,
|
||||
Bakery_use_button_text = function(self, card)
|
||||
local key = card.debuff and "b_Roland_debuffed" or
|
||||
(self.Roland_idle_capacity - #card.ability.extra.cards > 0 and "b_Roland_add" or "b_Roland_full")
|
||||
|
||||
return localize {type = "variable", key = key}
|
||||
return localize {type = "variable", key = self:Roland_idle_status(card)}
|
||||
end,
|
||||
Bakery_use_joker = function(_, card)
|
||||
f(G.hand.highlighted):each(function(v)
|
||||
table.insert(card.ability.extra.cards, {suit = v.base.suit, value = v.base.value})
|
||||
end)
|
||||
end,
|
||||
Roland_idle_status = function(self, card)
|
||||
return card.debuff and "b_Roland_debuffed" or
|
||||
(self.Roland_idle_capacity - #card.ability.extra.cards > 0 and "b_Roland_add" or "b_Roland_full")
|
||||
end,
|
||||
}
|
||||
|
||||
joker {
|
||||
|
|
@ -827,7 +849,7 @@ end
|
|||
|
||||
joker {
|
||||
key = "artemis",
|
||||
pronouns = "she_they",
|
||||
pronouns = "any_all",
|
||||
cost = 6,
|
||||
rarity = 2,
|
||||
config = {extra = {
|
||||
|
|
@ -837,13 +859,10 @@ joker {
|
|||
flipped = false,
|
||||
sequence = {"c_earth", "c_mars", "c_earth"},
|
||||
}},
|
||||
attributes = {"economy", "scaling", "planet", "space", "bakery_double_sided"},
|
||||
calc_dollar_bonus = function(_, card)
|
||||
return card.ability.extra.dollars
|
||||
end,
|
||||
inject = function(...)
|
||||
SMODS.Joker.inject(...)
|
||||
Bakery_API.double_sided_jokers.j_Roland_artemis = true
|
||||
end,
|
||||
loc_vars = function(_, info_queue, card)
|
||||
local extra = card.ability.extra
|
||||
|
||||
|
|
@ -895,7 +914,7 @@ joker {
|
|||
cost = 7,
|
||||
rarity = 3,
|
||||
config = {extra = {probability = 1, probability_mult = 2, reset = 1}},
|
||||
attributes = {"hands", "mod_chance", "scaling"},
|
||||
attributes = {"hands", "mod_chance", "scaling", "reset"},
|
||||
eternal_compat = true,
|
||||
blueprint_compat = false,
|
||||
perishable_compat = true,
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ end
|
|||
---@nodiscard
|
||||
function f.index(v)
|
||||
return function(x)
|
||||
return x[v]
|
||||
return x and x[v]
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -512,7 +512,7 @@ end
|
|||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
---@param func F|fun(v: V, k: K): boolean
|
||||
---@param func F|fun(v: V, k: K): any
|
||||
---@return boolean|V
|
||||
---@nodiscard
|
||||
---@overload fun(self: F|{ [K]: V }, func: string?): boolean|V
|
||||
|
|
@ -530,7 +530,7 @@ end
|
|||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
---@param func F|fun(v: V, k: K): boolean
|
||||
---@param func F|fun(v: V, k: K): any
|
||||
---@return boolean|V
|
||||
---@nodiscard
|
||||
---@overload fun(self: F|{ [K]: V }, func: string?): boolean|V
|
||||
|
|
@ -548,7 +548,7 @@ end
|
|||
|
||||
---@generic K, V
|
||||
---@param self F|{ [K]: V }
|
||||
---@param func F|fun(v: V, k: K): boolean
|
||||
---@param func F|fun(v: V, k: K): any
|
||||
---@return integer
|
||||
---@nodiscard
|
||||
---@overload fun(self: F|{ [K]: V }, func: string): integer
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ local function protect_ev(fun)
|
|||
return fun
|
||||
end
|
||||
|
||||
---@alias Attributes "mult"|"chips"|"xmult"|"xchips"|"score"|"xscore"|"blindsize"|"xblindsize"|"balance"|"swap"|"retrigger"|"scaling"|"reset"|"suit"|"diamonds"|"hearts"|"spades"|"clubs"|"hand_type"|"rank"|"ace"|"two"|"three"|"four"|"five"|"six"|"seven"|"eight"|"nine"|"ten"|"jack"|"queen"|"king"|"face"|"economy"|"generation"|"destroy_card"|"hands"|"discard"|"hand_size"|"chance"|"joker_slot"|"mod_chance"|"copying"|"full_deck"|"passive"|"joker"|"tarot"|"planet"|"spectral"|"enhancements"|"seals"|"editions"|"tag"|"skip"|"modify_card"|"perma_bonus"|"prevents_death"|"boss_blind"|"reroll"|"on_sell"|"sell_value"|"food"|"space"
|
||||
---@alias Attributes "mult"|"chips"|"xmult"|"xchips"|"score"|"xscore"|"blindsize"|"xblindsize"|"balance"|"swap"|"retrigger"|"scaling"|"reset"|"suit"|"diamonds"|"hearts"|"spades"|"clubs"|"hand_type"|"rank"|"ace"|"two"|"three"|"four"|"five"|"six"|"seven"|"eight"|"nine"|"ten"|"jack"|"queen"|"king"|"face"|"economy"|"generation"|"destroy_card"|"hands"|"discard"|"hand_size"|"chance"|"joker_slot"|"mod_chance"|"copying"|"full_deck"|"passive"|"joker"|"tarot"|"planet"|"spectral"|"enhancements"|"seals"|"editions"|"tag"|"skip"|"modify_card"|"perma_bonus"|"prevents_death"|"boss_blind"|"reroll"|"on_sell"|"sell_value"|"food"|"space"|"bakery_double_sided"
|
||||
if false then
|
||||
-- This allows for better type inference.
|
||||
SMODS.Mods.Roland.config = require "config"
|
||||
|
|
|
|||
|
|
@ -52,8 +52,11 @@ end
|
|||
SMODS.Atlas {
|
||||
px = 256,
|
||||
py = 256,
|
||||
fps = 12,
|
||||
frames = 12,
|
||||
key = "modicon",
|
||||
path = "icon.png",
|
||||
atlas_table = "ANIMATION_ATLAS",
|
||||
}
|
||||
|
||||
SMODS.current_mod.qol = qol
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ SMODS.Seal {
|
|||
pos = {x = 0, y = 0},
|
||||
attributes = {"destroy_card", "tag"},
|
||||
badge_colour = HEX "a6a6a6ff",
|
||||
pronouns = "he_him",
|
||||
pronouns = "they_them",
|
||||
calculate = function(_, card, context)
|
||||
local function eq(v)
|
||||
return v == card
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ SMODS.Sound {
|
|||
|
||||
spectral {
|
||||
key = "afterimage",
|
||||
pronouns = "he_they",
|
||||
pronouns = "she_they",
|
||||
artist = "aster",
|
||||
config = {extra = {amount = 2}},
|
||||
attributes = {"seal", "modify_card", "spectral"},
|
||||
|
|
@ -69,6 +69,7 @@ spectral {
|
|||
spectral {
|
||||
key = "primal",
|
||||
pronouns = "he_him",
|
||||
artist = "aster",
|
||||
attributes = {"enhancements", "modify_card", "spectral"},
|
||||
loc_vars = function(_, info_queue)
|
||||
table.insert(info_queue, G.P_CENTERS.m_stone)
|
||||
|
|
@ -128,7 +129,7 @@ spectral {
|
|||
|
||||
spectral {
|
||||
key = "refract",
|
||||
pronouns = "he_him",
|
||||
pronouns = "it_its",
|
||||
artist = "aster",
|
||||
config = {extra = {amount = 2}},
|
||||
attributes = {"seal", "modify_card", "spectral"},
|
||||
|
|
|
|||
35
src/tag.lua
|
|
@ -55,6 +55,7 @@ end
|
|||
SMODS.Tag {
|
||||
key = "freeze",
|
||||
atlas = "tag",
|
||||
pronouns = "any_all",
|
||||
min_ante = 1,
|
||||
pos = {x = 0, y = 0},
|
||||
config = {amount = 5},
|
||||
|
|
@ -73,6 +74,7 @@ SMODS.Tag {
|
|||
|
||||
if tag.triggered or
|
||||
(tag.ability.amount or self.config.amount) <= 0 or
|
||||
(context.card.edition and context.card.edition.Roland_frozen) or
|
||||
context.type ~= "Bakery_score_card" then
|
||||
return
|
||||
end
|
||||
|
|
@ -85,13 +87,42 @@ SMODS.Tag {
|
|||
SMODS.Tag {
|
||||
key = "invisible",
|
||||
atlas = "tag",
|
||||
pronouns = "any_all",
|
||||
min_ante = 2,
|
||||
pos = {x = 1, y = 0},
|
||||
apply = function(_, tag)
|
||||
config = {invis_rounds = 0, total_rounds = 2},
|
||||
loc_vars = function(self, _, tag)
|
||||
tag.ability = tag.ability or f(self.config):table()
|
||||
local main_end = {}
|
||||
|
||||
local _ = f((G.jokers or {}).cards or {}):map "edition":any "negative" and
|
||||
localize {type = "other", key = "remove_negative", nodes = main_end, vars = {}}
|
||||
|
||||
return {
|
||||
vars = {
|
||||
tag.ability.total_rounds or self.config.total_rounds,
|
||||
tag.ability.invis_rounds or self.config.invis_rounds,
|
||||
},
|
||||
main_end = main_end[1],
|
||||
}
|
||||
end,
|
||||
increment = function(self)
|
||||
f(G.GAME.tags):where("key", "tag_Roland_invisible"):each(function(v)
|
||||
v.ability = v.ability or {}
|
||||
v.ability.invis_rounds = (v.ability.invis_rounds or self.config.invis_rounds) + 1
|
||||
v:juice_up()
|
||||
end)
|
||||
end,
|
||||
apply = function(self, tag)
|
||||
local modifiers = G.GAME.modifiers
|
||||
tag.ability = tag.ability or {}
|
||||
local ab = tag.ability
|
||||
ab.invis_rounds = ab.invis_rounds or self.config.invis_rounds
|
||||
ab.total_rounds = ab.total_rounds or self.config.total_rounds
|
||||
|
||||
if tag.triggered or
|
||||
not next(G.jokers.cards) or
|
||||
ab.invis_rounds < ab.total_rounds or
|
||||
#G.jokers.cards + (modifiers.Roland_invisible or 0) >= G.jokers.config.card_limit then
|
||||
return
|
||||
end
|
||||
|
|
@ -101,7 +132,7 @@ SMODS.Tag {
|
|||
|
||||
tag:yep("!", G.C.GREY, function()
|
||||
local copied = pseudorandom_element(G.jokers.cards, pseudoseed "Roland_invisible")
|
||||
local copy = copy_card(copied)
|
||||
local copy = copy_card(copied, nil, nil, nil, copied.edition and copied.edition.negative)
|
||||
G.jokers:emplace(copy)
|
||||
copy:add_to_deck()
|
||||
modifiers.Roland_invisible = (modifiers.Roland_invisible or 0) - 1
|
||||
|
|
|
|||