Create box function

Really useful for making boxes 👍

目前為 2023-07-27 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Create box function
// @namespace    create_box_owot
// @version      1
// @description  Really useful for making boxes 👍
// @author       e_g.
// @match        https://ourworldoftext.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=ourworldoftext.com
// @grant        none
// ==/UserScript==

createBox = function(box){
    //Help
    if(box == "help") return console.log(`Arguments available (insert them inside an object):
    x
    y
    width
    height
    borderSize
    mainColor (0x)
    borderColor (0x)
    textColor (0x)
    textBgColor (0x)
    title
    description
    footer
    titleAlign ("center", "left", "right")
    descAlign ("center", "left", "right")
    footerAlign ("center", "left", "right")
    footer2space (makes the footer 2 spaces horizontally instead of 1, to make a more precise 1:1 space)
    borderCollision (text will stick to the border instead of having 1 space)
    fullActions (set to true to make borderSize extreme values or making a box bigger than 512 characters)

Arguments you should not use because they're not customizable and are important parts from the box creation:
    size
    formattedDesc
    descIndex
    titleFormula
    descFormula
    footerFormula`);
    // Errors and warnings
    if(box.x === undefined) return console.error("X position isn't specified.");
    if(box.y === undefined) return console.error("Y position isn't specified.");
    if(box.width * box.height > 512 && !box.fullActions) return console.error("To make boxes bigger than 512 characters, add the arg fullActions and set it as true.");
    if(box.title.length > box.width - box.borderSize * 4 - !box.borderCollision * 2) return console.error("Title too big" + (box.title.length <= box.width - box.borderSize * 4 ? ", set borderCollision to true so you can use that title." : ""));
    if(box.footer && box.footer.length > box.width - box.borderSize * 4 - !box.borderCollision * 2 + box.footer2space) return console.error("Footer too big");
    if(box.borderSize * 4 >= box.width / 1.5 && !box.fullActions) return console.error("Box's main content is too small. Proceed by adding the arg fullActions to the args and setting it to true.");
    box.size = box.width * box.height + ((box.width - box.borderSize * 4) * (box.height - box.borderSize * 2)) * !!box.borderSize + box.title.length + box.description.length + (box.footer ? box.footer.length : 0);
    if(state.worldModel.char_rate.reduce((x, y) => x * y / 1e3) * 24 < box.size) return console.error("Your rate limit is too low to draw the box");
    if(state.worldModel.char_rate.reduce((x, y) => x * y / 1e3) * 2 < box.size) console.warn("The box might be messed up because your rate limit is too low for the box's size.");
    if(box.x % 1){
        box.x = Math.floor(box.x);
        console.warn(`The x value is a decimal value. It will be rounded to ${box.x}.`);
    };
    if(box.y % 1){
        box.y = Math.floor(box.y);
        console.warn(`The y value is a decimal value. It will be rounded to ${box.y}.`);
    };
    if(box.width % 1){
        box.width = Math.floor(box.width);
        console.warn(`The width size is a decimal value. It will be rounded to ${box.width}.`);
    };
    if(box.height % 1){
        box.height = Math.floor(box.height);
        console.warn(`The height size is a decimal value. It will be rounded to ${box.height}.`);
    };
    if(box.borderSize % 1){
        box.borderSize = Math.round(box.borderSize);
        console.warn(`The border size is a decimal value. It will be rounded to ${box.borderSize}.`);
    };
    if(box.borderSize * 4 >= box.width / 2) console.warn("Consider reducing border's size to add space for the main content!");
    if(box.footer2space && box.borderCollision) console.warn("Both footer2space and borderCollision are activated, this may cause conflict for the box.");
    // Avoid glitching when a word is too big for the box
    if(!box.description.endsWith(" ") && box.description.split(" ").at(-1).length > box.width - box.borderSize * 4 - 2) box.description += " ";
    // Rest of description's separating setup + see if it's too big for the box
    if(box.description.length > box.width - box.borderSize * 4 - !box.borderCollision * 2 && box.description.split(" ").length > 1){
        box.formattedDesc = [...box.description.match(RegExp(`.{0,${box.width - box.borderSize * 4 - !box.borderCollision * 2}} |.{${box.width - box.borderSize * 4 - !box.borderCollision * 2}}`, "g")), box.description.split(" ").at(-1)];
        if(box.formattedDesc.slice(-2).join("").length <= box.width - box.borderSize * 4 - !box.borderCollision * 2) box.formattedDesc = [...box.formattedDesc.slice(0, box.formattedDesc.length - 2), box.formattedDesc.slice(-2).join("")];
        box.formattedDesc = box.formattedDesc.map(x => x.replace(/ +$/, ""));
    }
    else box.formattedDesc = box.description.match(RegExp(`.{0,${box.width - box.borderSize * 4 - !box.borderCollision * 2}}`, "g"));
    box.formattedDesc = box.formattedDesc.filter(x => x != "");
    if(box.formattedDesc.length == 1 && box.formattedDesc[0] == "") box.formattedDesc = [];
    if(box.formattedDesc.length > box.height - box.borderSize * 2 - 2 - !box.borderCollision * 2 - !!box.footer * 2) return console.error("Description too long for the size of this box. Try setting borderCollision to true, or if that doesn't work, set a bigger size for the box or shorten the description.");
    //Make the box and box's border (reversed order)
    if(box.borderSize) filltoxy(box.x, box.y, box.width, box.height, "█", box.borderColor);
    filltoxy(box.x + box.borderSize * 2, box.y + box.borderSize, box.width - box.borderSize * 4, box.height - box.borderSize * 2, "█", box.mainColor);
    //Alignment formula of title and draw it
    if(!box.titleAlign) box.titleAlign = "center";
    if(box.titleAlign == "center"){
        box.titleFormula = Math.ceil(box.x + box.width / 2 - box.title.length / 2);
    }
    else if(box.titleAlign == "left"){
        box.titleFormula = Math.ceil(box.x + box.borderSize * 2 + !box.borderCollision);
    }
    else if(box.titleAlign == "right"){
        box.titleFormula = Math.ceil(box.x + (box.width - box.borderSize * 2 - !box.borderCollision - box.title.length));
    }
    else{
        console.warn("titleAlign had an invalid align, and was automatically assigned to center (the valid ones are: center, left, right)");
        box.titleAlign = "center";
        box.titleFormula = Math.ceil(box.x + box.width / 2 - box.title.length / 2);
    };
    texttoxy(box.titleFormula, box.y + box.borderSize + !box.borderCollision, box.title, box.textColor, box.textBgColor);
    //Alignment formula of description and draw it
    if(!box.descAlign) box.descAlign = "center";
    if(box.descAlign == "center"){
        box.descFormula = function(formattedDesc, descIndex){
            return Math.ceil(box.x + box.width / 2 - formattedDesc[descIndex - box.borderSize - 3].length / 2);
        };
    }
    else if(box.descAlign == "left"){
        box.descFormula = function(){
            return Math.ceil(box.x + box.borderSize * 2 + !box.borderCollision);
        };
    }
    else if(box.descAlign == "right"){
        box.descFormula = function(formattedDesc, descIndex){
            return Math.ceil(box.x + (box.width - box.borderSize * 2 - !box.borderCollision - formattedDesc[descIndex - box.borderSize - 3].length));
        };
    }
    else{
        console.warn("descAlign had an invalid align, and was automatically assigned to center (the valid ones are: center, left, right)");
        box.descAlign = "center";
        box.descFormula = function(formattedDesc, descIndex){
            return Math.ceil(box.x + box.width / 2 - formattedDesc[descIndex - box.borderSize - 3].length / 2);
        };
    };
    for(box.descIndex = box.borderSize + 3; box.descIndex < box.formattedDesc.length + box.borderSize + 3; box.descIndex++){
        texttoxy(box.descFormula(box.formattedDesc, box.descIndex), box.y + box.descIndex - !!box.borderCollision, box.formattedDesc[box.descIndex - box.borderSize - 3], box.textColor, box.textBgColor);
    };
    //Alignment formula of footer and draw it IF there's any
    if(!box.footer) return;
    if(!box.footerAlign) box.footerAlign = "right";
    if(box.footerAlign == "center"){
        box.footerFormula = Math.ceil(box.x + box.width / 2 - box.footer.length / 2);
    }
    else if(box.footerAlign == "left"){
        box.footerFormula = Math.ceil(box.x + box.borderSize * 2 + !box.borderCollision + !!box.footer2space);
    }
    else if(box.footerAlign == "right"){
        box.footerFormula = Math.ceil(box.x + (box.width - box.borderSize * 2 - !box.borderCollision - !!box.footer2space - box.footer.length));
    }
    else{
        console.warn("footerAlign had an invalid align, and was automatically assigned to right (the valid ones are: center, left, right)");
        box.footerAlign = "right";
        box.footerFormula = Math.ceil(box.x + (box.width - box.borderSize * 2 - !box.borderCollision - !!box.footer2space - box.footer.length));
    };
    texttoxy(box.footerFormula, box.y + box.height - box.borderSize - 1 - !box.borderCollision, box.footer, box.textColor, box.textBgColor);
}