1811 lines
50 KiB
Lua
1811 lines
50 KiB
Lua
-- gameset.lua: functions for gameset UI and logic
|
|
|
|
-- Future changes I want to make to this:
|
|
-- - Sort cards in the Cryptid additions tab in collection order
|
|
-- - Give thematic sets a button to view content from just their set
|
|
-- - Edition decks and similar display their editions in the gameset config UI
|
|
|
|
-------------------------
|
|
------ MODS LIST --------
|
|
-------------------------
|
|
|
|
-- If you plan on adding any new cross-mod content with one of these mods within the Cryptid source,
|
|
-- please add the name here so it displays properly in the Disabled message.
|
|
-- do it in the format MOD_ID = "MOD_NAME"
|
|
Cryptid.cross_mod_names = {
|
|
CardSleeves = "Card Sleeves",
|
|
Cryptid = "Cryptid",
|
|
jen = "Jen's Almanac",
|
|
sdm0sstuff = "SDM_0's Stuff",
|
|
magic_the_jokering = "Magic the Jokering",
|
|
}
|
|
-------------------------
|
|
---- TUTORIAL SYSTEM ----
|
|
-------------------------
|
|
|
|
local gu = Game.update
|
|
function Game:update(dt)
|
|
gu(self, dt)
|
|
if not G.PROFILES[G.SETTINGS.profile].cry_intro_complete then
|
|
G.FUNCS.cry_intro_controller()
|
|
end
|
|
end
|
|
|
|
G.FUNCS.cry_intro_controller = function()
|
|
if Jen then
|
|
G.PROFILES[G.SETTINGS.profile].cry_intro_complete = true
|
|
G.PROFILES[G.SETTINGS.profile].cry_gameset = "madness"
|
|
end
|
|
G.PROFILES[G.SETTINGS.profile].cry_intro_progress = G.PROFILES[G.SETTINGS.profile].cry_intro_progress
|
|
or {
|
|
state = "start",
|
|
completed = {},
|
|
}
|
|
if not G.SETTINGS.paused and not G.PROFILES[G.SETTINGS.profile].cry_intro_complete then
|
|
if G.STATE == G.STATES.MENU and not G.PROFILES[G.SETTINGS.profile].cry_intro_progress.completed.start then
|
|
G.PROFILES[G.SETTINGS.profile].cry_intro_progress.section = "start"
|
|
G.FUNCS.cry_intro_part("start")
|
|
G.PROFILES[G.SETTINGS.profile].cry_intro_progress.completed.start = true
|
|
G:save_progress()
|
|
end
|
|
end
|
|
end
|
|
|
|
function create_UIBox_character_button_with_sprite(args)
|
|
local button = args.button or "NONE"
|
|
local func = args.func or nil
|
|
local colour = args.colour or G.C.RED
|
|
local update_func = args.update_func or nil
|
|
local sprite = args.sprite or nil
|
|
|
|
local t = --{n=G.UIT.ROOT, config = {align = "cm", padding = 0.1, colour = G.C.CLEAR}, nodes={
|
|
{
|
|
n = G.UIT.C,
|
|
config = {
|
|
align = "tm",
|
|
minw = 2.5,
|
|
padding = 0.2,
|
|
minh = 1.2,
|
|
r = 0.1,
|
|
hover = true,
|
|
colour = colour,
|
|
button = func,
|
|
func = update_func,
|
|
shadow = true,
|
|
maxw = args.maxw,
|
|
id = args.id,
|
|
},
|
|
nodes = {
|
|
{
|
|
n = G.UIT.R,
|
|
config = { align = "cm", padding = 0 },
|
|
nodes = {
|
|
{
|
|
n = G.UIT.T,
|
|
config = {
|
|
text = button,
|
|
scale = 0.55,
|
|
colour = G.C.UI.TEXT_LIGHT,
|
|
focus_args = { button = "x", orientation = "bm" },
|
|
func = "set_button_pip",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
n = G.UIT.R,
|
|
config = { align = "cm", padding = 0 },
|
|
nodes = {
|
|
{ n = G.UIT.O, config = { object = sprite } },
|
|
},
|
|
},
|
|
},
|
|
} --,
|
|
--}}
|
|
return t
|
|
end
|
|
|
|
G.FUNCS.cry_intro_part = function(_part)
|
|
local step = 1
|
|
G.SETTINGS.paused = true
|
|
if _part == "start" then
|
|
G.gateway = Sprite(
|
|
G.ROOM_ATTACH.T.x + G.ROOM_ATTACH.T.w / 2 - 1,
|
|
G.ROOM_ATTACH.T.y + G.ROOM_ATTACH.T.h / 2 - 4,
|
|
G.CARD_W * 1.5,
|
|
G.CARD_H * 1.5,
|
|
G.ASSET_ATLAS["cry_atlasnotjokers"],
|
|
{ x = 2, y = 0 }
|
|
)
|
|
G.gateway.states.visible = false
|
|
G.gateway.states.collide.can = true
|
|
G.gateway.states.focus.can = false
|
|
G.gateway.states.hover.can = true
|
|
G.gateway.states.drag.can = false
|
|
G.gateway.hover = Node.hover
|
|
G.yawetag = Sprite(
|
|
G.ROOM_ATTACH.T.x + G.ROOM_ATTACH.T.w / 2 - 1,
|
|
G.ROOM_ATTACH.T.y + G.ROOM_ATTACH.T.h / 2 - 4,
|
|
G.CARD_W * 1.5,
|
|
G.CARD_H * 1.5,
|
|
G.ASSET_ATLAS["cry_atlasnotjokers"],
|
|
{ x = 6, y = 5 }
|
|
)
|
|
G.yawetag.states.visible = false
|
|
G.yawetag.states.collide.can = true
|
|
G.yawetag.states.focus.can = false
|
|
G.yawetag.states.hover.can = true
|
|
G.yawetag.states.drag.can = false
|
|
G.yawetag.hover = Node.hover
|
|
step = cry_intro_info({
|
|
text_key = "cry_intro_1",
|
|
attach = { major = G.ROOM_ATTACH, type = "cm", offset = { x = 0, y = 0 } },
|
|
step = step,
|
|
})
|
|
step = cry_intro_info({
|
|
text_key = "cry_intro_2",
|
|
attach = { major = G.ROOM_ATTACH, type = "cm", offset = { x = 0, y = -3 } },
|
|
step = step,
|
|
})
|
|
step = cry_intro_info({
|
|
text_key = "cry_intro_3",
|
|
attach = { major = G.ROOM_ATTACH, type = "cm", offset = { x = 0, y = -3 } },
|
|
step = step,
|
|
highlight = {
|
|
G.gateway,
|
|
G.yawetag,
|
|
},
|
|
on_start = function()
|
|
G.gateway.states.visible = true
|
|
G.gateway:set_alignment({ major = G.ROOM_ATTACH, type = "cm", offset = { x = -2.5, y = -3 } })
|
|
G.yawetag.states.visible = true
|
|
G.yawetag:set_alignment({ major = G.ROOM_ATTACH, type = "cm", offset = { x = 2.5, y = -3 } })
|
|
end,
|
|
})
|
|
step = cry_intro_info({
|
|
text_key = "cry_intro_4",
|
|
attach = { major = G.ROOM_ATTACH, type = "cm", offset = { x = 0, y = -3 } },
|
|
step = step,
|
|
highlight = {
|
|
G.gateway,
|
|
G.yawetag,
|
|
},
|
|
})
|
|
local modestSprite = Sprite(0, 0, 1, 1, G.ASSET_ATLAS["cry_gameset"], { x = 0, y = 0 })
|
|
modestSprite:define_draw_steps({
|
|
{ shader = "dissolve", shadow_height = 0.05 },
|
|
{ shader = "dissolve" },
|
|
})
|
|
local mainlineSprite = Sprite(0, 0, 1, 1, G.ASSET_ATLAS["cry_gameset"], { x = 1, y = 0 })
|
|
mainlineSprite:define_draw_steps({
|
|
{ shader = "dissolve", shadow_height = 0.05 },
|
|
{ shader = "dissolve" },
|
|
})
|
|
local madnessSprite = Sprite(0, 0, 1, 1, G.ASSET_ATLAS["cry_gameset"], { x = 2, y = 0 })
|
|
madnessSprite:define_draw_steps({
|
|
{ shader = "dissolve", shadow_height = 0.05 },
|
|
{ shader = "dissolve" },
|
|
})
|
|
--TODO: localize
|
|
G.modestBtn = create_UIBox_character_button_with_sprite({
|
|
sprite = modestSprite,
|
|
button = "Modest",
|
|
id = "modest",
|
|
func = "cry_modest",
|
|
colour = G.C.GREEN,
|
|
maxw = 3,
|
|
})
|
|
G.mainlineBtn = create_UIBox_character_button_with_sprite({
|
|
sprite = mainlineSprite,
|
|
button = "Mainline",
|
|
id = "mainline",
|
|
func = "cry_mainline",
|
|
colour = G.C.RED,
|
|
maxw = 3,
|
|
})
|
|
G.madnessBtn = create_UIBox_character_button_with_sprite({
|
|
sprite = madnessSprite,
|
|
button = "Madness",
|
|
id = "madness",
|
|
func = "cry_madness",
|
|
colour = G.C.CRY_EXOTIC,
|
|
maxw = 3,
|
|
})
|
|
local gamesetUI = create_UIBox_generic_options({
|
|
infotip = false,
|
|
contents = {
|
|
G.modestBtn,
|
|
G.mainlineBtn,
|
|
G.madnessBtn,
|
|
},
|
|
back_label = "Confirm",
|
|
back_colour = G.C.BLUE,
|
|
back_func = "cry_gameset_confirm",
|
|
})
|
|
G.E_MANAGER:add_event(Event({
|
|
trigger = "after",
|
|
blocking = false,
|
|
blockable = false,
|
|
func = function()
|
|
G.madnessBtn.config.colour = G.C.CRY_EXOTIC
|
|
return true
|
|
end,
|
|
}))
|
|
gamesetUI.nodes[2] = nil
|
|
gamesetUI.config.colour = G.C.CLEAR
|
|
G.gamesetUI = UIBox({
|
|
definition = gamesetUI,
|
|
config = { major = G.ROOM_ATTACH, type = "cm", offset = { x = 0, y = 2.5 } },
|
|
})
|
|
G.gamesetUI.states.visible = false
|
|
step = cry_intro_info({
|
|
text_key = "cry_intro_5",
|
|
attach = { major = G.ROOM_ATTACH, type = "cm", offset = { x = 0, y = -3 } },
|
|
step = step,
|
|
highlight = {
|
|
G.gateway,
|
|
G.yawetag,
|
|
G.gamesetUI,
|
|
},
|
|
on_start = function()
|
|
--the scaling should be eased later...
|
|
G.gamesetUI.states.visible = true
|
|
G.gateway:set_alignment({ major = G.ROOM_ATTACH, type = "cm", offset = { x = -4.5, y = 2.2 } })
|
|
G.gateway.T.w = G.gateway.T.w * 3
|
|
G.gateway.T.h = G.gateway.T.h * 3
|
|
G.yawetag:set_alignment({ major = G.ROOM_ATTACH, type = "cm", offset = { x = 4.5, y = 2.2 } })
|
|
G.yawetag.T.w = G.yawetag.T.w * 3
|
|
G.yawetag.T.h = G.yawetag.T.h * 3
|
|
end,
|
|
no_button = true,
|
|
})
|
|
end
|
|
if _part == "modest" or _part == "mainline" or _part == "madness" then
|
|
local desc_length = { --number of times Jolly Joker speaks for each gameset
|
|
modest = 2,
|
|
mainline = 3,
|
|
madness = 3,
|
|
}
|
|
G.E_MANAGER:clear_queue("tutorial")
|
|
if G.OVERLAY_TUTORIAL.content then
|
|
G.OVERLAY_TUTORIAL.content:remove()
|
|
end
|
|
G.OVERLAY_TUTORIAL.Jimbo:remove_button()
|
|
G.OVERLAY_TUTORIAL.Jimbo:remove_speech_bubble()
|
|
G.OVERLAY_TUTORIAL.step = nil
|
|
for i = 1, desc_length[_part] do
|
|
step = cry_intro_info({
|
|
text_key = "cry_" .. _part .. "_" .. i,
|
|
attach = { major = G.ROOM_ATTACH, type = "cm", offset = { x = 0, y = -3 } },
|
|
step = step,
|
|
highlight = {
|
|
G.gamesetUI:get_UIE_by_ID(_part),
|
|
},
|
|
})
|
|
end
|
|
step = cry_intro_info({
|
|
no_button = true,
|
|
attach = { major = G.ROOM_ATTACH, type = "cm", offset = { x = 0, y = -3 } },
|
|
step = step,
|
|
highlight = {
|
|
G.gateway,
|
|
G.yawetag,
|
|
G.gamesetUI,
|
|
},
|
|
})
|
|
end
|
|
end
|
|
|
|
G.FUNCS.cry_modest = function(e)
|
|
G.modestBtn.config.colour = G.C.CRY_SELECTED
|
|
G.mainlineBtn.config.colour = G.C.RED
|
|
G.madnessBtn.config.colour = G.C.CRY_EXOTIC
|
|
G.FUNCS.cry_intro_part("modest")
|
|
G.selectedGameset = "modest"
|
|
end
|
|
G.FUNCS.cry_mainline = function(e)
|
|
G.modestBtn.config.colour = G.C.GREEN
|
|
G.mainlineBtn.config.colour = G.C.CRY_SELECTED
|
|
G.madnessBtn.config.colour = G.C.CRY_EXOTIC
|
|
G.FUNCS.cry_intro_part("mainline")
|
|
G.selectedGameset = "mainline"
|
|
end
|
|
G.FUNCS.cry_madness = function(e)
|
|
G.modestBtn.config.colour = G.C.GREEN
|
|
G.mainlineBtn.config.colour = G.C.RED
|
|
G.madnessBtn.config.colour = G.C.CRY_SELECTED
|
|
G.FUNCS.cry_intro_part("madness")
|
|
G.selectedGameset = "madness"
|
|
end
|
|
G.FUNCS.cry_gameset_confirm = function(e)
|
|
if G.selectedGameset then
|
|
G.PROFILES[G.SETTINGS.profile].cry_intro_complete = true
|
|
G.PROFILES[G.SETTINGS.profile].cry_gameset = G.selectedGameset
|
|
G.SETTINGS.paused = false
|
|
G.gamesetUI:remove()
|
|
G.gateway:remove()
|
|
G.yawetag:remove()
|
|
G.E_MANAGER:clear_queue("tutorial")
|
|
G.OVERLAY_TUTORIAL.Jimbo:remove()
|
|
if G.OVERLAY_TUTORIAL.content then
|
|
G.OVERLAY_TUTORIAL.content:remove()
|
|
end
|
|
G.OVERLAY_TUTORIAL:remove()
|
|
G.OVERLAY_TUTORIAL = nil
|
|
if G.selectedGameset == "madness" then
|
|
--Unlock All by default in madness
|
|
G.PROFILES[G.SETTINGS.profile].all_unlocked = true
|
|
for k, v in pairs(G.P_CENTERS) do
|
|
if not v.demo and not v.wip then
|
|
v.alerted = true
|
|
v.discovered = true
|
|
v.unlocked = true
|
|
end
|
|
end
|
|
for k, v in pairs(G.P_BLINDS) do
|
|
if not v.demo and not v.wip then
|
|
v.alerted = true
|
|
v.discovered = true
|
|
v.unlocked = true
|
|
end
|
|
end
|
|
for k, v in pairs(G.P_TAGS) do
|
|
if not v.demo and not v.wip then
|
|
v.alerted = true
|
|
v.discovered = true
|
|
v.unlocked = true
|
|
end
|
|
end
|
|
set_profile_progress()
|
|
set_discover_tallies()
|
|
G:save_progress()
|
|
G.FILE_HANDLER.force = true
|
|
end
|
|
end
|
|
end
|
|
|
|
function cry_intro_info(args)
|
|
local overlay_colour = { 0.32, 0.36, 0.41, 0 }
|
|
ease_value(overlay_colour, 4, 0.6, nil, "REAL", true, 0.4)
|
|
G.OVERLAY_TUTORIAL = G.OVERLAY_TUTORIAL
|
|
or UIBox({
|
|
definition = {
|
|
n = G.UIT.ROOT,
|
|
config = { align = "cm", padding = 32.05, r = 0.1, colour = overlay_colour, emboss = 0.05 },
|
|
nodes = {},
|
|
},
|
|
config = {
|
|
align = "cm",
|
|
offset = { x = 0, y = 3.2 },
|
|
major = G.ROOM_ATTACH,
|
|
bond = "Weak",
|
|
},
|
|
})
|
|
G.OVERLAY_TUTORIAL.step = G.OVERLAY_TUTORIAL.step or 1
|
|
G.OVERLAY_TUTORIAL.step_complete = false
|
|
local row_dollars_chips = G.HUD and G.HUD:get_UIE_by_ID("row_dollars_chips") or G.ROOM_ATTACH
|
|
local align = args.align or "tm"
|
|
local step = args.step or 1
|
|
local attach = args.attach or { major = row_dollars_chips, type = "tm", offset = { x = 0, y = -0.5 } }
|
|
local pos = args.pos or { x = attach.major.T.x + attach.major.T.w / 2, y = attach.major.T.y + attach.major.T.h / 2 }
|
|
local button = args.button or { button = localize("b_next"), func = "tut_next" }
|
|
args.highlight = args.highlight or {}
|
|
G.E_MANAGER:add_event(
|
|
Event({
|
|
trigger = "after",
|
|
delay = 0.3,
|
|
func = function()
|
|
if G.OVERLAY_TUTORIAL and G.OVERLAY_TUTORIAL.step == step and not G.OVERLAY_TUTORIAL.step_complete then
|
|
if args.on_start then
|
|
args.on_start()
|
|
end
|
|
G.CONTROLLER.interrupt.focus = true
|
|
G.OVERLAY_TUTORIAL.Jimbo = G.OVERLAY_TUTORIAL.Jimbo or Card_Character(pos)
|
|
if type(args.highlight) == "function" then
|
|
args.highlight = args.highlight()
|
|
end
|
|
args.highlight[#args.highlight + 1] = G.OVERLAY_TUTORIAL.Jimbo
|
|
if args.text_key then
|
|
G.OVERLAY_TUTORIAL.Jimbo:add_speech_bubble(args.text_key, align, args.loc_vars)
|
|
end
|
|
G.OVERLAY_TUTORIAL.Jimbo:set_alignment(attach)
|
|
if args.hard_set then
|
|
G.OVERLAY_TUTORIAL.Jimbo:hard_set_VT()
|
|
end
|
|
G.OVERLAY_TUTORIAL.button_listen = nil
|
|
if G.OVERLAY_TUTORIAL.content then
|
|
G.OVERLAY_TUTORIAL.content:remove()
|
|
end
|
|
if args.content then
|
|
G.OVERLAY_TUTORIAL.content = UIBox({
|
|
definition = args.content(),
|
|
config = {
|
|
align = args.content_config and args.content_config.align or "cm",
|
|
offset = args.content_config and args.content_config.offset or { x = 0, y = 0 },
|
|
major = args.content_config and args.content_config.major or G.OVERLAY_TUTORIAL.Jimbo,
|
|
bond = "Weak",
|
|
},
|
|
})
|
|
args.highlight[#args.highlight + 1] = G.OVERLAY_TUTORIAL.content
|
|
end
|
|
if args.button_listen then
|
|
G.OVERLAY_TUTORIAL.button_listen = args.button_listen
|
|
end
|
|
if not args.no_button then
|
|
G.OVERLAY_TUTORIAL.Jimbo:add_button(
|
|
button.button,
|
|
button.func,
|
|
button.colour,
|
|
button.update_func,
|
|
true
|
|
)
|
|
end
|
|
G.OVERLAY_TUTORIAL.Jimbo:say_stuff(2 * #(G.localization.misc.tutorial[args.text_key] or {}) + 1)
|
|
if args.snap_to then
|
|
G.E_MANAGER:add_event(
|
|
Event({
|
|
trigger = "immediate",
|
|
blocking = false,
|
|
blockable = false,
|
|
func = function()
|
|
if
|
|
G.OVERLAY_TUTORIAL
|
|
and G.OVERLAY_TUTORIAL.Jimbo
|
|
and not G.OVERLAY_TUTORIAL.Jimbo.talking
|
|
then
|
|
local _snap_to = args.snap_to()
|
|
if _snap_to then
|
|
G.CONTROLLER.interrupt.focus = false
|
|
G.CONTROLLER:snap_to({ node = args.snap_to() })
|
|
end
|
|
return true
|
|
end
|
|
end,
|
|
}),
|
|
"tutorial"
|
|
)
|
|
end
|
|
if args.highlight then
|
|
G.OVERLAY_TUTORIAL.highlights = args.highlight
|
|
end
|
|
G.OVERLAY_TUTORIAL.step_complete = true
|
|
end
|
|
return not G.OVERLAY_TUTORIAL or G.OVERLAY_TUTORIAL.step > step or G.OVERLAY_TUTORIAL.skip_steps
|
|
end,
|
|
}),
|
|
"tutorial"
|
|
)
|
|
return step + 1
|
|
end
|
|
|
|
-- Profile stuff: all profiles start with M to separate from vanilla
|
|
function G.UIDEF.profile_select()
|
|
G.focused_profile = G.focused_profile or G.SETTINGS.profile or (Cryptid.profile_prefix .. "1")
|
|
|
|
local t = create_UIBox_generic_options({
|
|
padding = 0,
|
|
contents = {
|
|
{
|
|
n = G.UIT.R,
|
|
config = { align = "cm", padding = 0, draw_layer = 1, minw = 4 },
|
|
nodes = {
|
|
create_tabs({
|
|
tabs = {
|
|
{
|
|
label = Cryptid.profile_prefix .. "1",
|
|
chosen = G.focused_profile == (Cryptid.profile_prefix .. "1"),
|
|
tab_definition_function = G.UIDEF.profile_option,
|
|
tab_definition_function_args = Cryptid.profile_prefix .. "1",
|
|
},
|
|
{
|
|
label = Cryptid.profile_prefix .. "2",
|
|
chosen = G.focused_profile == (Cryptid.profile_prefix .. "2"),
|
|
tab_definition_function = G.UIDEF.profile_option,
|
|
tab_definition_function_args = Cryptid.profile_prefix .. "2",
|
|
},
|
|
{
|
|
label = Cryptid.profile_prefix .. "3",
|
|
chosen = G.focused_profile == (Cryptid.profile_prefix .. "3"),
|
|
tab_definition_function = G.UIDEF.profile_option,
|
|
tab_definition_function_args = Cryptid.profile_prefix .. "3",
|
|
},
|
|
},
|
|
snap_to_nav = true,
|
|
}),
|
|
},
|
|
},
|
|
},
|
|
})
|
|
return t
|
|
end
|
|
|
|
------------------------
|
|
---- GAMESET SYSTEM ----
|
|
------------------------
|
|
|
|
-- Gets gameset sprite of current profile
|
|
function gameset_sprite(scale, profile, force_gameset)
|
|
gameset = force_gameset
|
|
or G.PROFILES[profile or G.SETTINGS.profile].cry_gameset_overrides and "modified"
|
|
or G.PROFILES[profile or G.SETTINGS.profile].cry_gameset
|
|
scale = scale or 1
|
|
local sprite = Sprite(
|
|
0,
|
|
0,
|
|
scale,
|
|
scale,
|
|
G.ASSET_ATLAS["cry_gameset"],
|
|
{ x = (gameset == "modified" and 3 or gameset == "madness" and 2 or gameset == "modest" and 0 or 1), y = 0 }
|
|
)
|
|
sprite:define_draw_steps({
|
|
{ shader = "dissolve", shadow_height = 0.09 },
|
|
{ shader = "dissolve" },
|
|
})
|
|
sprite.states.collide.can = true
|
|
sprite.states.drag.can = true
|
|
return sprite
|
|
end
|
|
|
|
-- designed to work on any object type
|
|
function cry_get_gameset(card, center)
|
|
if Jen then
|
|
return "madness"
|
|
end
|
|
if not center then
|
|
if not card then
|
|
return G.PROFILES[G.SETTINGS.profile].cry_gameset or "mainline"
|
|
end
|
|
center = card.config and card.config.center or card.effect and card.effect.center or card
|
|
end
|
|
if card.force_gameset then
|
|
return card.force_gameset
|
|
end
|
|
if center.force_gameset then
|
|
return center.force_gameset
|
|
end
|
|
if center.fake_card then
|
|
return G.PROFILES[G.SETTINGS.profile].cry_gameset or "mainline"
|
|
end
|
|
if not center.key then
|
|
if center.tag and center.tag.key then --dumb fix for tags
|
|
center = center.tag
|
|
else
|
|
print("Could not find key for center: " .. tprint(center))
|
|
return G.PROFILES[G.SETTINGS.profile].cry_gameset or "mainline"
|
|
end
|
|
end
|
|
local gameset = G.PROFILES[G.SETTINGS.profile].cry_gameset or "mainline"
|
|
if Cryptid_config.experimental and center.extra_gamesets then
|
|
for i = 1, #center.extra_gamesets do
|
|
if center.extra_gamesets[i] == "experimental_" .. gameset then
|
|
gameset = "experimental_" .. gameset
|
|
break
|
|
elseif center.extra_gamesets[i] == "experimental" then
|
|
gameset = "experimental"
|
|
break
|
|
end
|
|
end
|
|
end
|
|
if
|
|
G.PROFILES[G.SETTINGS.profile].cry_gameset_overrides
|
|
and G.PROFILES[G.SETTINGS.profile].cry_gameset_overrides[center.key]
|
|
then
|
|
return G.PROFILES[G.SETTINGS.profile].cry_gameset_overrides[center.key]
|
|
end
|
|
return gameset
|
|
end
|
|
-- set_ability accounts for gamesets
|
|
function Card:get_gameset(center)
|
|
return cry_get_gameset(self, center)
|
|
end
|
|
local csa = Card.set_ability
|
|
function Card:set_ability(center, y, z)
|
|
if not center.config then
|
|
center.config = {} --crashproofing
|
|
end
|
|
csa(self, center, y, z)
|
|
if center.gameset_config and center.gameset_config[self:get_gameset(center)] then
|
|
for k, v in pairs(center.gameset_config[self:get_gameset(center)]) do
|
|
if k ~= "disabled" and k ~= "center" then
|
|
if k == "cost" then
|
|
self.base_cost = v
|
|
else
|
|
self.ability[k] = v
|
|
end
|
|
end
|
|
end
|
|
if center.gameset_config[self:get_gameset(center)].disabled then
|
|
self.cry_disabled = true
|
|
end
|
|
if center.gameset_config[self:get_gameset(center)].center and not self.gameset_select then
|
|
for k, v in pairs(center.gameset_config[self:get_gameset(center)].center) do
|
|
center[k] = v
|
|
self[k] = v
|
|
if k == "rarity" then
|
|
center:set_rarity(v)
|
|
else
|
|
self.config.center[k] = v
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
--open gameset config UI when clicking on a card in the Cryptid collection
|
|
--disable this functionality for Jen's Almanac
|
|
if not Jen then
|
|
local ccl = Card.click
|
|
function Card:click()
|
|
ccl(self)
|
|
if G.your_collection then
|
|
for k, v in pairs(G.your_collection) do
|
|
if self.area == v and G.ACTIVE_MOD_UI and G.ACTIVE_MOD_UI.id == "Cryptid" then
|
|
if not self.config.center or self.config.center and self.config.center.set == "Default" then
|
|
--make a fake center
|
|
local old_force_gameset = self.config.center and self.config.center.force_gameset
|
|
if self.seal then
|
|
self.config.center = SMODS.Seal.obj_table[self.seal]
|
|
self.config.center.set = "Seal"
|
|
end
|
|
for k, v in pairs(SMODS.Stickers) do
|
|
if self.ability[k] then
|
|
self.config.center = SMODS.Sticker.obj_table[k]
|
|
self.config.center.set = "Sticker"
|
|
end
|
|
end
|
|
if self.config.center then
|
|
self.config.center.force_gameset = old_force_gameset
|
|
end
|
|
end
|
|
if self.gameset_select then
|
|
Card.cry_set_gameset(self, self.config.center, self.config.center.force_gameset)
|
|
cry_update_obj_registry()
|
|
end
|
|
cry_gameset_config_UI(self.config.center)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- gameset config UI
|
|
function cry_gameset_config_UI(center)
|
|
if not center then
|
|
center = G.viewedContentSet
|
|
end
|
|
G.SETTINGS.paused = true
|
|
G.your_collection = {}
|
|
G.your_collection[1] = CardArea(
|
|
G.ROOM.T.x + 0.2 * G.ROOM.T.w / 2,
|
|
G.ROOM.T.h,
|
|
5.3 * G.CARD_W,
|
|
1.03 * G.CARD_H,
|
|
{ card_limit = 5, type = "title", highlight_limit = 0, collection = true }
|
|
)
|
|
local deck_tables = {
|
|
n = G.UIT.R,
|
|
config = { align = "cm", padding = 0, no_fill = true },
|
|
nodes = {
|
|
{ n = G.UIT.O, config = { object = G.your_collection[1] } },
|
|
},
|
|
}
|
|
|
|
local gamesets = { "disabled", "modest", "mainline", "madness" }
|
|
if center.extra_gamesets then
|
|
for i = 1, #center.extra_gamesets do
|
|
gamesets[#gamesets + 1] = center.extra_gamesets[i]
|
|
end
|
|
end
|
|
if center.set == "Content Set" then
|
|
gamesets = { "disabled", G.PROFILES[G.SETTINGS.profile].cry_gameset }
|
|
end
|
|
for i = 1, #gamesets do
|
|
if
|
|
not (
|
|
center.gameset_config
|
|
and center.gameset_config[gamesets[i]]
|
|
and center.gameset_config[gamesets[i]].disabled
|
|
)
|
|
then
|
|
local _center = cry_deep_copy(center)
|
|
_center.force_gameset = gamesets[i]
|
|
local card = create_generic_card(_center)
|
|
card.gameset_select = true
|
|
G.your_collection[1]:emplace(card)
|
|
--[[if not is_back then
|
|
local card = Card(
|
|
G.your_collection[1].T.x + G.your_collection[1].T.w / 2,
|
|
G.your_collection[1].T.y,
|
|
G.CARD_W,
|
|
G.CARD_H,
|
|
G.P_CARDS.empty,
|
|
_center
|
|
)
|
|
card:start_materialize()
|
|
card.gameset_select = true
|
|
G.your_collection[1]:emplace(card)
|
|
else
|
|
local fake_center = {
|
|
set = "Back",
|
|
force_gameset = gamesets[i],
|
|
pos = center.pos,
|
|
atlas = center.atlas,
|
|
key = center.key,
|
|
config = {}
|
|
}
|
|
local card = Card(G.ROOM.T.x + 0.2*G.ROOM.T.w/2,G.ROOM.T.h, G.CARD_W, G.CARD_H, G.P_CARDS.empty, fake_center)
|
|
card:start_materialize()
|
|
card.gameset_select = true
|
|
G.your_collection[1]:emplace(card)
|
|
end--]]
|
|
end
|
|
end
|
|
|
|
INIT_COLLECTION_CARD_ALERTS()
|
|
local args = {
|
|
infotip = localize("cry_gameset_explanation"),
|
|
back_func = G.cry_prev_collec,
|
|
snap_back = true,
|
|
contents = {
|
|
{
|
|
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 },
|
|
},
|
|
},
|
|
}
|
|
if center.set == "Content Set" then
|
|
G.viewedContentSet = center
|
|
args.back2 = true
|
|
args.back2_func = "your_collection_current_set"
|
|
args.back2_label = localize("cry_view_set_contents")
|
|
args.back2_colour = G.C.CRY_SELECTED
|
|
end
|
|
local t = create_UIBox_generic_options(args)
|
|
G.FUNCS.overlay_menu({
|
|
definition = t,
|
|
})
|
|
end
|
|
|
|
function G.FUNCS.cry_gameset_config_UI()
|
|
G.cry_prev_collec = "your_collection_content_sets"
|
|
cry_gameset_config_UI()
|
|
end
|
|
|
|
local collection_shtuff = {
|
|
"blinds",
|
|
"jokers",
|
|
|
|
-- consumables don't work
|
|
-- idk what smods is doing with consumable collection stuff, anyone know what the buttons are doing?
|
|
"tarots",
|
|
"planets",
|
|
"spectrals",
|
|
"codes",
|
|
|
|
"vouchers",
|
|
"enhancements",
|
|
"decks",
|
|
"editions",
|
|
"tags",
|
|
"seals",
|
|
"boosters",
|
|
"stickers",
|
|
"content_sets",
|
|
}
|
|
|
|
-- sure this is cool and all but it doesn't keep page yet so it's pretty useless
|
|
-- would need to regex patch that
|
|
|
|
for i, v in ipairs(collection_shtuff) do
|
|
local ref = G.FUNCS["your_collection_" .. v]
|
|
G.FUNCS["your_collection_" .. v] = function(e)
|
|
G.cry_prev_collec = "your_collection_" .. v
|
|
ref(e)
|
|
end
|
|
end
|
|
G.cry_prev_collec = "your_collection_jokers"
|
|
|
|
-- change the rarity sticker's color for gameset selection on an item
|
|
local gtc = get_type_colour
|
|
function get_type_colour(center, card)
|
|
local color = gtc(center, card)
|
|
if center.set == "Back" or center.set == "Tag" or center.set == "Blind" then
|
|
color = G.C.CRY_SELECTED
|
|
end
|
|
if card.gameset_select then
|
|
if center.force_gameset == "modest" then
|
|
color = G.C.GREEN
|
|
elseif center.force_gameset == "mainline" then
|
|
color = G.C.RED
|
|
elseif center.force_gameset == "madness" then
|
|
color = G.C.CRY_EXOTIC
|
|
elseif center.force_gameset ~= "disabled" then
|
|
color = G.C.CRY_ASCENDANT
|
|
end
|
|
end
|
|
if
|
|
cry_get_gameset(card, center) == "disabled"
|
|
or (center.cry_disabled and (not card.gameset_select or center.cry_disabled.type ~= "manual"))
|
|
then
|
|
color = mix_colours(G.C.RED, G.C.GREY, 0.7)
|
|
end
|
|
return color
|
|
end
|
|
|
|
function Card:cry_set_gameset(center, gameset)
|
|
if
|
|
G.PROFILES[G.SETTINGS.profile].cry_gameset == gameset
|
|
and not G.PROFILES[G.SETTINGS.profile].cry_gameset_overrides
|
|
then
|
|
return
|
|
end
|
|
if not G.PROFILES[G.SETTINGS.profile].cry_gameset_overrides then
|
|
G.PROFILES[G.SETTINGS.profile].cry_gameset_overrides = {}
|
|
end
|
|
G.PROFILES[G.SETTINGS.profile].cry_gameset_overrides[center.key] = gameset
|
|
if G.PROFILES[G.SETTINGS.profile].cry_gameset == gameset then
|
|
G.PROFILES[G.SETTINGS.profile].cry_gameset_overrides[center.key] = nil
|
|
end
|
|
local empty = true
|
|
for _, _ in pairs(G.PROFILES[G.SETTINGS.profile].cry_gameset_overrides) do
|
|
empty = false
|
|
break
|
|
end
|
|
if empty then
|
|
G.PROFILES[G.SETTINGS.profile].cry_gameset_overrides = nil
|
|
end
|
|
G:save_progress()
|
|
end
|
|
|
|
function G.FUNCS.reset_gameset_config()
|
|
G.PROFILES[G.SETTINGS.profile].cry_gameset_overrides = nil
|
|
cry_update_obj_registry()
|
|
G:save_progress()
|
|
end
|
|
|
|
function cry_card_enabled(key, iter)
|
|
if not iter then
|
|
iter = 0
|
|
end --iter is used to prevent infinite loops from freezing on startup
|
|
if iter > 10 then
|
|
print("Warning: Circular dependency with " .. key)
|
|
return true
|
|
end
|
|
local card = cry_get_center(key)
|
|
if
|
|
not card
|
|
or cry_get_gameset(card) == "disabled"
|
|
or card.gameset_config
|
|
and card.gameset_config[cry_get_gameset(card)]
|
|
and card.gameset_config[cry_get_gameset(card)].disabled
|
|
then
|
|
return { type = "manual" }
|
|
end
|
|
if card.dependencies then
|
|
if card.dependencies.items then
|
|
for i = 1, #card.dependencies.items do
|
|
if cry_card_enabled(card.dependencies.items[i], iter + 1) ~= true then
|
|
return { type = "card_dependency", key = card.dependencies.items[i] }
|
|
end
|
|
end
|
|
end
|
|
if card.dependencies.mods then
|
|
for i = 1, #card.dependencies.mods do
|
|
if not (SMODS.Mods[card.dependencies.mods[i]] or {}).can_load then
|
|
return { type = "mod_dependency", key = card.dependencies.mods[i] }
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if card.conflicts then
|
|
if card.conflicts.mods then
|
|
for i = 1, #card.conflicts.mods do
|
|
if (SMODS.Mods[card.conflicts.mods[i]] or {}).can_load then
|
|
return { type = "mod_conflict", key = card.conflicts.mods[i] }
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
function cry_get_center(key, m)
|
|
if not m then
|
|
-- check for non game objects
|
|
if SMODS.Seals.obj_table and SMODS.Seals.obj_table[key] then
|
|
return SMODS.Seals.obj_table[key]
|
|
end
|
|
if SMODS.Stickers.obj_table and SMODS.Stickers.obj_table[key] then
|
|
return SMODS.Stickers.obj_table[key]
|
|
end
|
|
m = SMODS.GameObject
|
|
if m.subclasses then
|
|
for k, v in pairs(m.subclasses) do
|
|
local c = cry_get_center(key, v)
|
|
if c then
|
|
return c
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return m.obj_table and m.obj_table[key]
|
|
end
|
|
|
|
------------------------------
|
|
---- CARD ENABLING SYSTEM ----
|
|
------------------------------
|
|
|
|
SMODS.GameObject._disable = function(self, reason)
|
|
if not self.cry_disabled then
|
|
self.cry_disabled = reason or { type = "manual" } --used to display more information that can be used later
|
|
end
|
|
end
|
|
SMODS.GameObject.enable = function(self)
|
|
if self.cry_disabled then
|
|
self.cry_disabled = nil
|
|
end
|
|
end
|
|
|
|
-- Note: For custom pools, these only support Center.pools, not ObjectType.cards
|
|
-- That could cause issues with mod compat in the future
|
|
-- Potential improvement: automatic pool detection from gamesets?
|
|
SMODS.Center._disable = function(self, reason)
|
|
if not self.cry_disabled then
|
|
self.cry_disabled = reason or { type = "manual" } --used to display more information that can be used later
|
|
SMODS.remove_pool(G.P_CENTER_POOLS[self.set], self.key)
|
|
for k, v in pairs(self.pools or {}) do
|
|
SMODS.ObjectTypes[k]:delete_card(self)
|
|
end
|
|
G.P_CENTERS[self.key] = nil
|
|
end
|
|
end
|
|
SMODS.Center.enable = function(self)
|
|
if self.cry_disabled then
|
|
self.cry_disabled = nil
|
|
SMODS.insert_pool(G.P_CENTER_POOLS[self.set], self)
|
|
G.P_CENTERS[self.key] = self
|
|
for k, v in pairs(self.pools or {}) do
|
|
SMODS.ObjectTypes[k]:inject_card(self)
|
|
end
|
|
end
|
|
end
|
|
SMODS.Joker.enable = function(self)
|
|
if self.cry_disabled then
|
|
SMODS.Center.enable(self)
|
|
SMODS.insert_pool(G.P_JOKER_RARITY_POOLS[self.rarity], self)
|
|
local vanilla_rarities = { ["Common"] = 1, ["Uncommon"] = 2, ["Rare"] = 3, ["Legendary"] = 4 }
|
|
if vanilla_rarities[self.rarity] then
|
|
SMODS.insert_pool(G.P_JOKER_RARITY_POOLS[vanilla_rarities[self.rarity]], self)
|
|
end
|
|
end
|
|
end
|
|
SMODS.Joker._disable = function(self, reason)
|
|
if not self.cry_disabled then
|
|
SMODS.Center._disable(self, reason)
|
|
SMODS.remove_pool(G.P_JOKER_RARITY_POOLS[self.rarity], self.key)
|
|
local vanilla_rarities = { ["Common"] = 1, ["Uncommon"] = 2, ["Rare"] = 3, ["Legendary"] = 4 }
|
|
if vanilla_rarities[self.rarity] then
|
|
SMODS.remove_pool(G.P_JOKER_RARITY_POOLS[vanilla_rarities[self.rarity]], self.key)
|
|
end
|
|
end
|
|
end
|
|
SMODS.Joker.set_rarity = function(self, rarity)
|
|
SMODS.remove_pool(G.P_JOKER_RARITY_POOLS[self.rarity], self.key)
|
|
self.rarity = rarity
|
|
SMODS.insert_pool(G.P_JOKER_RARITY_POOLS[self.rarity], self)
|
|
local vanilla_rarities = { ["Common"] = 1, ["Uncommon"] = 2, ["Rare"] = 3, ["Legendary"] = 4 }
|
|
if vanilla_rarities[self.rarity] then
|
|
SMODS.insert_pool(G.P_JOKER_RARITY_POOLS[vanilla_rarities[self.rarity]], self)
|
|
end
|
|
end
|
|
|
|
SMODS.Consumable.enable = function(self)
|
|
if self.cry_disabled then
|
|
SMODS.Center.enable(self)
|
|
SMODS.insert_pool(G.P_CENTER_POOLS["Consumeables"], self)
|
|
end
|
|
end
|
|
SMODS.Consumable._disable = function(self, reason)
|
|
if not self.cry_disabled then
|
|
SMODS.Center._disable(self, reason)
|
|
SMODS.remove_pool(G.P_CENTER_POOLS["Consumeables"], self.key)
|
|
end
|
|
end
|
|
|
|
SMODS.Tag._disable = function(self, reason)
|
|
if not self.cry_disabled then
|
|
self.cry_disabled = reason or { type = "manual" } --used to display more information that can be used later
|
|
SMODS.remove_pool(G.P_CENTER_POOLS[self.set], self.key)
|
|
G.P_TAGS[self.key] = nil
|
|
end
|
|
end
|
|
SMODS.Tag.enable = function(self)
|
|
if self.cry_disabled then
|
|
self.cry_disabled = nil
|
|
SMODS.insert_pool(G.P_CENTER_POOLS[self.set], self)
|
|
G.P_TAGS[self.key] = self
|
|
end
|
|
end
|
|
|
|
SMODS.Blind._disable = function(self, reason)
|
|
if not self.cry_disabled then
|
|
self.cry_disabled = reason or { type = "manual" } --used to display more information that can be used later
|
|
G.P_BLINDS[self.key] = nil
|
|
end
|
|
end
|
|
SMODS.Blind.enable = function(self)
|
|
if self.cry_disabled then
|
|
self.cry_disabled = nil
|
|
G.P_BLINDS[self.key] = self
|
|
end
|
|
end
|
|
|
|
--Removing seals from the center table causes issues
|
|
SMODS.Seal._disable = function(self, reason)
|
|
if not self.cry_disabled then
|
|
self.cry_disabled = reason or { type = "manual" } --used to display more information that can be used later
|
|
SMODS.remove_pool(G.P_CENTER_POOLS[self.set], self.key)
|
|
end
|
|
end
|
|
SMODS.Seal.enable = function(self)
|
|
if self.cry_disabled then
|
|
self.cry_disabled = nil
|
|
SMODS.insert_pool(G.P_CENTER_POOLS[self.set], self)
|
|
end
|
|
end
|
|
|
|
--Removing editions from the center table causes issues, so instead we make them unable to spawn naturally
|
|
SMODS.Edition._disable = function(self, reason)
|
|
if not self.cry_disabled then
|
|
self.cry_disabled = reason or { type = "manual" } --used to display more information that can be used later
|
|
SMODS.remove_pool(G.P_CENTER_POOLS[self.set], self.key)
|
|
self.cry_get_weight = self.get_weight
|
|
self.get_weight = function()
|
|
return 0
|
|
end
|
|
end
|
|
end
|
|
SMODS.Edition.enable = function(self)
|
|
if self.cry_disabled then
|
|
self.cry_disabled = nil
|
|
SMODS.insert_pool(G.P_CENTER_POOLS[self.set], self)
|
|
self.get_weight = self.cry_get_weight
|
|
self.cry_get_weight = nil
|
|
end
|
|
end
|
|
|
|
function cry_update_obj_registry(m, force_enable)
|
|
if not m then
|
|
m = SMODS.GameObject
|
|
if m.subclasses then
|
|
for k, v in pairs(m.subclasses) do
|
|
cry_update_obj_registry(v, force_enable)
|
|
end
|
|
end
|
|
end
|
|
if m.obj_table then
|
|
for k, v in pairs(m.obj_table) do
|
|
if v.mod and v.mod.id == "Cryptid" then
|
|
local en = force_enable or cry_card_enabled(k)
|
|
if en == true then
|
|
if v.cry_disabled then
|
|
v:enable()
|
|
end
|
|
else
|
|
if not v.cry_disabled then
|
|
v:_disable(en)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
function cry_index_items(func, m)
|
|
if not m then
|
|
m = SMODS.GameObject
|
|
if m.subclasses then
|
|
for k, v in pairs(m.subclasses) do
|
|
cry_index_items(func, v)
|
|
end
|
|
end
|
|
end
|
|
if m.obj_table then
|
|
for k, v in pairs(m.obj_table) do
|
|
if v.mod and v.mod.id == "Cryptid" then
|
|
func(v)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
local init_item_prototypes_ref = Game.init_item_prototypes
|
|
function Game:init_item_prototypes()
|
|
cry_update_obj_registry(nil, true) --force enable, to prevent issues with profile reloading
|
|
init_item_prototypes_ref(self)
|
|
cry_update_obj_registry()
|
|
end
|
|
|
|
------------------------
|
|
----- CONTENT SETS -----
|
|
------------------------
|
|
|
|
-- Content sets are used to group cards together in the settings menu, to bulk enable/disable things
|
|
-- These include CSL content sets, as well as others which are categorical (nostalgic items, epic jokers, etc.)
|
|
-- Because of this, they are referred to as Thematic Sets in-game
|
|
|
|
SMODS.ContentSet = SMODS.Center:extend({
|
|
set = "Content Set",
|
|
pos = { x = 0, y = 0 },
|
|
config = {},
|
|
class_prefix = "set",
|
|
required_params = {
|
|
"key",
|
|
},
|
|
inject = function(self)
|
|
if not G.P_CENTER_POOLS[self.set] then
|
|
G.P_CENTER_POOLS[self.set] = {}
|
|
end
|
|
SMODS.Center.inject(self)
|
|
if not self.cry_order then
|
|
self.cry_order = 0
|
|
end
|
|
end,
|
|
})
|
|
G.P_CENTER_POOLS["Content Set"] = {}
|
|
-- For now, I made larger sets appear earlier. This can be tweaked later...
|
|
SMODS.ContentSet({
|
|
key = "m",
|
|
atlas = "atlasepic",
|
|
pos = { x = 3, y = 1 }, --m
|
|
cry_order = -22,
|
|
})
|
|
SMODS.ContentSet({
|
|
key = "epic",
|
|
atlas = "atlasepic",
|
|
pos = { x = 2, y = 1 }, --Canvas
|
|
cry_order = -32,
|
|
})
|
|
SMODS.ContentSet({
|
|
key = "code",
|
|
atlas = "code",
|
|
pos = { x = 0, y = 0 }, --://CRASH
|
|
cry_order = -39,
|
|
})
|
|
SMODS.ContentSet({
|
|
key = "exotic",
|
|
atlas = "atlasexotic",
|
|
pos = { x = 0, y = 1 }, --Iterum
|
|
soul_pos = { x = 1, y = 1, extra = { x = 2, y = 1 } },
|
|
cry_order = -20,
|
|
})
|
|
SMODS.ContentSet({
|
|
key = "blind",
|
|
atlas = "blinds",
|
|
pos = { x = 0, y = 4 }, --The Joke
|
|
cry_blind = true,
|
|
cry_order = -26,
|
|
})
|
|
SMODS.ContentSet({
|
|
key = "deck",
|
|
atlas = "atlasdeck",
|
|
pos = { x = 4, y = 5 }, --Critical Deck
|
|
cry_order = -23,
|
|
})
|
|
SMODS.ContentSet({
|
|
key = "spooky",
|
|
atlas = "atlasspooky",
|
|
pos = { x = 1, y = 0 }, --Chocolate Dice
|
|
cry_order = -14,
|
|
})
|
|
SMODS.ContentSet({
|
|
key = "cursed",
|
|
atlas = "atlasspooky",
|
|
pos = { x = 3, y = 0 }, --Ghost
|
|
cry_order = -6,
|
|
})
|
|
SMODS.ContentSet({
|
|
key = "timer",
|
|
atlas = "blinds",
|
|
pos = { x = 0, y = 1 }, --The Clock
|
|
cry_blind = true,
|
|
cry_order = -2,
|
|
})
|
|
SMODS.ContentSet({
|
|
key = "misc",
|
|
atlas = "cry_misc",
|
|
pos = { x = 2, y = 0 }, --Echo Card
|
|
cry_order = -22,
|
|
})
|
|
SMODS.ContentSet({
|
|
key = "misc_joker",
|
|
atlas = "atlasone",
|
|
pos = { x = 2, y = 3 }, --Nice
|
|
cry_order = -111,
|
|
})
|
|
SMODS.ContentSet({
|
|
key = "planet",
|
|
atlas = "atlasnotjokers",
|
|
pos = { x = 4, y = 2 }, --Planet.lua
|
|
cry_order = -8,
|
|
})
|
|
SMODS.ContentSet({
|
|
key = "spectral",
|
|
atlas = "atlasnotjokers",
|
|
pos = { x = 1, y = 1 }, --Replica
|
|
cry_order = -12,
|
|
})
|
|
SMODS.ContentSet({
|
|
key = "tag",
|
|
atlas = "tag_cry",
|
|
pos = { x = 0, y = 2 }, --Cat Tag
|
|
cry_tag = true,
|
|
cry_order = -30,
|
|
})
|
|
SMODS.ContentSet({
|
|
key = "tier3",
|
|
atlas = "atlasvoucher",
|
|
pos = { x = 5, y = 2 }, --Asteroglyph
|
|
cry_order = -18,
|
|
})
|
|
SMODS.ContentSet({
|
|
key = "voucher",
|
|
atlas = "atlasvoucher",
|
|
pos = { x = 1, y = 2 }, --Tag Printer
|
|
cry_order = -15,
|
|
})
|
|
SMODS.ContentSet({
|
|
key = "poker_hand_stuff",
|
|
atlas = "atlasthree",
|
|
pos = { x = 7, y = 1 }, --The Fuck!? (Clusterfuck's XMult Joker)
|
|
cry_order = -16,
|
|
})
|
|
|
|
-- these are mostly copy/paste from vanilla code
|
|
G.FUNCS.your_collection_content_sets = function(e)
|
|
G.cry_prev_collec = "your_collection_content_sets"
|
|
G.SETTINGS.paused = true
|
|
G.FUNCS.overlay_menu({
|
|
definition = create_UIBox_your_collection_content_sets(),
|
|
})
|
|
end
|
|
|
|
G.FUNCS.your_collection_current_set = function(e)
|
|
G.cry_prev_collec = "your_collection_current_set"
|
|
G.SETTINGS.paused = true
|
|
G.FUNCS.overlay_menu({
|
|
definition = create_UIBox_your_collection_current_set(),
|
|
})
|
|
end
|
|
|
|
function create_UIBox_your_collection_content_sets()
|
|
local deck_tables = {}
|
|
|
|
G.your_collection = {}
|
|
for j = 1, 3 do
|
|
G.your_collection[j] = CardArea(
|
|
G.ROOM.T.x + 0.2 * G.ROOM.T.w / 2,
|
|
G.ROOM.T.h,
|
|
5 * G.CARD_W,
|
|
0.95 * G.CARD_H,
|
|
{ card_limit = 5, type = "title", highlight_limit = 0, collection = true }
|
|
)
|
|
table.insert(deck_tables, {
|
|
n = G.UIT.R,
|
|
config = { align = "cm", padding = 0.07, no_fill = true },
|
|
nodes = {
|
|
{ n = G.UIT.O, config = { object = G.your_collection[j] } },
|
|
},
|
|
})
|
|
end
|
|
|
|
local joker_pool = {}
|
|
for k, v in pairs(SMODS.ContentSet.obj_table) do
|
|
if v.set == "Content Set" then
|
|
table.insert(joker_pool, v)
|
|
end
|
|
end
|
|
table.sort(joker_pool, function(a, b)
|
|
return a.cry_order < b.cry_order
|
|
end)
|
|
local joker_options = {}
|
|
for i = 1, math.ceil(#joker_pool / (5 * #G.your_collection)) do
|
|
table.insert(
|
|
joker_options,
|
|
localize("k_page")
|
|
.. " "
|
|
.. tostring(i)
|
|
.. "/"
|
|
.. tostring(math.ceil(#joker_pool / (5 * #G.your_collection)))
|
|
)
|
|
end
|
|
|
|
for i = 1, 5 do
|
|
for j = 1, #G.your_collection do
|
|
local center = joker_pool[i + (j - 1) * 5]
|
|
if not center then
|
|
break
|
|
end
|
|
local card = create_generic_card(
|
|
center,
|
|
G.your_collection[j].T.x + G.your_collection[j].T.w / 2,
|
|
G.your_collection[j].T.y
|
|
)
|
|
G.your_collection[j]:emplace(card)
|
|
end
|
|
end
|
|
|
|
INIT_COLLECTION_CARD_ALERTS()
|
|
|
|
local t = create_UIBox_generic_options({
|
|
back_func = G.ACTIVE_MOD_UI and "openModUI_" .. G.ACTIVE_MOD_UI.id or "your_collection",
|
|
contents = {
|
|
{ n = G.UIT.R, config = { align = "cm", r = 0.1, colour = G.C.BLACK, emboss = 0.05 }, nodes = deck_tables },
|
|
{
|
|
n = G.UIT.R,
|
|
config = { align = "cm" },
|
|
nodes = {
|
|
create_option_cycle({
|
|
options = joker_options,
|
|
w = 4.5,
|
|
cycle_shoulders = true,
|
|
opt_callback = "your_collection_content_set_page",
|
|
current_option = 1,
|
|
colour = G.C.RED,
|
|
no_pips = true,
|
|
focus_args = { snap_to = true, nav = "wide" },
|
|
}),
|
|
},
|
|
},
|
|
},
|
|
})
|
|
return t
|
|
end
|
|
|
|
function create_UIBox_your_collection_current_set()
|
|
local deck_tables = {}
|
|
|
|
G.your_collection = {}
|
|
for j = 1, 3 do
|
|
G.your_collection[j] = CardArea(
|
|
G.ROOM.T.x + 0.2 * G.ROOM.T.w / 2,
|
|
G.ROOM.T.h,
|
|
5 * G.CARD_W,
|
|
0.95 * G.CARD_H,
|
|
{ card_limit = 5, type = "title", highlight_limit = 0, collection = true }
|
|
)
|
|
table.insert(deck_tables, {
|
|
n = G.UIT.R,
|
|
config = { align = "cm", padding = 0.07, no_fill = true },
|
|
nodes = {
|
|
{ n = G.UIT.O, config = { object = G.your_collection[j] } },
|
|
},
|
|
})
|
|
end
|
|
|
|
joker_pool = {}
|
|
local function is_in_set(card)
|
|
if card.dependencies and card.dependencies.items then
|
|
for i = 1, #card.dependencies.items do
|
|
if card.dependencies.items[i] == G.viewedContentSet.key then
|
|
joker_pool[#joker_pool + 1] = card
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
cry_index_items(is_in_set)
|
|
table.sort(joker_pool, function(a, b)
|
|
return a.cry_order < b.cry_order
|
|
end)
|
|
local joker_options = {}
|
|
for i = 1, math.ceil(#joker_pool / (5 * #G.your_collection)) do
|
|
table.insert(
|
|
joker_options,
|
|
localize("k_page")
|
|
.. " "
|
|
.. tostring(i)
|
|
.. "/"
|
|
.. tostring(math.ceil(#joker_pool / (5 * #G.your_collection)))
|
|
)
|
|
end
|
|
|
|
for i = 1, 5 do
|
|
for j = 1, #G.your_collection do
|
|
local center = joker_pool[i + (j - 1) * 5]
|
|
if not center then
|
|
break
|
|
end
|
|
local card = create_generic_card(
|
|
center,
|
|
G.your_collection[j].T.x + G.your_collection[j].T.w / 2,
|
|
G.your_collection[j].T.y
|
|
)
|
|
G.your_collection[j]:emplace(card)
|
|
end
|
|
end
|
|
|
|
INIT_COLLECTION_CARD_ALERTS()
|
|
|
|
local t = create_UIBox_generic_options({
|
|
back_func = "cry_gameset_config_UI",
|
|
contents = {
|
|
{ n = G.UIT.R, config = { align = "cm", r = 0.1, colour = G.C.BLACK, emboss = 0.05 }, nodes = deck_tables },
|
|
{
|
|
n = G.UIT.R,
|
|
config = { align = "cm" },
|
|
nodes = {
|
|
create_option_cycle({
|
|
options = joker_options,
|
|
w = 4.5,
|
|
cycle_shoulders = true,
|
|
opt_callback = "your_collection_current_set_page",
|
|
current_option = 1,
|
|
colour = G.C.RED,
|
|
no_pips = true,
|
|
focus_args = { snap_to = true, nav = "wide" },
|
|
}),
|
|
},
|
|
},
|
|
},
|
|
})
|
|
return t
|
|
end
|
|
|
|
G.FUNCS.your_collection_content_set_page = function(args)
|
|
if not args or not args.cycle_config then
|
|
return
|
|
end
|
|
for j = 1, #G.your_collection do
|
|
for i = #G.your_collection[j].cards, 1, -1 do
|
|
local c = G.your_collection[j]:remove_card(G.your_collection[j].cards[i])
|
|
c:remove()
|
|
c = nil
|
|
end
|
|
end
|
|
local joker_pool = {}
|
|
for k, v in pairs(SMODS.ContentSet.obj_table) do
|
|
if v.set == "Content Set" then
|
|
table.insert(joker_pool, v)
|
|
end
|
|
end
|
|
table.sort(joker_pool, function(a, b)
|
|
return a.cry_order < b.cry_order
|
|
end)
|
|
for i = 1, 5 do
|
|
for j = 1, #G.your_collection do
|
|
local center =
|
|
joker_pool[i + (j - 1) * 5 + (5 * #G.your_collection * (args.cycle_config.current_option - 1))]
|
|
if not center then
|
|
break
|
|
end
|
|
local card = create_generic_card(
|
|
center,
|
|
G.your_collection[j].T.x + G.your_collection[j].T.w / 2,
|
|
G.your_collection[j].T.y
|
|
)
|
|
G.your_collection[j]:emplace(card)
|
|
end
|
|
end
|
|
INIT_COLLECTION_CARD_ALERTS()
|
|
end
|
|
G.FUNCS.your_collection_current_set_page = function(args)
|
|
if not args or not args.cycle_config then
|
|
return
|
|
end
|
|
for j = 1, #G.your_collection do
|
|
for i = #G.your_collection[j].cards, 1, -1 do
|
|
local c = G.your_collection[j]:remove_card(G.your_collection[j].cards[i])
|
|
c:remove()
|
|
c = nil
|
|
end
|
|
end
|
|
joker_pool = {}
|
|
local function is_in_set(card)
|
|
if card.dependencies and card.dependencies.items then
|
|
for i = 1, #card.dependencies.items do
|
|
if card.dependencies.items[i] == G.viewedContentSet.key then
|
|
joker_pool[#joker_pool + 1] = card
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
cry_index_items(is_in_set)
|
|
table.sort(joker_pool, function(a, b)
|
|
return a.cry_order < b.cry_order
|
|
end)
|
|
for i = 1, 5 do
|
|
for j = 1, #G.your_collection do
|
|
local center =
|
|
joker_pool[i + (j - 1) * 5 + (5 * #G.your_collection * (args.cycle_config.current_option - 1))]
|
|
if not center then
|
|
break
|
|
end
|
|
local card = create_generic_card(
|
|
center,
|
|
G.your_collection[j].T.x + G.your_collection[j].T.w / 2,
|
|
G.your_collection[j].T.y
|
|
)
|
|
G.your_collection[j]:emplace(card)
|
|
end
|
|
end
|
|
INIT_COLLECTION_CARD_ALERTS()
|
|
end
|
|
|
|
------------------------------
|
|
---- GENERIC COLLECTIONS -----
|
|
------------------------------
|
|
|
|
function create_generic_card(center, x, y)
|
|
--todo: make gameset stickers play nicely with resized sprites
|
|
local is_blind = center.set == "Blind" or center.cry_blind
|
|
local is_tag = center.set == "Tag" or center.cry_tag
|
|
local card = Card(
|
|
x or G.ROOM.T.x + 0.2 * G.ROOM.T.w / 2,
|
|
y or G.ROOM.T.h,
|
|
is_blind and 0.7 * G.CARD_W or is_tag and 0.42 * G.CARD_W or G.CARD_W,
|
|
is_blind and 0.7 * G.CARD_W or is_tag and 0.42 * G.CARD_W or G.CARD_H,
|
|
nil,
|
|
center.set ~= "Seal" and center.set ~= "Sticker" and center or G.P_CENTERS.c_base
|
|
)
|
|
--todo: make this work when the edition is disabled (although it's a good failsafe that it doesn't?)
|
|
if center.set == "Edition" then
|
|
card:set_edition(center.key, true, true)
|
|
end
|
|
if safe_get(center, "config", "cry_antimatter") then
|
|
card:set_edition("e_negative", true, true)
|
|
return card
|
|
end
|
|
if safe_get(center, "config", "cry_force_edition") then
|
|
card:set_edition({ [center.config.cry_force_edition] = true }, true, true)
|
|
end
|
|
if center.set == "Seal" then
|
|
card:set_seal(center.key, true, true)
|
|
card.config.center = cry_deep_copy(card.config.center)
|
|
card.config.center.force_gameset = center.force_gameset
|
|
card.config.center.key = center.key
|
|
end
|
|
if safe_get(center, "config", "cry_force_seal") then
|
|
card:set_seal(center.config.cry_force_seal, true, true)
|
|
end
|
|
if center.set == "Sticker" then
|
|
center:apply(card, true)
|
|
card.config.center = cry_deep_copy(card.config.center)
|
|
card.config.center.force_gameset = center.force_gameset
|
|
card.config.center.key = center.key
|
|
end
|
|
if safe_get(center, "config", "cry_force_sticker") then
|
|
SMODS.Stickers[center.config.cry_force_sticker]:apply(card, true)
|
|
end
|
|
return card
|
|
end
|
|
|
|
-- Hooks for all collection types
|
|
local smcp = SMODS.collection_pool
|
|
SMODS.collection_pool = function(m)
|
|
if G.ACTIVE_MOD_UI and G.ACTIVE_MOD_UI.id == "Cryptid" then
|
|
-- use SMODS pools instead of vanilla pools, so disabled cards appear
|
|
if m[1] and m[1].set and m[1].set == "Seal" then
|
|
m = {}
|
|
for k, v in pairs(SMODS.Seal.obj_table) do
|
|
if v.mod and v.mod.id == "Cryptid" then
|
|
table.insert(m, v)
|
|
end
|
|
end
|
|
elseif m[1] and m[1].set and m[1].set == "Sticker" then
|
|
m = {}
|
|
for k, v in pairs(SMODS.Sticker.obj_table) do
|
|
if v.mod and v.mod.id == "Cryptid" then
|
|
table.insert(m, v)
|
|
end
|
|
end
|
|
elseif m[1] and m[1].set and G.P_CENTER_POOLS[m[1].set] == m then
|
|
local set = m[1].set
|
|
m = {}
|
|
for k, v in pairs(SMODS.Center.obj_table) do
|
|
if v.set == set and v.mod and v.mod.id == "Cryptid" then
|
|
table.insert(m, v)
|
|
end
|
|
end
|
|
end
|
|
-- Fix blind issues
|
|
for k, v in pairs(m) do
|
|
if v.set == "Blind" and v.mod and v.mod.id == "Cryptid" then
|
|
v.config = {}
|
|
end
|
|
end
|
|
table.sort(m, function(a, b)
|
|
return a.cry_order < b.cry_order
|
|
end)
|
|
end
|
|
return smcp(m)
|
|
end
|
|
|
|
-- Make Cryptid show all collection boxes (kinda silly)
|
|
local mct = modsCollectionTally
|
|
function modsCollectionTally(pool, set)
|
|
local t = mct(pool, set)
|
|
if G.ACTIVE_MOD_UI and G.ACTIVE_MOD_UI.id == "Cryptid" then
|
|
local obj_tally = { tally = 0, of = 0 }
|
|
--infer pool
|
|
local _set = set or safe_get(pool, 1, "set")
|
|
--check for general consumables
|
|
local consumable = false
|
|
if _set and safe_get(pool, 1, "consumeable") then
|
|
for i = 1, #pool do
|
|
if safe_get(pool, i, "set") ~= _set then
|
|
consumable = true
|
|
break
|
|
end
|
|
end
|
|
end
|
|
if _set then
|
|
if _set == "Seal" then
|
|
pool = SMODS.Seal.obj_table
|
|
set = _set
|
|
elseif G.P_CENTER_POOLS[_set] then
|
|
pool = SMODS.Center.obj_table
|
|
set = _set
|
|
end
|
|
end
|
|
for _, v in pairs(pool) do
|
|
if v.mod and G.ACTIVE_MOD_UI.id == v.mod.id and not v.no_collection then
|
|
if consumable then
|
|
if safe_get(v, "consumeable") then
|
|
obj_tally.of = obj_tally.of + 1
|
|
if cry_card_enabled(v.key) == true then
|
|
obj_tally.tally = obj_tally.tally + 1
|
|
end
|
|
end
|
|
elseif set then
|
|
if v.set and v.set == set then
|
|
obj_tally.of = obj_tally.of + 1
|
|
if cry_card_enabled(v.key) == true then
|
|
obj_tally.tally = obj_tally.tally + 1
|
|
end
|
|
end
|
|
else
|
|
obj_tally.of = obj_tally.of + 1
|
|
if cry_card_enabled(v.key) == true then
|
|
obj_tally.tally = obj_tally.tally + 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return obj_tally
|
|
end
|
|
return t
|
|
end
|
|
|
|
-- Make non-center collections show all cards as centers
|
|
local uibk = create_UIBox_your_collection_decks
|
|
function create_UIBox_your_collection_decks()
|
|
if G.ACTIVE_MOD_UI and G.ACTIVE_MOD_UI.id == "Cryptid" then
|
|
local generic_collection_pool = {}
|
|
for k, v in pairs(SMODS.Center.obj_table) do
|
|
if v.set == "Back" and v.mod and v.mod.id == "Cryptid" then
|
|
table.insert(generic_collection_pool, v)
|
|
end
|
|
end
|
|
return SMODS.card_collection_UIBox(generic_collection_pool, { 5, 5, 5 }, {
|
|
modify_card = function(card, center, i, j)
|
|
if center.config.cry_antimatter then
|
|
card:set_edition("e_negative", true, true)
|
|
return card
|
|
end
|
|
if center.config.cry_force_edition then
|
|
card:set_edition({ [center.config.cry_force_edition] = true }, true, true)
|
|
end
|
|
if center.config.cry_force_seal then
|
|
card:set_seal(center.config.cry_force_seal, true, true)
|
|
end
|
|
if center.config.cry_force_sticker then
|
|
SMODS.Stickers[center.config.cry_force_sticker]:apply(card, true)
|
|
end
|
|
end,
|
|
})
|
|
else
|
|
return uibk()
|
|
end
|
|
end
|
|
|
|
local uitag = create_UIBox_your_collection_tags
|
|
function create_UIBox_your_collection_tags()
|
|
if G.ACTIVE_MOD_UI and G.ACTIVE_MOD_UI.id == "Cryptid" then
|
|
local generic_collection_pool = {}
|
|
for k, v in pairs(SMODS.Tag.obj_table) do
|
|
if v.set == "Tag" and v.mod and v.mod.id == "Cryptid" then
|
|
table.insert(generic_collection_pool, v)
|
|
end
|
|
end
|
|
return SMODS.card_collection_UIBox(generic_collection_pool, { 6, 6, 6, 6 }, {
|
|
card_scale = 0.42,
|
|
h_mod = 0.3,
|
|
w_mod = 0.55,
|
|
area_type = "title_2",
|
|
modify_card = function(card, center, i, j)
|
|
card.T.h = card.T.w
|
|
end,
|
|
})
|
|
else
|
|
return uitag()
|
|
end
|
|
end
|
|
|
|
local uibl = create_UIBox_your_collection_blinds
|
|
function create_UIBox_your_collection_blinds()
|
|
if G.ACTIVE_MOD_UI and G.ACTIVE_MOD_UI.id == "Cryptid" then
|
|
local generic_collection_pool = {}
|
|
for k, v in pairs(SMODS.Blind.obj_table) do
|
|
if v.set == "Blind" and v.mod and v.mod.id == "Cryptid" then
|
|
table.insert(generic_collection_pool, v)
|
|
end
|
|
end
|
|
return SMODS.card_collection_UIBox(generic_collection_pool, { 5, 5, 5, 5, 5 }, {
|
|
card_scale = 0.70,
|
|
h_mod = 0.45,
|
|
w_mod = 0.70,
|
|
area_type = "title_2",
|
|
modify_card = function(card, center, i, j)
|
|
card.T.h = card.T.w
|
|
end,
|
|
})
|
|
else
|
|
return uibl()
|
|
end
|
|
end
|
|
|
|
local uisl = create_UIBox_your_collection_seals
|
|
function create_UIBox_your_collection_seals()
|
|
if G.ACTIVE_MOD_UI and G.ACTIVE_MOD_UI.id == "Cryptid" then
|
|
return SMODS.card_collection_UIBox(G.P_CENTER_POOLS.Seal, { 5, 5 }, {
|
|
snap_back = true,
|
|
infotip = localize("ml_edition_seal_enhancement_explanation"),
|
|
hide_single_page = true,
|
|
collapse_single_page = true,
|
|
center = "c_base",
|
|
h_mod = 1.03,
|
|
modify_card = function(card, center)
|
|
card:set_seal(center.key, true)
|
|
-- Make disabled UI appear
|
|
card.config.center = cry_deep_copy(card.config.center)
|
|
card.config.center.key = center.key
|
|
end,
|
|
})
|
|
else
|
|
return uisl()
|
|
end
|
|
end
|
|
|
|
local uist = create_UIBox_your_collection_stickers
|
|
function create_UIBox_your_collection_stickers()
|
|
if G.ACTIVE_MOD_UI and G.ACTIVE_MOD_UI.id == "Cryptid" then
|
|
return SMODS.card_collection_UIBox(SMODS.Stickers, { 5, 5 }, {
|
|
snap_back = true,
|
|
hide_single_page = true,
|
|
collapse_single_page = true,
|
|
center = "c_base",
|
|
h_mod = 1.03,
|
|
back_func = "your_collection_other_gameobjects",
|
|
modify_card = function(card, center)
|
|
card.ignore_pinned = true
|
|
center:apply(card, true)
|
|
-- Make disabled UI appear
|
|
card.config.center = cry_deep_copy(card.config.center)
|
|
card.config.center.key = center.key
|
|
end,
|
|
})
|
|
else
|
|
return uist()
|
|
end
|
|
end
|
|
|
|
--hacky fix to get animated atlases visible for centers
|
|
local smai = SMODS.Atlas.inject
|
|
SMODS.Atlas.inject = function(self)
|
|
smai(self)
|
|
if self.atlas_table ~= "ASSET_ATLAS" then
|
|
G.ASSET_ATLAS[self.key_noloc or self.key] = G[self.atlas_table][self.key_noloc or self.key]
|
|
end
|
|
end
|