A shitload of stuff

This commit is contained in:
SPT-dev 2023-03-02 21:10:18 -05:00
parent afa7002710
commit ab9989ffff
60 changed files with 1535 additions and 695 deletions

View File

@ -1,107 +1,6 @@
@charset "UTF-8";
@import url("https://fonts.googleapis.com/css2?family=Open+Sans&family=Source+Sans+Pro:wght@400;700&display=swap");
h1,
.headline-1,
.heading-1 {
font-size: 6rem;
font-weight: 300;
letter-spacing: -0.015625em;
line-height: 6rem;
}
h2,
.headline-2,
.heading-2 {
font-size: 3.75rem;
font-weight: 300;
letter-spacing: -0.0083333333em;
line-height: 3.75rem;
}
h3,
.headline-3,
.heading-3 {
font-size: 3rem;
font-weight: 400;
letter-spacing: normal;
line-height: 3.125rem;
}
h4,
.headline-4,
.heading-4 {
font-size: 2.125rem;
font-weight: 400;
letter-spacing: 0.0073529412em;
line-height: 2.5rem;
}
h5,
.headline-5,
.heading-5 {
font-size: 1.5rem;
font-weight: 400;
letter-spacing: normal;
line-height: 2rem;
}
h6,
.headline-6,
.heading-6 {
font-size: 1.25rem;
font-weight: 500;
letter-spacing: 0.125em;
line-height: 2rem;
}
.subtitle-1 {
font-size: 1rem;
font-weight: 400;
letter-spacing: 0.009375em;
line-height: 1.75rem;
}
.subtitle-2 {
font-size: 0.875rem;
font-weight: 500;
letter-spacing: 0.0071428571em;
line-height: 1.375rem;
}
.body-1 {
font-size: 1rem;
font-weight: 400;
letter-spacing: 0.03125em;
line-height: 1.5rem;
}
.body-2 {
font-size: 0.875rem;
font-weight: 400;
letter-spacing: 0.0178571429em;
line-height: 1.25rem;
}
.button {
font-size: 0.875rem;
font-weight: 500;
letter-spacing: 0.0892857143em;
line-height: 2.25rem;
}
.caption {
font-size: 0.75rem;
font-weight: 400;
letter-spacing: 0.0333333333em;
line-height: 1.25rem;
}
.overline {
font-size: 0.75rem;
font-weight: 500;
letter-spacing: 0.1666666667em;
line-height: 2rem;
}
@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap");
aki-button,
*[aki-button],
*.aki-button {
@ -124,7 +23,7 @@ aki-button:hover:not(:active),
aki-button:active,
*[aki-button]:active,
*.aki-button:active {
background: #121212;
background: #080808;
box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12);
color: #fff;
}
@ -132,7 +31,7 @@ aki-button:active,
aki-card,
*.aki-card,
*[aki-card] {
background: #121212;
background: #080808;
box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12);
border-radius: 0.125rem;
color: #fff;
@ -177,7 +76,7 @@ aki-toolbar,
*[aki-toolbar],
*.aki-toolbar {
align-items: center;
background-color: #121212;
background-color: #080808;
box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12);
color: #fff;
display: flex;
@ -186,9 +85,8 @@ aki-toolbar,
justify-content: flex-start;
max-height: 5.5rem;
min-width: 20rem;
text-transform: uppercase;
width: 100%;
z-index: 1;
z-index: 2;
}
aki-toolbar a,
*[aki-toolbar] a,
@ -205,7 +103,7 @@ aki-toolbar nav,
aki-toolbar nav a,
*[aki-toolbar] nav a,
*.aki-toolbar nav a {
border-bottom: 0.25rem solid #121212;
border-bottom: 0.25rem solid #080808;
cursor: pointer;
padding: 1rem;
letter-spacing: 0.0178571429em;
@ -223,31 +121,63 @@ aki-toolbar nav a[active],
border-bottom: 0.25rem solid #ffc107;
}
.text1 {
font-family: "Open Sans", sans-serif;
font-weight: 400;
}
.text2 {
font-family: "Source Sans Pro", sans-serif;
font-weight: 700;
}
html {
font-family: "Source Sans Pro", sans-serif;
font-size: 16px;
font-size: 100%;
}
body {
display: flex;
flex-direction: column;
font-family: "Roboto", sans-serif;
font-weight: 400;
height: 100vh;
line-height: 1.75;
margin: 0;
padding: 0;
position: absolute;
width: 100vw;
}
p {
margin-bottom: 1rem;
}
h1,
h2,
h3,
h4,
h5 {
margin: 3rem 0 1.38rem;
font-family: "Roboto", sans-serif;
font-weight: 400;
line-height: 1.3;
}
h1 {
margin-top: 0;
font-size: 3.052rem;
}
h2 {
font-size: 2.441rem;
}
h3 {
font-size: 1.953rem;
}
h4 {
font-size: 1.563rem;
}
h5 {
font-size: 1.25rem;
}
small,
.text_small {
font-size: 0.8rem;
}
header .left,
header .center,
header .right {
@ -264,17 +194,10 @@ header .left .logo {
}
header .left .title {
font-size: 1.75rem;
font-weight: 700;
letter-spacing: 0.03125em;
margin-left: 1rem;
}
header .left .title span:last-child {
margin-left: 0.5rem;
}
@media (max-width: 64em) {
header .left .title span:first-child {
display: none;
}
}
@media (max-width: 48em) {
header .left .title {
margin-left: 0;
@ -283,108 +206,113 @@ header .left .title span:last-child {
header .right {
flex: 1 1 auto;
justify-content: flex-end;
text-transform: uppercase;
/*
@media (max-width: 64em) {
&.dropdown {
align-items: center;
cursor: pointer;
display: flex;
justify-content: center;
min-width: 4rem;
float: left;
overflow: hidden;
&:hover .dropdown-content {
// display: block;
background: $primary;
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);
display: flex;
flex-direction: column;
padding: 1rem;
right: 0;
top: 5.5rem;
}
.dropdown-button {
display: initial;
}
.dropdown-content {
display: none;
position: absolute;
z-index: 1;
}
}
}
*/
}
header .right .dropdown-button {
display: none;
}
@media (max-width: 64em) {
header .right.dropdown {
align-items: center;
cursor: pointer;
display: flex;
justify-content: center;
min-width: 4rem;
float: left;
overflow: hidden;
}
header .right.dropdown:hover .dropdown-content {
background: #121212;
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);
display: flex;
flex-direction: column;
padding: 1rem;
right: 0;
top: 5.5rem;
}
header .right.dropdown .dropdown-button {
display: initial;
}
header .right.dropdown .dropdown-content {
display: none;
position: absolute;
z-index: 1;
}
}
main {
display: flex;
flex-direction: row;
height: 100%;
position: relative;
overflow: auto;
width: 100%;
}
main aside {
background-color: #121212;
box-shadow: 0 8px 10px -5px rgba(0, 0, 0, 0.2), 0 16px 24px 2px rgba(0, 0, 0, 0.14), 0 6px 30px 5px rgba(0, 0, 0, 0.12);
background: #080808;
box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12);
color: #fff;
max-width: 20rem;
overflow-y: auto;
width: 20rem;
width: 100%;
z-index: 1;
}
main aside .subheader,
main aside ul {
padding: 1rem;
main aside nav {
margin: 1rem 0;
}
main aside .subheader {
font-family: "Source Sans Pro";
font-size: 1rem;
font-weight: 700;
main aside nav a,
main aside nav div {
display: block;
padding: 0.25rem 0.5rem 0.25rem 1rem;
width: calc(100% - 1.5rem);
}
main aside ul {
font-family: "Open Sans";
font-size: 0.875rem;
font-weight: 400;
main aside nav ul {
list-style: none;
margin: 0;
padding-left: 1rem;
}
main aside ul li {
cursor: pointer;
padding: 0.25rem 0;
}
main aside ul li a {
main aside nav a {
color: #fff;
text-decoration: none;
}
main aside ul li a:hover {
main aside nav a:hover {
filter: invert(0.15);
}
main aside ul li a[active] {
main aside nav a.active {
color: #ffc107;
}
main #router-outlet {
background: #282828;
main aside nav .node.hide ul {
max-height: 0 !important;
}
main aside nav .node.hide div::after {
transform: rotate(-90deg);
}
main aside nav .node div {
cursor: pointer;
display: flex;
}
main aside nav .node div::after {
content: "🔽";
margin-right: 1rem;
text-align: right;
}
main aside nav .node ul {
overflow: hidden;
}
main article {
background: #1f1f1f;
color: #fff;
height: calc(100% - 2rem);
position: relative;
overflow: auto;
padding: 1rem 2rem;
width: calc(100% - 4rem);
padding: 1rem 27.1% 1rem 10.4%;
width: 62.5%;
}
footer {
bottom: 0;
color: rgba(255, 255, 255, 0.25);
font-size: 0.625rem;
left: 0;
padding: 0.5rem 1.5rem;
position: absolute;
width: calc(100% - 1.5rem * 2);
}
@media (max-width: 48em) {
footer {
display: none;
}
main article img {
max-width: 100%;
}
a {
@ -392,168 +320,146 @@ a {
text-decoration: none;
}
.doc-typography {
/*
p,
pre ul,
li,
blockquote,
span,
code {
font-size: .875rem;
font-weight: 400;
letter-spacing: .03125em;
line-height: 1.5rem;
}
pre,
code {
background: $code !important;
}
blockquote,
code,
.doc-alert,
.doc-info,
.doc-warning,
.doc-note {
border-radius: $border-radius;
}
blockquote,
code,
pre,
.doc-alert,
.doc-info,
.doc-warning,
.doc-note {
padding: $padding;
}
blockquote,
code,
pre,
li,
.doc-alert,
.doc-info,
.doc-warning,
.doc-note {
margin: $margin;
}
blockquote {
background: $blockquote;
color: $on-blockquote;
}
// for url/links
// span,
a {
color: $accent;
cursor: pointer;
text-decoration: none;
&:hover {
filter: invert(.15);
}
}
img {
max-width: 100%;
}
.doc-alert,
.doc-info,
.doc-warning,
.doc-note {
box-shadow: $elevation-z2;
}
.doc-alert {
background: $alert;
color: $on-alert;
&::before {
content: "Alert";
display: block;
font-weight: 700;
margin: 0 0 .25rem 0;
}
}
.doc-info {
background: $info;
color: $on-info;
&::before {
content: "Info";
display: block;
font-weight: 700;
margin: 0 0 .25rem 0;
}
}
.doc-warning {
background: $warning;
color: $on-warning;
&::before {
content: "Warning";
display: block;
font-weight: 700;
margin: 0 0 .25rem 0;
}
}
.doc-note {
background: $note;
color: $on-note;
&::before {
content: "Note";
display: block;
font-weight: 700;
margin: 0 0 .25rem 0;
}
}
*/
}
.doc-typography table {
text-align: left;
}
.doc-typography h1,
.doc-typography h2,
.doc-typography h3,
.doc-typography h4,
.doc-typography h5,
.doc-typography h6 {
margin: 0;
}
.doc-typography h1 {
font-family: "Source Sans Pro";
font-size: 3rem;
font-weight: 700;
letter-spacing: -0.015625em;
line-height: 6rem;
}
.doc-typography h2 {
font-family: "Source Sans Pro";
font-size: 2.25rem;
font-weight: 700;
letter-spacing: -0.0083333333em;
line-height: 3.75rem;
}
.doc-typography h3 {
font-family: "Source Sans Pro";
font-size: 1.75rem;
font-weight: 700;
letter-spacing: normal;
line-height: 3.125rem;
}
.doc-typography h4 {
font-family: "Source Sans Pro";
font-size: 1.75rem;
font-weight: 500;
letter-spacing: 0.0073529412em;
line-height: 2.5rem;
}
.doc-typography h5 {
font-family: "Source Sans Pro";
font-size: 1.5rem;
font-weight: 500;
letter-spacing: normal;
line-height: 2rem;
}
.doc-typography h6 {
font-family: "Source Sans Pro";
font-size: 1.25rem;
font-weight: 500;
letter-spacing: normal;
line-height: 2rem;
}
.doc-typography p,
.doc-typography pre ul,
.doc-typography li,
.doc-typography blockquote,
.doc-typography span,
.doc-typography code {
font-size: 0.875rem;
font-weight: 400;
letter-spacing: 0.03125em;
line-height: 1.5rem;
}
.doc-typography p,
.doc-typography ul,
.doc-typography li,
.doc-typography blockquote,
.doc-typography span {
font-family: "Open Sans";
}
.doc-typography pre,
.doc-typography code {
background: #101010 !important;
}
.doc-typography blockquote,
.doc-typography code,
.doc-typography .doc-alert,
.doc-typography .doc-info,
.doc-typography .doc-warning,
.doc-typography .doc-note {
border-radius: 0.125rem;
}
.doc-typography blockquote,
.doc-typography code,
.doc-typography pre,
.doc-typography .doc-alert,
.doc-typography .doc-info,
.doc-typography .doc-warning,
.doc-typography .doc-note {
padding: 0.25rem 0.5rem;
}
.doc-typography blockquote,
.doc-typography code,
.doc-typography pre,
.doc-typography li,
.doc-typography .doc-alert,
.doc-typography .doc-info,
.doc-typography .doc-warning,
.doc-typography .doc-note {
margin: 0 0 0.5rem;
}
.doc-typography blockquote {
background: #181818;
color: #ccc;
background: rgba(255, 255, 255, 0.125);
border-radius: 4px;
margin: 0;
padding: 0.5rem 0.7rem;
}
.doc-typography a {
color: #ffc107;
cursor: pointer;
text-decoration: none;
}
.doc-typography a:hover {
filter: invert(0.15);
}
.doc-typography img {
max-width: 100%;
}
.doc-typography .doc-alert,
.doc-typography .doc-info,
.doc-typography .doc-warning,
.doc-typography .doc-note {
box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
}
.doc-typography .doc-alert {
background: #AF1010;
color: #fff;
}
.doc-typography .doc-alert::before {
content: "Alert";
display: block;
font-weight: 700;
margin: 0 0 0.25rem 0;
}
.doc-typography .doc-info {
background: #0D47A1;
color: #fff;
}
.doc-typography .doc-info::before {
content: "Info";
display: block;
font-weight: 700;
margin: 0 0 0.25rem 0;
}
.doc-typography .doc-warning {
background: #ffc107;
color: #000;
}
.doc-typography .doc-warning::before {
content: "Warning";
display: block;
font-weight: 700;
margin: 0 0 0.25rem 0;
}
.doc-typography .doc-note {
background: #999;
color: #080808;
}
.doc-typography .doc-note::before {
content: "Note";
display: block;
font-weight: 700;
margin: 0 0 0.25rem 0;
.doc-typography blockquote p {
margin: 0;
}
/*# sourceMappingURL=style.css.map */

View File

@ -1 +1 @@
{"version":3,"sourceRoot":"","sources":["../scss/utils/theme.scss","../scss/utils/typography.scss","../scss/components/aki-button.scss","../scss/utils/elevation.scss","../scss/components/aki-card.scss","../scss/components/aki-divider.scss","../scss/components/aki-toolbar.scss","../scss/style.scss"],"names":[],"mappings":"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","file":"style.css"}
{"version":3,"sourceRoot":"","sources":["../scss/utils/theme.scss","../scss/style.scss","../scss/components/aki-button.scss","../scss/utils/elevation.scss","../scss/components/aki-card.scss","../scss/components/aki-divider.scss","../scss/components/aki-toolbar.scss"],"names":[],"mappings":"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","file":"style.css"}

View File

@ -0,0 +1,104 @@
{
"routes": [
{
"name": "Demo",
"hidden": false,
"filepath": "demo.md"
},
{
"name": "GETTING STARTED",
"routes": [
{
"name": "About",
"filepath": "getting_started/about.md"
},
{
"name": "Setup",
"filepath": "getting_started/setup.md"
},
{
"name": "F.A.Q.",
"filepath": "getting_started/faq.md"
}
]
},
{
"name": "TUTORIALS",
"type": "section",
"routes": [
{
"name": "Tutorial: Getting OP",
"routes": [
{
"name": "Introduction",
"filepath": "tutorials/tut_0/tut0_0.md"
},
{
"name": "Getting started",
"filepath": "tutorials/tut_0/tut0_1.md"
},
{
"name": "1. Edit character level",
"filepath": "tutorials/tut_0/tut0_2.md"
},
{
"name": "2. Edit skill level",
"filepath": "tutorials/tut_0/tut0_3.md"
},
{
"name": "3. Edit quest status",
"filepath": "tutorials/tut_0/tut0_4.md"
},
{
"name": "4. Edit hideout area status",
"filepath": "tutorials/tut_0/tut0_5.md"
},
{
"name": "5. Add money to stash",
"filepath": "tutorials/tut_0/tut0_6.md"
}
]
},
{
"name": "Tutorial: Being a god with style",
"filepath": "tutorials/tut_1.md"
},
{
"name": "Tutorial: Creating a new weapon",
"routes": [
{
"name": "0. Introduction",
"filepath": "tutorials/tut_2/cw_0.md"
},
{
"name": "1. Creating a new weapon",
"filepath": "tutorials/tut_2/cw_1.md"
},
{
"name": "2. Adding it the to flea market",
"filepath": "tutorials/tut_2/cw_2.md"
},
{
"name": "3. Adding it to a trader",
"filepath": "tutorials/tut_2/cw_3.md"
},
{
"name": "4. Editing a weapon's texture",
"filepath": "tutorials/tut_2/cw_4.md"
}
]
}
]
},
{
"name": "API REFERENCE",
"hidden": false,
"filepath": "api_ref/api.md"
},
{
"name": "API REFERENCE LIST",
"hidden": true,
"routes": []
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 645 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 629 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 615 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 645 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

341
docs/assets/js/docs.js Normal file
View File

@ -0,0 +1,341 @@
/**
* TODO: override the marker.js renderer for urls
* to enable proper anchor support.
*
* Probably just need to check if the text starts
* with a # or not to cover most cases.
*/
class Docs {
/**
* @param {string} defaultView
* @param {string} routesPath
*/
constructor(defaultViewPath, fetchPath = 'content', routesPath = './assets/data/routes.json') {
/** @type {string} */
this.defaultViewPath = defaultViewPath;
/** @type {string} */
this.fetchPath = fetchPath;
/** @type {string} */
this.routesPath = routesPath;
/** @type {Array.<JSON>} */
this.routesData = [];
/** @type {Array.<(Route, RoutingNode)} */
this.routes = [];
/** @type {Route} */
this.currentRoute = undefined;
this.onExec();
}
async onExec() {
// Get routes.
this.routesData = await this.fetchRoutes();
// Generate nav based on routes.
this.generateNav(this.routesData, document.querySelector('aside'));
// Add listener for hash change.
window.addEventListener('hashchange', () => this.handleLocation(window.location));
if (window.location.hash) {
this.handleLocation(window.location);
} else if (typeof this.defaultViewPath !== 'undefined') {
// TODO: Do it.
console.log("Missing Feature !\nShould load the default view");
}
}
/**
* @returns {Array.<JSON>} The array containing the routes.
*/
async fetchRoutes() {
const response = await fetch(this.routesPath);
const json = await response.json();
return json["routes"];
}
/**
* @param {Array.<JSON>} routes
* @param {HTMLElement} target
*/
generateNav(routesData, target) {
/** @type {Array.<RoutingItem>} */
const routes = [];
const nav = document.createElement("nav");
routesData.forEach(routeData => {
if ("routes" in routeData) {
routes.push(new RoutingNode(routeData["name"], routeData["hidden"], routeData["routes"]));
} else {
routes.push(new Route(routeData["name"], routeData["hidden"], routeData["filepath"]));
}
});
routes.forEach(routingItem => {
if (!routingItem.hasOwnProperty("hidden") || !routingItem["hidden"]) {
nav.appendChild(routingItem.buildSelf());
}
});
target.appendChild(nav);
this.routes = routes;
}
/**
* @param {Location} location
*/
handleLocation(location) {
let hashes = location.hash.split('#');
hashes.splice(0, 1);
console.log(hashes);
if (typeof this.currentRoute === "undefined" || this.currentRoute.filepath !== hashes[0]) {
const route = this.findMatchingRoute(hashes[0], this.routes);
this.currentRoute = route;
this.displayRoute(route);
const activeLinks = document.querySelectorAll('a.active');
const newActiveLinks = document.querySelectorAll(`a[href='#${hashes[0]}']`);
if (activeLinks.length > 0) {
activeLinks.forEach(link => link.classList.remove('active'));
}
newActiveLinks.forEach(newLink => newLink.classList.add('active'));
// TODO: update active route in the page's navbar
if (hashes.length > 1) {
this.handleLocation(window.location);
}
} else {
const el = document.querySelector(`#${hashes[1]}`);
el.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
}
/**
* @param {string} filepath The filepath to search.
* @returns {Route} The matching route.
*/
findMatchingRoute(filepath, routes) {
console.log("filepath:", filepath);
let match = undefined;
for (let routingItem of routes) {
// If the routingItem is a route and have what we are looking for.
if (routingItem.hasOwnProperty('filepath') && routingItem['filepath'] === filepath) {
match = routingItem;
break;
}
// Recursive search to go deeper.
for (let v of Object.keys(routingItem)) {
if (typeof routingItem[v] === 'object' && v === 'routes') {
const o = this.findMatchingRoute(filepath, routingItem[v]);
if (o != null) {
match = o;
break;
}
}
}
}
return match;
}
/**
* @param {Route} route The route to load.
*/
async displayRoute(route) {
const content = await route.loadSelf(this.fetchPath);
const contentOutlet = document.querySelector('#router-outlet');
this.removeChildren(contentOutlet);
contentOutlet.innerHTML = marked(content);
Prism.highlightAll(); // edited
}
removeChildren(element) {
let count = element.childNodes.length;
while (count--) {
element.removeChild(element.lastChild);
}
}
}
class RoutingItem {
/**
* @param {string} name
* @param {boolean} hidden
*/
constructor(name, hidden) {
this.name = name;
this.hidden = hidden;
}
buildSelf() {
const element = document.createElement("div");
element.innerText = this.name;
return element;
}
}
class Route extends RoutingItem {
/**
* @param {string} name
* @param {boolean} hidden
* @param {string} filepath
*/
constructor(name, hidden, filepath) {
super(name, hidden);
/** @type {string} */
this.filepath = filepath;
}
/**
* @returns {HTMLAnchorElement} The Route as an HTML link.
*/
buildSelf() {
const element = document.createElement("a");
element.href = `#${this.filepath}`;
element.innerText = this.name;
return element;
}
/**
* @returns {string} The document content to load as a string.
*/
async loadSelf(prefix, suffix) {
if (typeof prefix === 'undefined') {
prefix = '';
} else {
prefix += '/';
}
if (typeof suffix === 'undefined') {
suffix = '';
} else {
suffix += '/';
}
const response = await fetch(`${prefix}${this.filepath}${suffix}`);
const text = await response.text();
return text;
}
}
class RoutingNode extends RoutingItem {
/**
* @param {string} name
* @param {boolean} hidden
* @param {Array.<JSON>} routesData
*/
constructor(name, hidden, routesData) {
super(name, hidden);
/** @type {Array.<JSON>} */
this.routesData = routesData;
/** @type {Array.<(Route,RoutingNode)>} */
this.routes = [];
this.onExec();
}
onExec() {
this.routesData.forEach(routeData => {
if ("routes" in routeData) {
this.routes.push(new RoutingNode(routeData["name"], routeData["hidden"], routeData["routes"]));
} else {
this.routes.push(new Route(routeData["name"], routeData["hidden"], routeData["filepath"]));
}
});
}
/**
* @returns {HTMLUListElement} The RoutingNode as an HTML unordered list.
*/
buildSelf(prefix, suffix) {
if (typeof prefix === 'undefined') {
prefix = '';
} else {
prefix += '/';
}
if (typeof suffix === 'undefined') {
suffix = '';
} else {
suffix += '/';
}
const element = document.createElement('section');
element.classList.add("node","hide");
const heading = document.createElement('div');
heading.innerText = this.name;
heading.addEventListener('click', toggleDisplay);
const list = document.createElement('ul');
// list.classList.add("hide");
this.routes.forEach(entry => {
const childEl = document.createElement('li');
childEl.appendChild(entry.buildSelf());
list.appendChild(childEl);
});
element.appendChild(heading);
element.appendChild(list);
return element;
}
}
// TODO: find them a new home
/**
* @param {Event} event
*/
function toggleDisplay(event) {
const dropdown = event.currentTarget.parentNode;
// const list = dropdown.querySelector('ul');
toggleClass(dropdown, 'hide');
};
/**
* @param {HTMLElement} el
* @param {string} className
*/
function toggleClass(el, className) {
if (el.classList.contains(className)) {
el.classList.remove(className);
} else {
el.classList.add(className);
}
};

View File

@ -12,9 +12,8 @@ aki-toolbar,
justify-content: flex-start;
max-height: 5.5rem;
min-width: 20rem;
text-transform: uppercase;
width: 100%;
z-index: 1;
z-index: 2;
a {
color: $on-primary;

View File

@ -1,37 +1,75 @@
@import './utils/theme.scss';
@import './utils/elevation.scss';
@import './utils/typography.scss';
// @import './utils/typography.scss';
@import './components/aki-button.scss';
@import './components/aki-card.scss';
@import './components/aki-divider.scss';
@import './components/aki-toolbar.scss';
.text1 {
font-family: 'Open Sans', sans-serif;
font-weight: 400;
}
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');
.text2 {
font-family: 'Source Sans Pro', sans-serif;
font-weight: 700;
}
// TODO: Media queries for smaller screens and devices.
html {
font-family: 'Source Sans Pro', sans-serif;
font-size: $base-font-size;
font-size: 100%;
}
body {
display: flex;
flex-direction: column;
font-family: 'Roboto', sans-serif;
font-weight: 400;
height: 100vh;
line-height: 1.75;
margin: 0;
padding: 0;
position: absolute;
width: 100vw;
}
p {
margin-bottom: 1rem;
}
h1,
h2,
h3,
h4,
h5 {
margin: 3rem 0 1.38rem;
font-family: 'Roboto', sans-serif;
font-weight: 400;
line-height: 1.3;
}
h1 {
margin-top: 0;
font-size: 3.052rem;
}
h2 {
font-size: 2.441rem;
}
h3 {
font-size: 1.953rem;
}
h4 {
font-size: 1.563rem;
}
h5 {
font-size: 1.25rem;
}
small,
.text_small {
font-size: 0.8rem;
}
// --------
header {
.left,
@ -53,19 +91,10 @@ header {
.title {
font-size: 1.75rem;
font-weight: 700;
letter-spacing: .03125em;
margin-left: 1rem;
span:last-child {
margin-left: .5rem;
}
@media (max-width: #{$bp-medium}) {
span:first-child {
display: none;
}
}
@media (max-width: #{$bp-small}) {
margin-left: 0;
}
@ -75,11 +104,14 @@ header {
.right {
flex: 1 1 auto;
justify-content: flex-end;
text-transform: uppercase;
.dropdown-button {
display: none;
}
// TODO: Redo header media query
/*
@media (max-width: #{$bp-medium}) {
&.dropdown {
align-items: center;
@ -113,6 +145,7 @@ header {
}
}
}
*/
}
}
@ -120,78 +153,89 @@ main {
display: flex;
flex-direction: row;
height: 100%;
position: relative;
overflow: auto;
width: 100%;
aside {
background-color: $primary;
box-shadow: $elevation-z16;
background: $primary;
box-shadow: $elevation-z4;
color: $on-primary;
max-width: 20rem;
overflow-y: auto;
width: 20rem;
width: 100%;
z-index: 1;
.subheader,
ul {
padding: 1rem;
}
nav {
margin: 1rem 0;
.subheader {
font-family: $font-source-sans-pro;
font-size: 1rem;
font-weight: 700;
}
a,
div {
display: block;
padding: .25rem .5rem .25rem 1rem;
width: calc(100% - 1.5rem);
ul {
font-family: $font-open-sans;
font-size: .875rem;
font-weight: 400;
list-style: none;
margin: 0;
// &:hover {
// background-color: rgba($secondary,.5);
// }
}
li {
cursor: pointer;
padding: .25rem 0;
ul {
list-style: none;
margin: 0;
padding-left: 1rem;
}
a {
color: $on-secondary;
text-decoration: none;
a {
color: $on-secondary;
&:hover {
filter: invert(.15);
&:hover {
filter: invert(.15);
}
&.active {
color: $accent;
}
}
// TODO: Redo list status indicator + animations
.node {
&.hide {
ul {
max-height: 0 !important;
}
&[active] {
color: $accent;
div::after {
transform: rotate(-90deg);
}
}
div {
cursor: pointer;
display: flex;
&::after {
content: "🔽";
margin-right: 1rem;
text-align: right;
}
}
ul {
overflow: hidden;
}
}
}
}
#router-outlet {
article {
background: $secondary;
color: $on-secondary;
height: calc(100% - 2rem);
position: relative;
overflow: auto;
padding: 1rem 2rem;
width: calc(100% - 4rem);
}
}
padding: 1rem 27.1% 1rem 10.4%;
width: 62.5%;
footer {
bottom: 0;
color: rgba(255, 255, 255, .25);
font-size: .625rem;
left: 0;
padding: .5rem 1.5rem;
position: absolute;
width: calc(100% - 1.5rem * 2);
@media (max-width: #{$bp-small}) {
display: none;
img {
max-width: 100%;
}
}
}
@ -200,6 +244,7 @@ a {
text-decoration: none;
}
// Docs typography
.doc-typography {
$alert: #AF1010;
$on-alert: #fff;
@ -220,71 +265,25 @@ a {
$blockquote: #181818;
$on-blockquote: #ccc;
$padding: .25rem .5rem;
$border-radius: $border-radius;
// $padding: .25rem .5rem;
// $border-radius: $border-radius;
$margin: 0 0 .5rem;
table {
text-align: left;
}
h1,
h2,
h3,
h4,
h5,
h6 {
blockquote {
background: rgba(255, 255, 255, .125);
border-radius: 4px;
margin: 0;
}
padding: .5rem .7rem;
h1 {
font-family: $font-source-sans-pro;
font-size: 3rem;
font-weight: 700;
letter-spacing: -.015625em;
line-height: 6rem;
p {
margin: 0;
}
}
h2 {
font-family: $font-source-sans-pro;
font-size: 2.25rem;
font-weight: 700;
letter-spacing: -.0083333333em;
line-height: 3.75rem;
}
h3 {
font-family: $font-source-sans-pro;
font-size: 1.75rem;
font-weight: 700;
letter-spacing: normal;
line-height: 3.125rem;
}
h4 {
font-family: $font-source-sans-pro;
font-size: 1.75rem;
font-weight: 500;
letter-spacing: .0073529412em;
line-height: 2.5rem;
}
h5 {
font-family: $font-source-sans-pro;
font-size: 1.5rem;
font-weight: 500;
letter-spacing: normal;
line-height: 2rem;
}
h6 {
font-family: $font-source-sans-pro;
font-size: 1.25rem;
font-weight: 500;
letter-spacing: normal;
line-height: 2rem;
}
/*
p,
pre ul,
li,
@ -297,14 +296,6 @@ a {
line-height: 1.5rem;
}
p,
ul,
li,
blockquote,
span {
font-family: $font-open-sans;
}
pre,
code {
background: $code !important;
@ -418,4 +409,5 @@ a {
}
}
*/
}

View File

@ -3,10 +3,10 @@
$background: #fff;
$on-background: #000;
$primary: #121212;
$primary: #080808;
$on-primary: #fff;
$secondary: #282828;
$secondary: #1f1f1f;
$on-secondary: #fff;
$accent: #ffc107;

View File

@ -11,14 +11,12 @@
<body>
<header aki-toolbar>
<a class="left" href="../../index.html">
<a class="left" href="./">
<img class="logo" src="./assets/img/logo.png">
<span class="title text2">
<span>SPT-AKI - Docs</span>
</span>
<span class="title">SPT-AKI - Docs</span>
</a>
<nav class="text2 right dropdown">
<nav class="right dropdown">
<div class="dropdown-button">...</div>
<div class="dropdown-content">
<a href="https://www.sp-tarkov.com">Website</a>
@ -30,133 +28,13 @@
<main>
<aside></aside>
<div id="router-outlet" class="doc-typography">
<div class="text2" style="align-items:center;display:flex;height:100%;justify-content: center;">
<div aki-card>
Select a guide on the left to get started.
</div>
</div>
</div>
<article id="router-outlet" class="doc-typography"></article>
</main>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script src="./assets/js/prism.js"></script>
<script src="./assets/js/aki-navigator.js"></script>
<script src="./assets/js/docs.js"></script>
<script>
// TODO: keep updating old files and add them the the routes list
// TODO: work on routes nesting
const routes = {
"SPT-AKI": {
"About": "spt-aki/about.md",
"Install": "spt-aki/install.md",
"FAQ": "spt-aki/faq.md",
},
"Tutorials": {
// Generalist tutorials (walkthrough projects)
"Edit profiles": "tutorials/edit_profiles.md",
"Edit weapons texture": "tutorials/edit_weapons_texture.md",
"Edit weapons texture(images)": "tutorials/photoshop_texture_editing.md",
"WorkInProgress": "demo.md"
},
"Modding": {
// Here are guides only related to modifying the server/client.
"WorkInProgress": "demo.md"
},
"Resources": {
// Here are ressources (mostly ingame ids list) to help with modding.
"Tutorials index": "resources/index.md",
"Player profile": "resources/player_profile.md",
"Quests": "resources/quests.md",
"Locations": "resources/locations.md",
"Item stats": "resources/items_stats.md",
"Other": "resources/other.md",
},
"Development": {
// Documents related to maintaining the project
"Setup": "development/setup.md",
"Dump data": "development/dump_data.md"
},
// "DEBUG": {
// "** Markdown Demo": "demo.md"
// },
// "Tutorials-old":{
// "Create a mod on SP-Tarkov": ".old/tutorials/create_a_mod.md", // TODO: Create a "modding 101 series"
// "How to report a bug": ".old/tutorials/bug-report.md", // TODO: include in FAQ
// "Editing differents things in my player profile": ".old/tutorials/edit_the_player_profile.md",
// "Change some traders behaviour": ".old/tutorials/edit_traders_values.md",
// "How to customize maps values": ".old/tutorials/edit_location_values.md",
// "Change global values of the server": ".old/tutorials/edit_globals_values.md",
// "Edit weapons textures": ".old/tutorials/edit_weapons_textures.md",
// "Edit weapons textures with photoshop": ".old/tutorials/photoshop_texture_editing.md",
// "Customize weather presets": ".old/tutorials/create_weather.md",
// "Add new bundles to the game": ".old/tutorials/add_new_bundles.md"
// },
// "Modding":{
// "All items stats resources":"resources/itemsStats_resources.md",
// "All locations resources":"resources/locations_resources.md",
// "All player profile resources":"resources/playerProfile_resources.md",
// "All quest resources":"resources/quests_resources.md",
// "All other resources":"resources/other_resources.md"
// }
};
/**
* Populates the <aside> element in the page
* based on the `routes` object content.
*/
function populateNav() {
Object.entries(routes).forEach(([key, node]) => {
const sectionTitle = document.createElement('div');
sectionTitle.classList.add('subheader');
sectionTitle.innerText = key;
const sectionList = document.createElement('ul');
// sectionTitle.appendChild(sectionList);
Object.entries(node).forEach(([k, v]) => {
const listItem = document.createElement('li');
const link = document.createElement('a');
link.innerText = k;
link.href = `#${v}`;
listItem.appendChild(link);
// listItem.setAttribute('link', v);
// listItem.innerText = k;
// The nav binding
listItem.addEventListener('click', e => {
if (e.target && e.target.hasAttribute('link')) {
window.location.hash = e.target.getAttribute('link');
}
});
sectionList.appendChild(listItem);
});
const divider = document.createElement('hr');
divider.setAttribute('aki-divider', '');
const nav = document.querySelector('aside');
nav.appendChild(sectionTitle);
nav.appendChild(sectionList);
nav.appendChild(divider);
});
}
populateNav();
// Dirty override
class AkiNavigatorDocs extends AkiNavigator {
async fetchView(view) {
const response = await fetch(`${this.fetchPath}/${view}`);
const text = await response.text();
this.removeChildren(this.contentOutlet);
this.contentOutlet.innerHTML = marked(text); // edited
Prism.highlightAll(); // edited
}
}
const akiNavigator = new AkiNavigatorDocs(undefined, 'md');
const docs = new Docs(undefined, 'md');
</script>
</body>

166
docs/index.old.html Normal file
View File

@ -0,0 +1,166 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>SPT-AKI</title>
<link rel="stylesheet" href="./assets/css/style.css">
<link rel="stylesheet" href="./assets/css/prism.css">
</head>
<body>
<header aki-toolbar>
<a class="left" href="../../index.html">
<img class="logo" src="./assets/img/logo.png">
<span class="title text2">
<span>SPT-AKI - Docs</span>
</span>
</a>
<nav class="text2 right dropdown">
<div class="dropdown-button">...</div>
<div class="dropdown-content">
<a href="https://www.sp-tarkov.com">Website</a>
<a href="https://mods.sp-tarkov.com">Workshop</a>
<a href="https://dev.sp-tarkov.com">Gitea</a>
</div>
</nav>
</header>
<main>
<aside></aside>
<div id="router-outlet" class="doc-typography">
<div class="text2" style="align-items:center;display:flex;height:100%;justify-content: center;">
<div aki-card>
Select a guide on the left to get started.
</div>
</div>
</div>
</main>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script src="./assets/js/prism.js"></script>
<script src="./assets/js/aki-navigator.js"></script>
<script>
// TODO: keep updating old files and add them the the routes list
// TODO: work on routes nesting
const routes = {
"SPT-AKI": {
"About": "spt-aki/about.md",
"Install": "spt-aki/install.md",
"FAQ": "spt-aki/faq.md",
},
"Tutorials": {
// Generalist tutorials (walkthrough projects)
"Character profile": {
"Edit character level": "tutorials/profile/edit_character_level.md",
"Edit skill level": "tutorials/profile/edit_skill_level.md"
},
"Edit profiles": "tutorials/edit_profiles.md",
"Edit weapons texture": "tutorials/edit_weapons_texture.md",
"Edit weapons texture(images)": "tutorials/photoshop_texture_editing.md",
"WorkInProgress": "demo.md"
},
"Modding": {
// Here are guides only related to modifying the server/client.
"WorkInProgress": "demo.md"
},
"Resources": {
// Here are ressources (mostly ingame ids list) to help with modding.
"Tutorials index": "resources/index.md",
"Player profile": "resources/player_profile.md",
"Quests": "resources/quests.md",
"Locations": "resources/locations.md",
"Item stats": "resources/items_stats.md",
"Other": "resources/other.md",
},
"Development": {
// Documents related to maintaining the project
"Setup": "development/setup.md",
"Dump data": "development/dump_data.md"
},
// "DEBUG": {
// "** Markdown Demo": "demo.md"
// },
// "Tutorials-old":{
// "Create a mod on SP-Tarkov": ".old/tutorials/create_a_mod.md", // TODO: Create a "modding 101 series"
// "How to report a bug": ".old/tutorials/bug-report.md", // TODO: include in FAQ
// "Editing differents things in my player profile": ".old/tutorials/edit_the_player_profile.md",
// "Change some traders behaviour": ".old/tutorials/edit_traders_values.md",
// "How to customize maps values": ".old/tutorials/edit_location_values.md",
// "Change global values of the server": ".old/tutorials/edit_globals_values.md",
// "Edit weapons textures": ".old/tutorials/edit_weapons_textures.md",
// "Edit weapons textures with photoshop": ".old/tutorials/photoshop_texture_editing.md",
// "Customize weather presets": ".old/tutorials/create_weather.md",
// "Add new bundles to the game": ".old/tutorials/add_new_bundles.md"
// },
// "Modding":{
// "All items stats resources":"resources/itemsStats_resources.md",
// "All locations resources":"resources/locations_resources.md",
// "All player profile resources":"resources/playerProfile_resources.md",
// "All quest resources":"resources/quests_resources.md",
// "All other resources":"resources/other_resources.md"
// }
};
/**
* Populates the <aside> element in the page
* based on the `routes` object content.
*/
function populateNav() {
Object.entries(routes).forEach(([key, node]) => {
const sectionTitle = document.createElement('div');
sectionTitle.classList.add('subheader');
sectionTitle.innerText = key;
const sectionList = document.createElement('ul');
// sectionTitle.appendChild(sectionList);
Object.entries(node).forEach(([k, v]) => {
const listItem = document.createElement('li');
const link = document.createElement('a');
link.innerText = k;
link.href = `#${v}`;
listItem.appendChild(link);
// listItem.setAttribute('link', v);
// listItem.innerText = k;
// The nav binding
listItem.addEventListener('click', e => {
if (e.target && e.target.hasAttribute('link')) {
window.location.hash = e.target.getAttribute('link');
}
});
sectionList.appendChild(listItem);
});
const divider = document.createElement('hr');
divider.setAttribute('aki-divider', '');
const nav = document.querySelector('aside');
nav.appendChild(sectionTitle);
nav.appendChild(sectionList);
nav.appendChild(divider);
});
}
populateNav();
// Dirty override
class AkiNavigatorDocs extends AkiNavigator {
async fetchView(view) {
const response = await fetch(`${this.fetchPath}/${view}`);
const text = await response.text();
this.removeChildren(this.contentOutlet);
this.contentOutlet.innerHTML = marked(text); // edited
Prism.highlightAll(); // edited
}
}
const akiNavigator = new AkiNavigatorDocs("lol", 'md');
</script>
</body>

View File

@ -0,0 +1,9 @@
# 101 - Getting started
This tutorial is an introduction to SPT-AKI editing. It will cover basic file editing as well as a quick introduction to modding.
## Getting the right tools for the job
...
##

View File

@ -1,5 +1,9 @@
# ![Editing profiles](./assets/img/headers/tutorials_profiles.png)
> * As with every editing tutorial, it's recommanded to use VSCodium.
> * The game and the server need to be closed before doing any changes.
> * It's recommended to create a backup of the profile you're about to edit.
## Legend
Expression | What | Example
@ -7,12 +11,6 @@ Expression | What | Example
`%server%` | Server folder. | `C:\Games\SPT-AKI\Server\`
`%profileID%` | File containing a profile. | `C:\Games\SPT-AKI\Server\user\profiles\9dbfcbf0d3be487b9ac20cd8.json`
## Requirements & Notes
* [VSCodium](https://github.com/VSCodium/vscodium/releases/download/1.51.1/VSCodiumSetup-x64-1.49.1.exe)
Before doing any changes, the game and the server need to be closed. It's also recommended to create a backup of the profile you're about to edit. For this, heads to `%server%\user\%profileID%` and create a copy of the profile.
## Edit character level
* Open the wanted character profile with VSCodium (`%server%\user\%profileId%`).
@ -28,43 +26,23 @@ On the next server startup the character will be at the desired level.
* Before:
```json
[...]
"characters": {
"pmc": {
"_id": "pmc9dbfcbf0d3be487b9ac20cd8",
"aid": "9dbfcbf0d3be487b9ac20cd8",
"savage": "scav9dbfcbf0d3be487b9ac20cd8",
"Info": {
"Nickname": "Atomos",
"LowerNickname": "atomos",
"Side": "Bear",
"Voice": "Bear_3",
"Level": 1,
"Experience": 27, // <== What needs to be edited.
"RegistrationDate": 1605806909,
"GameVersion": "standard",
[...]
// [...]
"Side": "Bear",
"Voice": "Bear_3",
"Level": 1,
"Experience": 27, // <== What needs to be edited.
// [...]
```
* After:
```json
[...]
"characters": {
"pmc": {
"_id": "pmc9dbfcbf0d3be487b9ac20cd8",
"aid": "9dbfcbf0d3be487b9ac20cd8",
"savage": "scav9dbfcbf0d3be487b9ac20cd8",
"Info": {
"Nickname": "Atomos",
"LowerNickname": "atomos",
"Side": "Bear",
"Voice": "Bear_3",
"Level": 1,
"Experience": 781760, // To reach level 30.
"RegistrationDate": 1605806909,
"GameVersion": "standard",
[...]
// [...]
"Side": "Bear",
"Voice": "Bear_3",
"Level": 1,
"Experience": 781760,
// [...]
```
> **Understanding why :** A character's level, in Escape From Tarkov, is not tied to the `"Level"` property. Instead, it's derived from the amount of experience it has. As such, a character with `781760` experience points will be level 30.
@ -76,6 +54,7 @@ On the next server startup the character will be at the desired level.
* *You should now have a long list of all the character skills:*
```json
// [...]
"Common": [
{
"Id": "BotReload",
@ -89,14 +68,7 @@ On the next server startup the character will be at the desired level.
"PointsEarnedDuringSession": 0,
"LastAccess": 0
},
{
"Id": "Strength",
"Progress": 0,
"PointsEarnedDuringSession": 0,
"LastAccess": 0
},
[...]
// [...]
```
* Edit the `Progress` property value of any wanted skill except for `BotReload`.
@ -104,9 +76,7 @@ On the next server startup the character will be at the desired level.
On the next server startup the character's skills will be at the desired level.
Skill properties details :
<div class="doc-info">
### Skill properties
Property | Purpose
----------------------------|---------
@ -115,25 +85,16 @@ Property | Purpose
`PointsEarnedDuringSession` | How many points were acquired during the last session.
`LastAccess` | Last time a point was earned for this skill *(it's a timestamp)*.
</div>
> Each level correspond to 100 points.
> Each level correspond to 100 points (Level 1 = 100, level 10 = 1000, and so on). As such, for `Endurance` to reach level 51, you need to write `5100` for the skill's `Progress` property.
>
> * Level 1 : `100`.
> * Level 10 : `1000`.
> * Level 15 : `1500`.
> * Level 51 : `5100`.
For `Strengh` to reach level 51, you need to write `5100` for the skill's `Progress` property.
```json
{
"Id": "Strength",
"Progress": 5100,
"PointsEarnedDuringSession": 0,
"LastAccess": 0
},
```
>```json
>{
> "Id": "Endurance",
> "Progress": 5100,
> "PointsEarnedDuringSession": 0,
> "LastAccess": 0
>},
>```
## Edit quest status

View File

@ -0,0 +1,50 @@
# Edit character level
> * As with every editing tutorial, it's recommanded to use VSCodium.
> * The game and the server need to be closed before doing any changes.
> * It's recommended to create a backup of the profile you're about to edit.
## Legend
Expression | What | Example
------------|-----------------------------|--------
`%server%` | Server folder. | `C:\Games\SPT-AKI\Server\`
`%profileID%` | File containing a profile. | `C:\Games\SPT-AKI\Server\user\profiles\9dbfcbf0d3be487b9ac20cd8.json`
## Steps
* Open the wanted character profile with VSCodium (`%server%\user\%profileId%`).
* Search for the line with the property `Experience`.
* Go to [this](https://escapefromtarkov.gamepedia.com/Character_skills) EFT Wiki page and copy the `Cumulative Total` value of desired level.
* Paste the value instead of the existing one.
* Save the file.
On the next server startup the character will be at the desired level.
## Example
* Before:
```json
// [...]
"Side": "Bear",
"Voice": "Bear_3",
"Level": 1,
"Experience": 27, // <== What needs to be edited.
// [...]
```
* After:
```json
// [...]
"Side": "Bear",
"Voice": "Bear_3",
"Level": 1,
"Experience": 781760,
// [...]
```
## Understanding why
A character's level, in Escape From Tarkov, is not tied to the `"Level"` property. Instead, it's derived from the amount of experience it has. As such, a character with `781760` experience points will be level 30.

View File

@ -0,0 +1,67 @@
# Edit skill level
> * As with every editing tutorial, it's recommanded to use VSCodium.
> * The game and the server need to be closed before doing any changes.
> * It's recommended to create a backup of the profile you're about to edit.
## Legend
Expression | What | Example
------------|-----------------------------|--------
`%server%` | Server folder. | `C:\Games\SPT-AKI\Server\`
`%profileID%` | File containing a profile. | `C:\Games\SPT-AKI\Server\user\profiles\9dbfcbf0d3be487b9ac20cd8.json`
## Steps
* Open the wanted character profile with VSCodium (`%server%\user\%profileId%`).
* Search for the line with the property `Skills`.
* Next to it, you should have a long list of all the character skills:
```json
// [...]
"Common": [
{
"Id": "BotReload",
"Progress": 0,
"PointsEarnedDuringSession": 0,
"LastAccess": -2147483648
},
{
"Id": "Endurance",
"Progress": 0,
"PointsEarnedDuringSession": 0,
"LastAccess": 0
},
// [...]
```
* Edit the `Progress` property value of any wanted skill except for `BotReload`.
* Save the file.
On the next server startup the character's skills will be at the desired level.
## Example
For `Endurance` to reach level 51, you need to write `5100` for the skill's `Progress` property.
```json
{
"Id": "Endurance",
"Progress": 5100,
"PointsEarnedDuringSession": 0,
"LastAccess": 0
},
```
## Properties
Property | Purpose
----------------------------|---------
`Id` | Name of the skill.
`Progress` | Number of points learned for this skill.
`PointsEarnedDuringSession` | How many points were acquired during the last session.
`LastAccess` | Last time a point was earned for this skill *(it's a timestamp)*.
## Understanding why
A character's skill level in Escape from Tarkov is reached for each hundred point increment. The level 1 requires 100 points, level 2 200 points, level 10 100 points and so on.

1
docs/md/api_ref/api.md Normal file
View File

@ -0,0 +1 @@
api

View File

@ -0,0 +1,98 @@
# About
SPT-AKI is a modding framework for Escape From Tarkov made for people who want to play **offline singleplayer** with progression similar to live. It's made by fans for fans.
## Features
* Offline: No internet connection required, completely offline.
* Progression: You can progress through the game as you would in live.
* Accurate: Many of the game's systems behave exactly the same as live.
* Stable: No disconnects mid-raid, no cheaters to ruin your raid.
* Moddable: Completely configurable to your need through the modding system.
* Legit: SPT-AKI Requires a legally purchased copy of the game to play.
* Free of charge: You don't need to buy the software or the source code of the project to play.
* Open source: You are free to inspect and build the source code of SPT-AKI.
## Credits
The list is huge, so we most likely missed a couple of names.
* Main developer of the project
* Merijn Hendriks (InNoHurryToCode / Senko-san)
* All contributors
* Sorata-Senpai
* Baliston
* Psifour
* Krunchy
* Craink
* stx09
* Ginja
* Reider123
* Terkoiz
* Basuro
* And many more
* All modders
* AssAssIn
* Frumorn
* Kiva
* Divinity
* Prospero
* Saaly
* CROW
* DigitalBarrito
* Cheekiest Breeki
* And many more
* Websites
* Atomos: www and docs website
* AmazingTurtle: items website
* [Woltlab](https://www.woltlab.com/): mods website
* [Gitea](https://gitea.io/): dev website
* Documentation
* Baliston: adding servers functions
* Sorata-Senpai: most of the tutorials
* Senko-san: some tutorials
* enhausser: some tutorials
* Saaly: some tutorials
* Мастер Чиф#1334: fixing Sorata-Senpai english
## Licence
SPT-AKI is licenced under the `University of Illinois / NSCA Open Source` license.
The licence file can be found in each of the repositories related to the SPT-AKI project.
```text
Copyright (c) 2020 Merijn Hendriks. All rights reserved.
Developed by: Merijn Hendriks
SPT-AKI
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the “Software”), to deal
with the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimers.
Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimers in the documentation
and/or other materials provided with the distribution.
Neither the names of Merijn Hendriks, SPT-AKI, nor the names of
its contributors may be used to endorse or promote products derived from
this Software without specific prior written permission.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS WITH THE SOFTWARE.
```

View File

@ -0,0 +1,77 @@
# FAQ
This page will hopefully help you troubleshoot and fix most of the common problems that you might encounter.
## Launcher
### No servers are available
Make sure that `Server.exe` says that the server is running, then press the refresh button in the launcher.
### No connection can be established
Make sure that `Server.exe` says that the server is running.
### Error: "Object reference not set to an instance of an object"
Make sure you played EFT (Live) at least once on your current windows installation.
1. Start the server *(Server.exe)*.
2. Start the client *(EscapeFromTarkov.exe)*.
3. Wait about 10 seconds on the game loading screen.
4. Close the game *(`Alt + F4`)*.
5. Start `Launcher.exe`.
### Cleaning the temp files
1. Open the launcher.
2. Click on the cogwheel in the right upper corner.
3. Click the **clean temp files** button.
## Server
### Installing mods
Mods should be added the `<server>/mods` directory, located in the server directory.
## Game
### Error: "Input string 'number' is not a valid integer."
![Image showcasing the error](./assets/img/sp-tarkov/faq/error_int_as_string.png)
**⚠️ Close both the game and server when editing the profile⚠ .**
1. Open `<server>/user/profiles/yourProfileID.json` in VSCodium.
2. Search for the number appearing in the error
3. Remove the **".5"** of the number
4. Save the file
5. Start the server
### Endless loading
Your client version is wrong.
Make sure your client version is supported.
Make sure you installed the files correctly.
## Other
### Playing with friends / multiplayer
Play Escape From Tarkov (Live) [here](https://www.escapefromtarkov.com/preorder-page).
*SPT-AKI won't have multiplayer capabilities*.
If you ever find videos of people playing with others, it's not made by the SPT-AKI developers and is not related to it.
### Using the underbarrel grenade launcher
The underbarrel grenade launcher (GP-34) have issues when reloading that will block your character and prevent you from anything else in a raid.
It's not meant to be useable *(at the moment)*, otherwise it would be available on the official game.
### Stuck in the right click menu UI
You can reduce your mouse right click speed in the windows options.
![Windows 10 mouse settings menu](./assets/img/sp-tarkov/faq/mouse1.png)
![Additional mouse options menu](./assets/img/sp-tarkov/faq/mouse2.png)

View File

@ -0,0 +1,53 @@
# Setup guide
This guide covers the installation process for any of the releases of SPT-AKI since version `alpha-r6`.
## Requirements
<!-- TODO: update SPT-AKI files link -->
<!-- TODO: update 2nd img to a screenshot of the new release page -->
* A legal copy of [Escape From Tarkov](https://www.escapefromtarkov.com/preorder-page)
* Microsoft [.NET 5.0 Runtime (64bits)](https://dotnet.microsoft.com/download/dotnet/thank-you/runtime-5.0.0-windows-x64-installer)
* [Visual C++ Redistributable Packages for Visual Studio 2013](https://www.microsoft.com/en-ie/download/details.aspx?id=40784)
* Up to data for [DirectX End-User Runtimes](https://www.microsoft.com/en-ie/download/details.aspx?id=35)
* [SPT-AKI files](https://mods.sp-tarkov.com/files/category-file-list/58-releases/)
## Installation
### Checking compatibility
* Open BSG Launcher and check your game version (bottom right corner).
![BSG Launcher](../assets/img/sp-tarkov/install/001.webp)
<!-- Edit for the guilded version:
![BSG Launcher](https://img.guildedcdn.com/ContentMedia/096464129e28d628476bb066510e7ae9-Full.webp)
-->
* On the project page, check if one of SPT-AKI versions is compatible with your client version.
![SPT-AKI releases page](../assets/img/sp-tarkov/install/002.webp)
<!-- Edit for the guilded version:
![SP-Tarkov modules and server releases pages](https://img.guildedcdn.com/ContentMedia/25ffcad735c1a4f7aaba931bbfd6027e-Full.webp)
)
-->
> If no version is available for your client version, wait for the project to make a new release.
### Installing
Download the release matching your client version.
![SPT-AKI releases pages](../assets/img/sp-tarkov/install/003.webp)
<!-- Edit for the guilded version:
![Downloading SP-Tarkov modules and server releases](https://img.guildedcdn.com/ContentMedia/bd2187554d69181f3d11c0c257edd663-Full.webp)
)
-->
...
### Running
...

View File

@ -0,0 +1,25 @@
# Tutorial: Getting OP
This tutorial is an introduction to profile editing.
It will guide you through a set of instructions regarding editing diverse properties of one of your characters profile.
Additionnaly, explanations are provided to explain how the game and the server are using these properties.
By the end of this tutorial you will be able to do the following:
* Edit a character's level.
* Edit a character's skill level.
* Edit a character's quest status.
* Edit an hideout area status.
* Add money to a character's stash.
This tutorial should give you enough knowledge to gain confidence with character editing.
## What you'll do
The tutorial will guide you so that you can make a fresh character get OP by means of profile editing, so that you can go ahead and fool around in the game with a maxed out character without having to grind.
You'll start by creating a new character and step by step, upgrade him to become of "chad".
He will be level 30, have the max level for each skills, finished all quests and have a maxed out hideout. On top of that he will be loaded with enough money to start his own charity.

View File

@ -0,0 +1,26 @@
# Tutorial: Getting OP
> **Getting started**\
> You will need either [VSCode](https://code.visualstudio.com/) or [VSCodium](https://vscodium.com/) to properly follow this tutorial.
This tutorial is an introduction to profile editing. It will guide you through a set of instructions regarding editing diverse properties of one of your characters profile.
Additionnaly, explanations are provided to explain how the game and the server are using these properties.
By the end of this tutorial you will be able to do the following:
* Edit a character's level.
* Edit a character's skill level.
* Edit a character's quest status.
* Edit an hideout area status.
* Add money to a character's stash.
This tutorial should give you enough knowledge to gain confidence with character editing.
## What you'll do
The tutorial will help you make a fresh character OP by means of profile editing, so that you can go ahead and fool around in the game with a maxed out character without having to grind.
You'll start by creating a new character and step by step, upgrade him to become of "chad".
He will be level 30, have the max level for each skills, finished all quests and have a maxed out hideout. On top of that he will be loaded with enough money to start his own charity.

View File

@ -0,0 +1,66 @@
# Getting started
You will begin by creating a fresh profile using the SPT-AKI launcher. By following this tutorial, you'll prepare everything needed to proceed with the next steps.
In this part you will be doing the following:
1. Create a new profile
2. Identify your newly created profile.
3. Learn how to back up a profile simply.
## Legend
The table below is a set of "expressions" that will be used to avoid writing informations that might not apply to your use case, such as the path to your SPT-AKI installation, or a randomly generated value.
Expression | What | Example
--------------|-----------------------------|--------
`%game%` | SPT-AKI install location. | `C:\Games\SPT-AKI`
`%profileID%` | File containing a profile. | `C:\Games\SPT-AKI\Server\user\profiles\9dbfcbf0d3be487b9ac20cd8.json`
## Creating a new profile
You want a way to fool around in SPT-AKI but without also ruining the fun of having a character evolving normally. As such creating a new dedicated profile is probably the best way of achiving this goal.
To create a new profile:
1. Start SPT-AKI's server by going into `%game%\server\` and double clicking on the server executable.
2. Start SPT-AKI's launcher by going into `%game%\` and double clicking on the launcher executable.
3. Create a new profile through the launcher.
[screenshots (account creation)]
> Note about fresh profile (being mostly empty; do not edit; ...).
4. Starts the game.
5. Go through the onboarding and choose your language, nickname and faction.
[screenshot (fresh account inventory screen)]
6. Quit the game.
7. Close the launcher.
8. Close the server.
> Note about profile saving...
## Identifying a profile
...
### Alternative "quick" way
(by not closing the server and getting the profileID)
## Making a backup
...
## Final review
...
## Summary
* You learned how to identify a profile.
* You learned how to simply back up a profile.

View File

@ -0,0 +1,3 @@
# Editing a character level
...

View File

@ -0,0 +1,3 @@
# Editing a character's skill level
...

View File

@ -0,0 +1,3 @@
# Editing a character's quest status
...

View File

@ -0,0 +1,3 @@
# Editing an hideout area status
...

View File

@ -0,0 +1,3 @@
# Adding money to a character's stash
...

View File

@ -0,0 +1 @@
tut1_prefab_swap

View File

@ -0,0 +1 @@
cw_0

View File

@ -0,0 +1 @@
cw_p1

View File

@ -0,0 +1 @@
cw_p2

View File

@ -0,0 +1 @@
cw_p3

View File

@ -0,0 +1 @@
cw_p4