RE:CORD
REC_Books

Stracture

Welcome to REC_Books documentation.
Added
Updated
config/sh_config.lua

---@class REC_Books.Shared.Config
local config = {}

---[[
---    Debug Mode
---]]
---@type boolean
config.debugMode = true

---[[
---     Items (define them under the same names in ox_inventory items.lua, see _install/)
---     blank turns into a new book when it is used, book carries metadata.bookUid
---]]
config.items = {
    blank = "rec_book_blank",
    book  = "rec_book",
}

---[[
---     DO NOT TOUCH once a book exists (schema v1)
---     Logical size of a surface in page units (pu). board is used by cover-front,
---     cover-back and inside-front, page by every body page and inside-back.
---     Changing a value moves or cuts what players already placed.
---]]
config.surface = {
    board = { width = 1000, height = 1320, },
    page  = { width = 1000, height = 1300, },
}

---[[
---     Book
---     Leaves are sheets of paper, one leaf is two pages (initial 8 = 16 pages).
---     coverColor / pageColor / paper / font are what a new book starts with,
---     paper and font must be keys of config.papers and config.fonts.
---]]
config.book = {
    initialLeaves  = 8,
    minLeaves      = 1,
    maxLeaves      = 24,
    titleMaxLength = 40,
    coverColor     = "#5b3a29",
    pageColor      = "#fbf6ea",
    paper          = "lined",
    font           = "sans",
}

---[[
---     Fonts
---     family is a CSS font-family. src is optional: put a .woff2 under content/fonts/
---     and point at it to ship a font (every client downloads it on connect), the NUI
---     registers it under the first name of family.
---]]
config.fonts = {
    { key = "sans",       label = "Gothic",      family = "\"Yu Gothic\", \"Meiryo\", sans-serif", },
    { key = "serif",      label = "Mincho",      family = "\"Yu Mincho\", \"MS Mincho\", serif", },
    { key = "textbook",   label = "Textbook",    family = "\"UD Digi Kyokasho NP-R\", \"UD デジタル 教科書体 NP-R\", \"Yu Mincho\", serif", },
    { key = "hand",       label = "Handwriting", family = "\"REC Books Caveat\", \"Segoe Print\", \"Yu Gothic\", cursive", src = "content/fonts/caveat.woff2", },
    { key = "display",    label = "Display",     family = "\"REC Books Playfair\", Georgia, \"Yu Mincho\", serif", src = "content/fonts/playfair-display.woff2", },
    { key = "typewriter", label = "Typewriter",  family = "\"REC Books Courier Prime\", \"Courier New\", \"Yu Gothic\", monospace", src = "content/fonts/courier-prime.woff2", },
}

---[[
---     Stickers
---     scan adds every .svg / .png / .webp found under content/stickers/<category>/
---     (key = "<category>/<file>", label = file name, not tintable).
---     items are always listed and override the label / tintable of a scanned file.
---     tintable stickers can be recoloured by the player (single colour artwork only).
---]]
config.stickers = {
    scan = true,
    categories = {
        { key = "basic",  label = "Basic", },
        { key = "deco",   label = "Deco", },
        { key = "nature", label = "Nature", },
        { key = "life",   label = "Life", },
    },
    items = {
        { key = "basic/heart.svg",           label = "Heart",         tintable = true, },
        { key = "basic/star.svg",            label = "Star",          tintable = true, },
        { key = "basic/flower.svg",          label = "Flower",        tintable = false, },
        { key = "basic/arrow.svg",           label = "Arrow",         tintable = true, },
        { key = "basic/sparkle.svg",         label = "Sparkle",       tintable = true, },
        { key = "basic/check.svg",           label = "Check",         tintable = true, },
        { key = "basic/cross.svg",           label = "Cross",         tintable = true, },
        { key = "basic/circle.svg",          label = "Circle",        tintable = true, },
        { key = "basic/exclaim.svg",         label = "Exclamation",   tintable = true, },
        { key = "basic/question.svg",        label = "Question",      tintable = true, },
        { key = "basic/note.svg",            label = "Music",         tintable = true, },
        { key = "basic/crown.svg",           label = "Crown",         tintable = true, },
        { key = "basic/bolt.svg",            label = "Bolt",          tintable = true, },
        { key = "basic/drop.svg",            label = "Drop",          tintable = true, },
        { key = "basic/paw.svg",             label = "Paw",           tintable = true, },
        { key = "basic/bubble.svg",          label = "Bubble",        tintable = true, },
        { key = "basic/scribble.svg",        label = "Scribble",      tintable = true, },
        { key = "basic/flourish.svg",        label = "Flourish",      tintable = true, },
        { key = "basic/corner.svg",          label = "Corner",        tintable = true, },

        { key = "deco/tape-mint.svg",        label = "Tape (mint)",   tintable = false, },
        { key = "deco/tape-dots.svg",        label = "Tape (dots)",   tintable = false, },
        { key = "deco/tape-kraft.svg",       label = "Tape (kraft)",  tintable = false, },
        { key = "deco/clip.svg",             label = "Clip",          tintable = false, },
        { key = "deco/pin.svg",              label = "Pin",           tintable = false, },
        { key = "deco/ribbon.svg",           label = "Ribbon",        tintable = false, },
        { key = "deco/tag.svg",              label = "Tag",           tintable = false, },
        { key = "deco/postmark.svg",         label = "Postmark",      tintable = false, },
        { key = "deco/ticket.svg",           label = "Ticket",        tintable = false, },
        { key = "deco/sticky.svg",           label = "Sticky note",   tintable = false, },
        { key = "deco/bookmark.svg",         label = "Bookmark",      tintable = false, },
        { key = "deco/seal.svg",             label = "Wax seal",      tintable = false, },

        { key = "nature/sun.svg",            label = "Sun",           tintable = false, },
        { key = "nature/moon.svg",           label = "Moon",          tintable = false, },
        { key = "nature/cloud.svg",          label = "Cloud",         tintable = false, },
        { key = "nature/rain.svg",           label = "Rain",          tintable = false, },
        { key = "nature/rainbow.svg",        label = "Rainbow",       tintable = false, },
        { key = "nature/tulip.svg",          label = "Tulip",         tintable = false, },
        { key = "nature/sakura.svg",         label = "Sakura",        tintable = false, },
        { key = "nature/leaf.svg",           label = "Leaf",          tintable = false, },
        { key = "nature/clover.svg",         label = "Clover",        tintable = false, },
        { key = "nature/cactus.svg",         label = "Cactus",        tintable = false, },

        { key = "life/coffee.svg",           label = "Coffee",        tintable = false, },
        { key = "life/cake.svg",             label = "Cake",          tintable = false, },
        { key = "life/camera.svg",           label = "Camera",        tintable = false, },
        { key = "life/car.svg",              label = "Car",           tintable = false, },
        { key = "life/burger.svg",           label = "Burger",        tintable = false, },
        { key = "life/gift.svg",             label = "Gift",          tintable = false, },
        { key = "life/balloon.svg",          label = "Balloon",       tintable = false, },
        { key = "life/mappin.svg",           label = "Map pin",       tintable = false, },
        { key = "life/phone.svg",            label = "Phone",         tintable = false, },
        { key = "life/cash.svg",             label = "Cash",          tintable = false, },
    },
}

---[[
---     Papers (the pattern behind a page)
---     src is a square SVG tile under content/papers/ laid spacing x spacing pu from the
---     top left. margin is the left / right margin in pu, only papers with a margin make
---     the write tool snap to their lines.
---]]
config.papers = {
    { key = "plain",    label = "Plain", },
    { key = "lined",    label = "Lined",    src = "content/papers/lined.svg",    spacing = 56,  margin = 80, },
    { key = "grid",     label = "Grid",     src = "content/papers/grid.svg",     spacing = 50,  margin = 60, },
    { key = "dotted",   label = "Dotted",   src = "content/papers/dotted.svg",   spacing = 50,  margin = 60, },
    { key = "cloth",    label = "Cloth",    src = "content/papers/cloth.svg",    spacing = 24, },
    { key = "endpaper", label = "Endpaper", src = "content/papers/endpaper.svg", spacing = 240, },
}

---[[
---     Colours offered first in the colour picker (#rrggbb, lowercase)
---]]
---@type string[]
config.palette = { "#1f1f1f", "#ffffff", "#c0392b", "#e67e22", "#f1c40f", "#27ae60", "#2980b9", "#8e44ad", }

---[[
---     Showing a book to the players around
---     radius in metres, maxTargets players at most (closest first),
---     ticketSeconds how long an offer can be accepted.
---]]
config.share = {
    radius        = 3.0,
    maxTargets    = 4,
    ticketSeconds = 300,
}

---[[
---     NUI
---     autosaveDelay    ms after the last change before a surface is saved
---     autosaveMaxWait  ms at most between two saves while the player keeps editing
---     historyLimit     undo steps
---     snapThreshold    snap distance in screen px
---     motion           book animation preset: "normal" | "journey" | "old" | "default"
---     sound            page sound preset: "normal" | "journey" | "old"
---     audioVolume      multiplier on the volume of the sound preset, 0 mutes
---]]
config.ui = {
    autosaveDelay   = 1500,
    autosaveMaxWait = 8000,
    historyLimit    = 200,
    snapThreshold   = 6,
    motion          = "normal",
    sound           = "normal",
    audioVolume     = 1.0,
}

---[[
---     In game while a book is open
---     anim: the reading pose (closeBlend is the blend out speed when the book closes)
---     prop: the book in the hand
---     camera: a scripted camera placed relative to the player (offset / lookAt in metres
---     along the player axes, duration is the ease in / out in ms), enabled = false keeps
---     the gameplay camera
---]]
config.anim = {
    dict       = "cellphone@",
    name       = "cellphone_text_read_base",
    flag       = 49,
    blendIn    = 3.0,
    blendOut   = 3.0,
    closeBlend = 1.0,
}

config.prop = {
    model    = "prop_novel_01",
    bone     = 6286,
    offset   = vector3(0.15, 0.03, -0.065),
    rotation = vector3(0.0, 180.0, 90.0),
}

config.camera = {
    enabled  = true,
    fov      = 34.0,
    duration = 450,
    offset   = vector3(0.0, 0.95, 0.62),
    lookAt   = vector3(0.0, 0.42, 0.28),
}

return config
©2026 RE:CORD Development Group. All rights reserved.