diff --git a/404.html b/404.html index 725b396c8..f3c6d56bc 100644 --- a/404.html +++ b/404.html @@ -6,7 +6,7 @@ 404 | The Paper Pilot - + @@ -17,8 +17,8 @@
Skip to content

404

PAGE NOT FOUND

But if you don't change your direction, and if you keep looking, you may end up where you are heading.
- - + + \ No newline at end of file diff --git a/assets/app.9bfeb8de.js b/assets/app.9bfeb8de.js new file mode 100644 index 000000000..656823cd6 --- /dev/null +++ b/assets/app.9bfeb8de.js @@ -0,0 +1 @@ +function Ms(e,t){const n=Object.create(null),s=e.split(",");for(let o=0;o!!n[o.toLowerCase()]:o=>!!n[o]}const Pi="itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly",ki=Ms(Pi);function cr(e){return!!e||e===""}function Dn(e){if(K(e)){const t={};for(let n=0;n{if(n){const s=n.split(Si);s.length>1&&(t[s[0].trim()]=s[1].trim())}}),t}function he(e){let t="";if(we(e))t=e;else if(K(e))for(let n=0;nwe(e)?e:e==null?"":K(e)||ge(e)&&(e.toString===dr||!X(e.toString))?JSON.stringify(e,ar,2):String(e),ar=(e,t)=>t&&t.__v_isRef?ar(e,t.value):At(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((n,[s,o])=>(n[`${s} =>`]=o,n),{})}:ur(t)?{[`Set(${t.size})`]:[...t.values()]}:ge(t)&&!K(t)&&!hr(t)?String(t):t,ve={},It=[],Ke=()=>{},Ti=()=>!1,Ei=/^on[^a-z]/,hn=e=>Ei.test(e),Is=e=>e.startsWith("onUpdate:"),$e=Object.assign,As=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},Li=Object.prototype.hasOwnProperty,se=(e,t)=>Li.call(e,t),K=Array.isArray,At=e=>Rn(e)==="[object Map]",ur=e=>Rn(e)==="[object Set]",X=e=>typeof e=="function",we=e=>typeof e=="string",Ns=e=>typeof e=="symbol",ge=e=>e!==null&&typeof e=="object",fr=e=>ge(e)&&X(e.then)&&X(e.catch),dr=Object.prototype.toString,Rn=e=>dr.call(e),Mi=e=>Rn(e).slice(8,-1),hr=e=>Rn(e)==="[object Object]",Os=e=>we(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,Zt=Ms(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),Un=e=>{const t=Object.create(null);return n=>t[n]||(t[n]=e(n))},Ii=/-(\w)/g,Ze=Un(e=>e.replace(Ii,(t,n)=>n?n.toUpperCase():"")),Ai=/\B([A-Z])/g,Kt=Un(e=>e.replace(Ai,"-$1").toLowerCase()),jn=Un(e=>e.charAt(0).toUpperCase()+e.slice(1)),ls=Un(e=>e?`on${jn(e)}`:""),on=(e,t)=>!Object.is(e,t),cs=(e,t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,value:n})},_r=e=>{const t=parseFloat(e);return isNaN(t)?e:t};let ho;const Ni=()=>ho||(ho=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});let Ie;class Oi{constructor(t=!1){this.active=!0,this.effects=[],this.cleanups=[],!t&&Ie&&(this.parent=Ie,this.index=(Ie.scopes||(Ie.scopes=[])).push(this)-1)}run(t){if(this.active){const n=Ie;try{return Ie=this,t()}finally{Ie=n}}}on(){Ie=this}off(){Ie=this.parent}stop(t){if(this.active){let n,s;for(n=0,s=this.effects.length;n{const t=new Set(e);return t.w=0,t.n=0,t},pr=e=>(e.w&ht)>0,vr=e=>(e.n&ht)>0,Di=({deps:e})=>{if(e.length)for(let t=0;t{const{deps:t}=e;if(t.length){let n=0;for(let s=0;s{(f==="length"||f>=s)&&l.push(c)});else switch(n!==void 0&&l.push(i.get(n)),t){case"add":K(e)?Os(n)&&l.push(i.get("length")):(l.push(i.get(St)),At(e)&&l.push(i.get(gs)));break;case"delete":K(e)||(l.push(i.get(St)),At(e)&&l.push(i.get(gs)));break;case"set":At(e)&&l.push(i.get(St));break}if(l.length===1)l[0]&&bs(l[0]);else{const c=[];for(const f of l)f&&c.push(...f);bs(Bs(c))}}function bs(e,t){const n=K(e)?e:[...e];for(const s of n)s.computed&&po(s);for(const s of n)s.computed||po(s)}function po(e,t){(e!==je||e.allowRecurse)&&(e.scheduler?e.scheduler():e.run())}const Ui=Ms("__proto__,__v_isRef,__isVue"),br=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(Ns)),ji=Hs(),zi=Hs(!1,!0),Ki=Hs(!0),vo=Wi();function Wi(){const e={};return["includes","indexOf","lastIndexOf"].forEach(t=>{e[t]=function(...n){const s=ce(this);for(let r=0,i=this.length;r{e[t]=function(...n){Wt();const s=ce(this)[t].apply(this,n);return qt(),s}}),e}function Hs(e=!1,t=!1){return function(s,o,r){if(o==="__v_isReactive")return!e;if(o==="__v_isReadonly")return e;if(o==="__v_isShallow")return t;if(o==="__v_raw"&&r===(e?t?cl:Pr:t?$r:xr).get(s))return s;const i=K(s);if(!e&&i&&se(vo,o))return Reflect.get(vo,o,r);const l=Reflect.get(s,o,r);return(Ns(o)?br.has(o):Ui(o))||(e||Ne(s,"get",o),t)?l:ke(l)?i&&Os(o)?l:l.value:ge(l)?e?Us(l):Kn(l):l}}const qi=yr(),Gi=yr(!0);function yr(e=!1){return function(n,s,o,r){let i=n[s];if(Rt(i)&&ke(i)&&!ke(o))return!1;if(!e&&(!Vn(o)&&!Rt(o)&&(i=ce(i),o=ce(o)),!K(n)&&ke(i)&&!ke(o)))return i.value=o,!0;const l=K(n)&&Os(s)?Number(s)e,zn=e=>Reflect.getPrototypeOf(e);function mn(e,t,n=!1,s=!1){e=e.__v_raw;const o=ce(e),r=ce(t);n||(t!==r&&Ne(o,"get",t),Ne(o,"get",r));const{has:i}=zn(o),l=s?Ds:n?zs:rn;if(i.call(o,t))return l(e.get(t));if(i.call(o,r))return l(e.get(r));e!==o&&e.get(t)}function gn(e,t=!1){const n=this.__v_raw,s=ce(n),o=ce(e);return t||(e!==o&&Ne(s,"has",e),Ne(s,"has",o)),e===o?n.has(e):n.has(e)||n.has(o)}function bn(e,t=!1){return e=e.__v_raw,!t&&Ne(ce(e),"iterate",St),Reflect.get(e,"size",e)}function mo(e){e=ce(e);const t=ce(this);return zn(t).has.call(t,e)||(t.add(e),ot(t,"add",e,e)),this}function go(e,t){t=ce(t);const n=ce(this),{has:s,get:o}=zn(n);let r=s.call(n,e);r||(e=ce(e),r=s.call(n,e));const i=o.call(n,e);return n.set(e,t),r?on(t,i)&&ot(n,"set",e,t):ot(n,"add",e,t),this}function bo(e){const t=ce(this),{has:n,get:s}=zn(t);let o=n.call(t,e);o||(e=ce(e),o=n.call(t,e)),s&&s.call(t,e);const r=t.delete(e);return o&&ot(t,"delete",e,void 0),r}function yo(){const e=ce(this),t=e.size!==0,n=e.clear();return t&&ot(e,"clear",void 0,void 0),n}function yn(e,t){return function(s,o){const r=this,i=r.__v_raw,l=ce(i),c=t?Ds:e?zs:rn;return!e&&Ne(l,"iterate",St),i.forEach((f,h)=>s.call(o,c(f),c(h),r))}}function wn(e,t,n){return function(...s){const o=this.__v_raw,r=ce(o),i=At(r),l=e==="entries"||e===Symbol.iterator&&i,c=e==="keys"&&i,f=o[e](...s),h=n?Ds:t?zs:rn;return!t&&Ne(r,"iterate",c?gs:St),{next(){const{value:m,done:x}=f.next();return x?{value:m,done:x}:{value:l?[h(m[0]),h(m[1])]:h(m),done:x}},[Symbol.iterator](){return this}}}}function it(e){return function(...t){return e==="delete"?!1:this}}function el(){const e={get(r){return mn(this,r)},get size(){return bn(this)},has:gn,add:mo,set:go,delete:bo,clear:yo,forEach:yn(!1,!1)},t={get(r){return mn(this,r,!1,!0)},get size(){return bn(this)},has:gn,add:mo,set:go,delete:bo,clear:yo,forEach:yn(!1,!0)},n={get(r){return mn(this,r,!0)},get size(){return bn(this,!0)},has(r){return gn.call(this,r,!0)},add:it("add"),set:it("set"),delete:it("delete"),clear:it("clear"),forEach:yn(!0,!1)},s={get(r){return mn(this,r,!0,!0)},get size(){return bn(this,!0)},has(r){return gn.call(this,r,!0)},add:it("add"),set:it("set"),delete:it("delete"),clear:it("clear"),forEach:yn(!0,!0)};return["keys","values","entries",Symbol.iterator].forEach(r=>{e[r]=wn(r,!1,!1),n[r]=wn(r,!0,!1),t[r]=wn(r,!1,!0),s[r]=wn(r,!0,!0)}),[e,n,t,s]}const[tl,nl,sl,ol]=el();function Rs(e,t){const n=t?e?ol:sl:e?nl:tl;return(s,o,r)=>o==="__v_isReactive"?!e:o==="__v_isReadonly"?e:o==="__v_raw"?s:Reflect.get(se(n,o)&&o in s?n:s,o,r)}const rl={get:Rs(!1,!1)},il={get:Rs(!1,!0)},ll={get:Rs(!0,!1)},xr=new WeakMap,$r=new WeakMap,Pr=new WeakMap,cl=new WeakMap;function al(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function ul(e){return e.__v_skip||!Object.isExtensible(e)?0:al(Mi(e))}function Kn(e){return Rt(e)?e:js(e,!1,wr,rl,xr)}function fl(e){return js(e,!1,Zi,il,$r)}function Us(e){return js(e,!0,Xi,ll,Pr)}function js(e,t,n,s,o){if(!ge(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const r=o.get(e);if(r)return r;const i=ul(e);if(i===0)return e;const l=new Proxy(e,i===2?s:n);return o.set(e,l),l}function Nt(e){return Rt(e)?Nt(e.__v_raw):!!(e&&e.__v_isReactive)}function Rt(e){return!!(e&&e.__v_isReadonly)}function Vn(e){return!!(e&&e.__v_isShallow)}function kr(e){return Nt(e)||Rt(e)}function ce(e){const t=e&&e.__v_raw;return t?ce(t):e}function en(e){return Sn(e,"__v_skip",!0),e}const rn=e=>ge(e)?Kn(e):e,zs=e=>ge(e)?Us(e):e;function Cr(e){ft&&je&&(e=ce(e),gr(e.dep||(e.dep=Bs())))}function Sr(e,t){e=ce(e),e.dep&&bs(e.dep)}function ke(e){return!!(e&&e.__v_isRef===!0)}function me(e){return Vr(e,!1)}function dl(e){return Vr(e,!0)}function Vr(e,t){return ke(e)?e:new hl(e,t)}class hl{constructor(t,n){this.__v_isShallow=n,this.dep=void 0,this.__v_isRef=!0,this._rawValue=n?t:ce(t),this._value=n?t:rn(t)}get value(){return Cr(this),this._value}set value(t){const n=this.__v_isShallow||Vn(t)||Rt(t);t=n?t:ce(t),on(t,this._rawValue)&&(this._rawValue=t,this._value=n?t:rn(t),Sr(this))}}function _(e){return ke(e)?e.value:e}const _l={get:(e,t,n)=>_(Reflect.get(e,t,n)),set:(e,t,n,s)=>{const o=e[t];return ke(o)&&!ke(n)?(o.value=n,!0):Reflect.set(e,t,n,s)}};function Tr(e){return Nt(e)?e:new Proxy(e,_l)}var Er;class pl{constructor(t,n,s,o){this._setter=n,this.dep=void 0,this.__v_isRef=!0,this[Er]=!1,this._dirty=!0,this.effect=new Fs(t,()=>{this._dirty||(this._dirty=!0,Sr(this))}),this.effect.computed=this,this.effect.active=this._cacheable=!o,this.__v_isReadonly=s}get value(){const t=ce(this);return Cr(t),(t._dirty||!t._cacheable)&&(t._dirty=!1,t._value=t.effect.run()),t._value}set value(t){this._setter(t)}}Er="__v_isReadonly";function vl(e,t,n=!1){let s,o;const r=X(e);return r?(s=e,o=Ke):(s=e.get,o=e.set),new pl(s,o,r||!o,n)}function dt(e,t,n,s){let o;try{o=s?e(...s):e()}catch(r){Wn(r,t,n)}return o}function He(e,t,n,s){if(X(e)){const r=dt(e,t,n,s);return r&&fr(r)&&r.catch(i=>{Wn(i,t,n)}),r}const o=[];for(let r=0;r>>1;cn(Pe[s])Je&&Pe.splice(t,1)}function yl(e){K(e)?Ot.push(...e):(!nt||!nt.includes(e,e.allowRecurse?$t+1:$t))&&Ot.push(e),Mr()}function wo(e,t=ln?Je+1:0){for(;tcn(n)-cn(s)),$t=0;$te.id==null?1/0:e.id,wl=(e,t)=>{const n=cn(e)-cn(t);if(n===0){if(e.pre&&!t.pre)return-1;if(t.pre&&!e.pre)return 1}return n};function Ir(e){ys=!1,ln=!0,Pe.sort(wl);const t=Ke;try{for(Je=0;JeC.trim())),m&&(o=n.map(_r))}let l,c=s[l=ls(t)]||s[l=ls(Ze(t))];!c&&r&&(c=s[l=ls(Kt(t))]),c&&He(c,e,6,o);const f=s[l+"Once"];if(f){if(!e.emitted)e.emitted={};else if(e.emitted[l])return;e.emitted[l]=!0,He(f,e,6,o)}}function Ar(e,t,n=!1){const s=t.emitsCache,o=s.get(e);if(o!==void 0)return o;const r=e.emits;let i={},l=!1;if(!X(e)){const c=f=>{const h=Ar(f,t,!0);h&&(l=!0,$e(i,h))};!n&&t.mixins.length&&t.mixins.forEach(c),e.extends&&c(e.extends),e.mixins&&e.mixins.forEach(c)}return!r&&!l?(ge(e)&&s.set(e,null),null):(K(r)?r.forEach(c=>i[c]=null):$e(i,r),ge(e)&&s.set(e,i),i)}function Gn(e,t){return!e||!hn(t)?!1:(t=t.slice(2).replace(/Once$/,""),se(e,t[0].toLowerCase()+t.slice(1))||se(e,Kt(t))||se(e,t))}let Ve=null,Yn=null;function En(e){const t=Ve;return Ve=e,Yn=e&&e.type.__scopeId||null,t}function We(e){Yn=e}function qe(){Yn=null}function I(e,t=Ve,n){if(!t||e._n)return e;const s=(...o)=>{s._d&&Mo(-1);const r=En(t),i=e(...o);return En(r),s._d&&Mo(1),i};return s._n=!0,s._c=!0,s._d=!0,s}function as(e){const{type:t,vnode:n,proxy:s,withProxy:o,props:r,propsOptions:[i],slots:l,attrs:c,emit:f,render:h,renderCache:m,data:x,setupState:C,ctx:j,inheritAttrs:F}=e;let J,g;const T=En(e);try{if(n.shapeFlag&4){const G=o||s;J=Ue(h.call(G,G,m,r,C,x,j)),g=c}else{const G=t;J=Ue(G.length>1?G(r,{attrs:c,slots:l,emit:f}):G(r,null)),g=t.props?c:$l(c)}}catch(G){tn.length=0,Wn(G,e,1),J=V(Ae)}let z=J;if(g&&F!==!1){const G=Object.keys(g),{shapeFlag:ne}=z;G.length&&ne&7&&(i&&G.some(Is)&&(g=Pl(g,i)),z=_t(z,g))}return n.dirs&&(z=_t(z),z.dirs=z.dirs?z.dirs.concat(n.dirs):n.dirs),n.transition&&(z.transition=n.transition),J=z,En(T),J}const $l=e=>{let t;for(const n in e)(n==="class"||n==="style"||hn(n))&&((t||(t={}))[n]=e[n]);return t},Pl=(e,t)=>{const n={};for(const s in e)(!Is(s)||!(s.slice(9)in t))&&(n[s]=e[s]);return n};function kl(e,t,n){const{props:s,children:o,component:r}=e,{props:i,children:l,patchFlag:c}=t,f=r.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&c>=0){if(c&1024)return!0;if(c&16)return s?xo(s,i,f):!!i;if(c&8){const h=t.dynamicProps;for(let m=0;me.__isSuspense;function Nr(e,t){t&&t.pendingBranch?K(e)?t.effects.push(...e):t.effects.push(e):yl(e)}function Qn(e,t){if(xe){let n=xe.provides;const s=xe.parent&&xe.parent.provides;s===n&&(n=xe.provides=Object.create(s)),n[e]=t}}function Xe(e,t,n=!1){const s=xe||Ve;if(s){const o=s.parent==null?s.vnode.appContext&&s.vnode.appContext.provides:s.parent.provides;if(o&&e in o)return o[e];if(arguments.length>1)return n&&X(t)?t.call(s.proxy):t}}function Ut(e,t){return Jn(e,null,t)}function Or(e,t){return Jn(e,null,{flush:"post"})}const $o={};function st(e,t,n){return Jn(e,t,n)}function Jn(e,t,{immediate:n,deep:s,flush:o,onTrack:r,onTrigger:i}=ve){const l=xe;let c,f=!1,h=!1;if(ke(e)?(c=()=>e.value,f=Vn(e)):Nt(e)?(c=()=>e,s=!0):K(e)?(h=!0,f=e.some(g=>Nt(g)||Vn(g)),c=()=>e.map(g=>{if(ke(g))return g.value;if(Nt(g))return Mt(g);if(X(g))return dt(g,l,2)})):X(e)?t?c=()=>dt(e,l,2):c=()=>{if(!(l&&l.isUnmounted))return m&&m(),He(e,l,3,[x])}:c=Ke,t&&s){const g=c;c=()=>Mt(g())}let m,x=g=>{m=J.onStop=()=>{dt(g,l,4)}};if(fn)return x=Ke,t?n&&He(t,l,3,[c(),h?[]:void 0,x]):c(),Ke;let C=h?[]:$o;const j=()=>{if(!!J.active)if(t){const g=J.run();(s||f||(h?g.some((T,z)=>on(T,C[z])):on(g,C)))&&(m&&m(),He(t,l,3,[g,C===$o?void 0:C,x]),C=g)}else J.run()};j.allowRecurse=!!t;let F;o==="sync"?F=j:o==="post"?F=()=>Te(j,l&&l.suspense):(j.pre=!0,l&&(j.id=l.uid),F=()=>Ws(j));const J=new Fs(c,F);return t?n?j():C=J.run():o==="post"?Te(J.run.bind(J),l&&l.suspense):J.run(),()=>{J.stop(),l&&l.scope&&As(l.scope.effects,J)}}function Vl(e,t,n){const s=this.proxy,o=we(e)?e.includes(".")?Br(s,e):()=>s[e]:e.bind(s,s);let r;X(t)?r=t:(r=t.handler,n=t);const i=xe;jt(this);const l=Jn(o,r.bind(s),n);return i?jt(i):Vt(),l}function Br(e,t){const n=t.split(".");return()=>{let s=e;for(let o=0;o{Mt(n,t)});else if(hr(e))for(const n in e)Mt(e[n],t);return e}function Tl(){const e={isMounted:!1,isLeaving:!1,isUnmounting:!1,leavingVNodes:new Map};return De(()=>{e.isMounted=!0}),Ur(()=>{e.isUnmounting=!0}),e}const Be=[Function,Array],El={name:"BaseTransition",props:{mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:Be,onEnter:Be,onAfterEnter:Be,onEnterCancelled:Be,onBeforeLeave:Be,onLeave:Be,onAfterLeave:Be,onLeaveCancelled:Be,onBeforeAppear:Be,onAppear:Be,onAfterAppear:Be,onAppearCancelled:Be},setup(e,{slots:t}){const n=Zs(),s=Tl();let o;return()=>{const r=t.default&&Dr(t.default(),!0);if(!r||!r.length)return;let i=r[0];if(r.length>1){for(const F of r)if(F.type!==Ae){i=F;break}}const l=ce(e),{mode:c}=l;if(s.isLeaving)return us(i);const f=Po(i);if(!f)return us(i);const h=ws(f,l,s,n);xs(f,h);const m=n.subTree,x=m&&Po(m);let C=!1;const{getTransitionKey:j}=f.type;if(j){const F=j();o===void 0?o=F:F!==o&&(o=F,C=!0)}if(x&&x.type!==Ae&&(!Pt(f,x)||C)){const F=ws(x,l,s,n);if(xs(x,F),c==="out-in")return s.isLeaving=!0,F.afterLeave=()=>{s.isLeaving=!1,n.update()},us(i);c==="in-out"&&f.type!==Ae&&(F.delayLeave=(J,g,T)=>{const z=Hr(s,x);z[String(x.key)]=x,J._leaveCb=()=>{g(),J._leaveCb=void 0,delete h.delayedLeave},h.delayedLeave=T})}return i}}},Fr=El;function Hr(e,t){const{leavingVNodes:n}=e;let s=n.get(t.type);return s||(s=Object.create(null),n.set(t.type,s)),s}function ws(e,t,n,s){const{appear:o,mode:r,persisted:i=!1,onBeforeEnter:l,onEnter:c,onAfterEnter:f,onEnterCancelled:h,onBeforeLeave:m,onLeave:x,onAfterLeave:C,onLeaveCancelled:j,onBeforeAppear:F,onAppear:J,onAfterAppear:g,onAppearCancelled:T}=t,z=String(e.key),G=Hr(n,e),ne=(M,Z)=>{M&&He(M,s,9,Z)},de=(M,Z)=>{const Y=Z[1];ne(M,Z),K(M)?M.every(le=>le.length<=1)&&Y():M.length<=1&&Y()},oe={mode:r,persisted:i,beforeEnter(M){let Z=l;if(!n.isMounted)if(o)Z=F||l;else return;M._leaveCb&&M._leaveCb(!0);const Y=G[z];Y&&Pt(e,Y)&&Y.el._leaveCb&&Y.el._leaveCb(),ne(Z,[M])},enter(M){let Z=c,Y=f,le=h;if(!n.isMounted)if(o)Z=J||c,Y=g||f,le=T||h;else return;let A=!1;const ee=M._enterCb=H=>{A||(A=!0,H?ne(le,[M]):ne(Y,[M]),oe.delayedLeave&&oe.delayedLeave(),M._enterCb=void 0)};Z?de(Z,[M,ee]):ee()},leave(M,Z){const Y=String(e.key);if(M._enterCb&&M._enterCb(!0),n.isUnmounting)return Z();ne(m,[M]);let le=!1;const A=M._leaveCb=ee=>{le||(le=!0,Z(),ee?ne(j,[M]):ne(C,[M]),M._leaveCb=void 0,G[Y]===e&&delete G[Y])};G[Y]=e,x?de(x,[M,A]):A()},clone(M){return ws(M,t,n,s)}};return oe}function us(e){if(Xn(e))return e=_t(e),e.children=null,e}function Po(e){return Xn(e)?e.children?e.children[0]:void 0:e}function xs(e,t){e.shapeFlag&6&&e.component?xs(e.component.subTree,t):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function Dr(e,t=!1,n){let s=[],o=0;for(let r=0;r1)for(let r=0;r!!e.type.__asyncLoader,Xn=e=>e.type.__isKeepAlive;function Ll(e,t){Rr(e,"a",t)}function Ml(e,t){Rr(e,"da",t)}function Rr(e,t,n=xe){const s=e.__wdc||(e.__wdc=()=>{let o=n;for(;o;){if(o.isDeactivated)return;o=o.parent}return e()});if(Zn(t,s,n),n){let o=n.parent;for(;o&&o.parent;)Xn(o.parent.vnode)&&Il(s,t,n,o),o=o.parent}}function Il(e,t,n,s){const o=Zn(t,e,s,!0);pt(()=>{As(s[t],o)},n)}function Zn(e,t,n=xe,s=!1){if(n){const o=n[e]||(n[e]=[]),r=t.__weh||(t.__weh=(...i)=>{if(n.isUnmounted)return;Wt(),jt(n);const l=He(t,n,e,i);return Vt(),qt(),l});return s?o.unshift(r):o.push(r),r}}const rt=e=>(t,n=xe)=>(!fn||e==="sp")&&Zn(e,(...s)=>t(...s),n),Al=rt("bm"),De=rt("m"),Nl=rt("bu"),qs=rt("u"),Ur=rt("bum"),pt=rt("um"),Ol=rt("sp"),Bl=rt("rtg"),Fl=rt("rtc");function Hl(e,t=xe){Zn("ec",e,t)}function Qe(e,t,n,s){const o=e.dirs,r=t&&t.dirs;for(let i=0;it(i,l,void 0,r&&r[l]));else{const i=Object.keys(e);o=new Array(i.length);for(let l=0,c=i.length;lAn(t)?!(t.type===Ae||t.type===q&&!Kr(t.children)):!0)?e:null}const $s=e=>e?ni(e)?eo(e)||e.proxy:$s(e.parent):null,Ln=$e(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>$s(e.parent),$root:e=>$s(e.root),$emit:e=>e.emit,$options:e=>Qs(e),$forceUpdate:e=>e.f||(e.f=()=>Ws(e.update)),$nextTick:e=>e.n||(e.n=qn.bind(e.proxy)),$watch:e=>Vl.bind(e)}),Dl={get({_:e},t){const{ctx:n,setupState:s,data:o,props:r,accessCache:i,type:l,appContext:c}=e;let f;if(t[0]!=="$"){const C=i[t];if(C!==void 0)switch(C){case 1:return s[t];case 2:return o[t];case 4:return n[t];case 3:return r[t]}else{if(s!==ve&&se(s,t))return i[t]=1,s[t];if(o!==ve&&se(o,t))return i[t]=2,o[t];if((f=e.propsOptions[0])&&se(f,t))return i[t]=3,r[t];if(n!==ve&&se(n,t))return i[t]=4,n[t];Ps&&(i[t]=0)}}const h=Ln[t];let m,x;if(h)return t==="$attrs"&&Ne(e,"get",t),h(e);if((m=l.__cssModules)&&(m=m[t]))return m;if(n!==ve&&se(n,t))return i[t]=4,n[t];if(x=c.config.globalProperties,se(x,t))return x[t]},set({_:e},t,n){const{data:s,setupState:o,ctx:r}=e;return o!==ve&&se(o,t)?(o[t]=n,!0):s!==ve&&se(s,t)?(s[t]=n,!0):se(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(r[t]=n,!0)},has({_:{data:e,setupState:t,accessCache:n,ctx:s,appContext:o,propsOptions:r}},i){let l;return!!n[i]||e!==ve&&se(e,i)||t!==ve&&se(t,i)||(l=r[0])&&se(l,i)||se(s,i)||se(Ln,i)||se(o.config.globalProperties,i)},defineProperty(e,t,n){return n.get!=null?e._.accessCache[t]=0:se(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}};let Ps=!0;function Rl(e){const t=Qs(e),n=e.proxy,s=e.ctx;Ps=!1,t.beforeCreate&&Co(t.beforeCreate,e,"bc");const{data:o,computed:r,methods:i,watch:l,provide:c,inject:f,created:h,beforeMount:m,mounted:x,beforeUpdate:C,updated:j,activated:F,deactivated:J,beforeDestroy:g,beforeUnmount:T,destroyed:z,unmounted:G,render:ne,renderTracked:de,renderTriggered:oe,errorCaptured:M,serverPrefetch:Z,expose:Y,inheritAttrs:le,components:A,directives:ee,filters:H}=t;if(f&&Ul(f,s,null,e.appContext.config.unwrapInjectedRef),i)for(const be in i){const _e=i[be];X(_e)&&(s[be]=_e.bind(n))}if(o){const be=o.call(n,n);ge(be)&&(e.data=Kn(be))}if(Ps=!0,r)for(const be in r){const _e=r[be],mt=X(_e)?_e.bind(n,n):X(_e.get)?_e.get.bind(n,n):Ke,pn=!X(_e)&&X(_e.set)?_e.set.bind(n):Ke,gt=re({get:mt,set:pn});Object.defineProperty(s,be,{enumerable:!0,configurable:!0,get:()=>gt.value,set:Ge=>gt.value=Ge})}if(l)for(const be in l)Wr(l[be],s,n,be);if(c){const be=X(c)?c.call(n):c;Reflect.ownKeys(be).forEach(_e=>{Qn(_e,be[_e])})}h&&Co(h,e,"c");function ue(be,_e){K(_e)?_e.forEach(mt=>be(mt.bind(n))):_e&&be(_e.bind(n))}if(ue(Al,m),ue(De,x),ue(Nl,C),ue(qs,j),ue(Ll,F),ue(Ml,J),ue(Hl,M),ue(Fl,de),ue(Bl,oe),ue(Ur,T),ue(pt,G),ue(Ol,Z),K(Y))if(Y.length){const be=e.exposed||(e.exposed={});Y.forEach(_e=>{Object.defineProperty(be,_e,{get:()=>n[_e],set:mt=>n[_e]=mt})})}else e.exposed||(e.exposed={});ne&&e.render===Ke&&(e.render=ne),le!=null&&(e.inheritAttrs=le),A&&(e.components=A),ee&&(e.directives=ee)}function Ul(e,t,n=Ke,s=!1){K(e)&&(e=ks(e));for(const o in e){const r=e[o];let i;ge(r)?"default"in r?i=Xe(r.from||o,r.default,!0):i=Xe(r.from||o):i=Xe(r),ke(i)&&s?Object.defineProperty(t,o,{enumerable:!0,configurable:!0,get:()=>i.value,set:l=>i.value=l}):t[o]=i}}function Co(e,t,n){He(K(e)?e.map(s=>s.bind(t.proxy)):e.bind(t.proxy),t,n)}function Wr(e,t,n,s){const o=s.includes(".")?Br(n,s):()=>n[s];if(we(e)){const r=t[e];X(r)&&st(o,r)}else if(X(e))st(o,e.bind(n));else if(ge(e))if(K(e))e.forEach(r=>Wr(r,t,n,s));else{const r=X(e.handler)?e.handler.bind(n):t[e.handler];X(r)&&st(o,r,e)}}function Qs(e){const t=e.type,{mixins:n,extends:s}=t,{mixins:o,optionsCache:r,config:{optionMergeStrategies:i}}=e.appContext,l=r.get(t);let c;return l?c=l:!o.length&&!n&&!s?c=t:(c={},o.length&&o.forEach(f=>Mn(c,f,i,!0)),Mn(c,t,i)),ge(t)&&r.set(t,c),c}function Mn(e,t,n,s=!1){const{mixins:o,extends:r}=t;r&&Mn(e,r,n,!0),o&&o.forEach(i=>Mn(e,i,n,!0));for(const i in t)if(!(s&&i==="expose")){const l=jl[i]||n&&n[i];e[i]=l?l(e[i],t[i]):t[i]}return e}const jl={data:So,props:xt,emits:xt,methods:xt,computed:xt,beforeCreate:Se,created:Se,beforeMount:Se,mounted:Se,beforeUpdate:Se,updated:Se,beforeDestroy:Se,beforeUnmount:Se,destroyed:Se,unmounted:Se,activated:Se,deactivated:Se,errorCaptured:Se,serverPrefetch:Se,components:xt,directives:xt,watch:Kl,provide:So,inject:zl};function So(e,t){return t?e?function(){return $e(X(e)?e.call(this,this):e,X(t)?t.call(this,this):t)}:t:e}function zl(e,t){return xt(ks(e),ks(t))}function ks(e){if(K(e)){const t={};for(let n=0;n0)&&!(i&16)){if(i&8){const h=e.vnode.dynamicProps;for(let m=0;m{c=!0;const[x,C]=Gr(m,t,!0);$e(i,x),C&&l.push(...C)};!n&&t.mixins.length&&t.mixins.forEach(h),e.extends&&h(e.extends),e.mixins&&e.mixins.forEach(h)}if(!r&&!c)return ge(e)&&s.set(e,It),It;if(K(r))for(let h=0;h-1,C[1]=F<0||j-1||se(C,"default"))&&l.push(m)}}}const f=[i,l];return ge(e)&&s.set(e,f),f}function Vo(e){return e[0]!=="$"}function To(e){const t=e&&e.toString().match(/^\s*function (\w+)/);return t?t[1]:e===null?"null":""}function Eo(e,t){return To(e)===To(t)}function Lo(e,t){return K(t)?t.findIndex(n=>Eo(n,e)):X(t)&&Eo(t,e)?0:-1}const Yr=e=>e[0]==="_"||e==="$stable",Js=e=>K(e)?e.map(Ue):[Ue(e)],Gl=(e,t,n)=>{if(t._n)return t;const s=I((...o)=>Js(t(...o)),n);return s._c=!1,s},Qr=(e,t,n)=>{const s=e._ctx;for(const o in e){if(Yr(o))continue;const r=e[o];if(X(r))t[o]=Gl(o,r,s);else if(r!=null){const i=Js(r);t[o]=()=>i}}},Jr=(e,t)=>{const n=Js(t);e.slots.default=()=>n},Yl=(e,t)=>{if(e.vnode.shapeFlag&32){const n=t._;n?(e.slots=ce(t),Sn(t,"_",n)):Qr(t,e.slots={})}else e.slots={},t&&Jr(e,t);Sn(e.slots,es,1)},Ql=(e,t,n)=>{const{vnode:s,slots:o}=e;let r=!0,i=ve;if(s.shapeFlag&32){const l=t._;l?n&&l===1?r=!1:($e(o,t),!n&&l===1&&delete o._):(r=!t.$stable,Qr(t,o)),i=t}else t&&(Jr(e,t),i={default:1});if(r)for(const l in o)!Yr(l)&&!(l in i)&&delete o[l]};function Xr(){return{app:null,config:{isNativeTag:Ti,performance:!1,globalProperties:{},optionMergeStrategies:{},errorHandler:void 0,warnHandler:void 0,compilerOptions:{}},mixins:[],components:{},directives:{},provides:Object.create(null),optionsCache:new WeakMap,propsCache:new WeakMap,emitsCache:new WeakMap}}let Jl=0;function Xl(e,t){return function(s,o=null){X(s)||(s=Object.assign({},s)),o!=null&&!ge(o)&&(o=null);const r=Xr(),i=new Set;let l=!1;const c=r.app={_uid:Jl++,_component:s,_props:o,_container:null,_context:r,_instance:null,version:mc,get config(){return r.config},set config(f){},use(f,...h){return i.has(f)||(f&&X(f.install)?(i.add(f),f.install(c,...h)):X(f)&&(i.add(f),f(c,...h))),c},mixin(f){return r.mixins.includes(f)||r.mixins.push(f),c},component(f,h){return h?(r.components[f]=h,c):r.components[f]},directive(f,h){return h?(r.directives[f]=h,c):r.directives[f]},mount(f,h,m){if(!l){const x=V(s,o);return x.appContext=r,h&&t?t(x,f):e(x,f,m),l=!0,c._container=f,f.__vue_app__=c,eo(x.component)||x.component.proxy}},unmount(){l&&(e(null,c._container),delete c._container.__vue_app__)},provide(f,h){return r.provides[f]=h,c}};return c}}function In(e,t,n,s,o=!1){if(K(e)){e.forEach((x,C)=>In(x,t&&(K(t)?t[C]:t),n,s,o));return}if(Bt(s)&&!o)return;const r=s.shapeFlag&4?eo(s.component)||s.component.proxy:s.el,i=o?null:r,{i:l,r:c}=e,f=t&&t.r,h=l.refs===ve?l.refs={}:l.refs,m=l.setupState;if(f!=null&&f!==c&&(we(f)?(h[f]=null,se(m,f)&&(m[f]=null)):ke(f)&&(f.value=null)),X(c))dt(c,l,12,[i,h]);else{const x=we(c),C=ke(c);if(x||C){const j=()=>{if(e.f){const F=x?h[c]:c.value;o?K(F)&&As(F,r):K(F)?F.includes(r)||F.push(r):x?(h[c]=[r],se(m,c)&&(m[c]=h[c])):(c.value=[r],e.k&&(h[e.k]=c.value))}else x?(h[c]=i,se(m,c)&&(m[c]=i)):C&&(c.value=i,e.k&&(h[e.k]=i))};i?(j.id=-1,Te(j,n)):j()}}}let lt=!1;const xn=e=>/svg/.test(e.namespaceURI)&&e.tagName!=="foreignObject",$n=e=>e.nodeType===8;function Zl(e){const{mt:t,p:n,o:{patchProp:s,createText:o,nextSibling:r,parentNode:i,remove:l,insert:c,createComment:f}}=e,h=(g,T)=>{if(!T.hasChildNodes()){n(null,g,T),Tn(),T._vnode=g;return}lt=!1,m(T.firstChild,g,null,null,null),Tn(),T._vnode=g,lt&&console.error("Hydration completed but contains mismatches.")},m=(g,T,z,G,ne,de=!1)=>{const oe=$n(g)&&g.data==="[",M=()=>F(g,T,z,G,ne,oe),{type:Z,ref:Y,shapeFlag:le,patchFlag:A}=T;let ee=g.nodeType;T.el=g,A===-2&&(de=!1,T.dynamicChildren=null);let H=null;switch(Z){case an:ee!==3?T.children===""?(c(T.el=o(""),i(g),g),H=g):H=M():(g.data!==T.children&&(lt=!0,g.data=T.children),H=r(g));break;case Ae:ee!==8||oe?H=M():H=r(g);break;case Ft:if(oe&&(g=r(g),ee=g.nodeType),ee===1||ee===3){H=g;const Le=!T.children.length;for(let ue=0;ue{de=de||!!T.dynamicChildren;const{type:oe,props:M,patchFlag:Z,shapeFlag:Y,dirs:le}=T,A=oe==="input"&&le||oe==="option";if(A||Z!==-1){if(le&&Qe(T,null,z,"created"),M)if(A||!de||Z&48)for(const H in M)(A&&H.endsWith("value")||hn(H)&&!Zt(H))&&s(g,H,null,M[H],!1,void 0,z);else M.onClick&&s(g,"onClick",null,M.onClick,!1,void 0,z);let ee;if((ee=M&&M.onVnodeBeforeMount)&&Fe(ee,z,T),le&&Qe(T,null,z,"beforeMount"),((ee=M&&M.onVnodeMounted)||le)&&Nr(()=>{ee&&Fe(ee,z,T),le&&Qe(T,null,z,"mounted")},G),Y&16&&!(M&&(M.innerHTML||M.textContent))){let H=C(g.firstChild,T,g,z,G,ne,de);for(;H;){lt=!0;const Le=H;H=H.nextSibling,l(Le)}}else Y&8&&g.textContent!==T.children&&(lt=!0,g.textContent=T.children)}return g.nextSibling},C=(g,T,z,G,ne,de,oe)=>{oe=oe||!!T.dynamicChildren;const M=T.children,Z=M.length;for(let Y=0;Y{const{slotScopeIds:oe}=T;oe&&(ne=ne?ne.concat(oe):oe);const M=i(g),Z=C(r(g),T,M,z,G,ne,de);return Z&&$n(Z)&&Z.data==="]"?r(T.anchor=Z):(lt=!0,c(T.anchor=f("]"),M,Z),Z)},F=(g,T,z,G,ne,de)=>{if(lt=!0,T.el=null,de){const Z=J(g);for(;;){const Y=r(g);if(Y&&Y!==Z)l(Y);else break}}const oe=r(g),M=i(g);return l(g),n(null,T,M,oe,z,G,xn(M),ne),oe},J=g=>{let T=0;for(;g;)if(g=r(g),g&&$n(g)&&(g.data==="["&&T++,g.data==="]")){if(T===0)return r(g);T--}return g};return[h,m]}const Te=Nr;function ec(e){return tc(e,Zl)}function tc(e,t){const n=Ni();n.__VUE__=!0;const{insert:s,remove:o,patchProp:r,createElement:i,createText:l,createComment:c,setText:f,setElementText:h,parentNode:m,nextSibling:x,setScopeId:C=Ke,insertStaticContent:j}=e,F=(a,u,p,w=null,y=null,k=null,L=!1,P=null,S=!!u.dynamicChildren)=>{if(a===u)return;a&&!Pt(a,u)&&(w=vn(a),Ge(a,y,k,!0),a=null),u.patchFlag===-2&&(S=!1,u.dynamicChildren=null);const{type:$,ref:D,shapeFlag:N}=u;switch($){case an:J(a,u,p,w);break;case Ae:g(a,u,p,w);break;case Ft:a==null&&T(u,p,w,L);break;case q:A(a,u,p,w,y,k,L,P,S);break;default:N&1?ne(a,u,p,w,y,k,L,P,S):N&6?ee(a,u,p,w,y,k,L,P,S):(N&64||N&128)&&$.process(a,u,p,w,y,k,L,P,S,Et)}D!=null&&y&&In(D,a&&a.ref,k,u||a,!u)},J=(a,u,p,w)=>{if(a==null)s(u.el=l(u.children),p,w);else{const y=u.el=a.el;u.children!==a.children&&f(y,u.children)}},g=(a,u,p,w)=>{a==null?s(u.el=c(u.children||""),p,w):u.el=a.el},T=(a,u,p,w)=>{[a.el,a.anchor]=j(a.children,u,p,w,a.el,a.anchor)},z=({el:a,anchor:u},p,w)=>{let y;for(;a&&a!==u;)y=x(a),s(a,p,w),a=y;s(u,p,w)},G=({el:a,anchor:u})=>{let p;for(;a&&a!==u;)p=x(a),o(a),a=p;o(u)},ne=(a,u,p,w,y,k,L,P,S)=>{L=L||u.type==="svg",a==null?de(u,p,w,y,k,L,P,S):Z(a,u,y,k,L,P,S)},de=(a,u,p,w,y,k,L,P)=>{let S,$;const{type:D,props:N,shapeFlag:R,transition:W,dirs:te}=a;if(S=a.el=i(a.type,k,N&&N.is,N),R&8?h(S,a.children):R&16&&M(a.children,S,null,w,y,k&&D!=="foreignObject",L,P),te&&Qe(a,null,w,"created"),N){for(const fe in N)fe!=="value"&&!Zt(fe)&&r(S,fe,null,N[fe],k,a.children,w,y,tt);"value"in N&&r(S,"value",null,N.value),($=N.onVnodeBeforeMount)&&Fe($,w,a)}oe(S,a,a.scopeId,L,w),te&&Qe(a,null,w,"beforeMount");const pe=(!y||y&&!y.pendingBranch)&&W&&!W.persisted;pe&&W.beforeEnter(S),s(S,u,p),(($=N&&N.onVnodeMounted)||pe||te)&&Te(()=>{$&&Fe($,w,a),pe&&W.enter(S),te&&Qe(a,null,w,"mounted")},y)},oe=(a,u,p,w,y)=>{if(p&&C(a,p),w)for(let k=0;k{for(let $=S;${const P=u.el=a.el;let{patchFlag:S,dynamicChildren:$,dirs:D}=u;S|=a.patchFlag&16;const N=a.props||ve,R=u.props||ve;let W;p&&bt(p,!1),(W=R.onVnodeBeforeUpdate)&&Fe(W,p,u,a),D&&Qe(u,a,p,"beforeUpdate"),p&&bt(p,!0);const te=y&&u.type!=="foreignObject";if($?Y(a.dynamicChildren,$,P,p,w,te,k):L||_e(a,u,P,null,p,w,te,k,!1),S>0){if(S&16)le(P,u,N,R,p,w,y);else if(S&2&&N.class!==R.class&&r(P,"class",null,R.class,y),S&4&&r(P,"style",N.style,R.style,y),S&8){const pe=u.dynamicProps;for(let fe=0;fe{W&&Fe(W,p,u,a),D&&Qe(u,a,p,"updated")},w)},Y=(a,u,p,w,y,k,L)=>{for(let P=0;P{if(p!==w){if(p!==ve)for(const P in p)!Zt(P)&&!(P in w)&&r(a,P,p[P],null,L,u.children,y,k,tt);for(const P in w){if(Zt(P))continue;const S=w[P],$=p[P];S!==$&&P!=="value"&&r(a,P,$,S,L,u.children,y,k,tt)}"value"in w&&r(a,"value",p.value,w.value)}},A=(a,u,p,w,y,k,L,P,S)=>{const $=u.el=a?a.el:l(""),D=u.anchor=a?a.anchor:l("");let{patchFlag:N,dynamicChildren:R,slotScopeIds:W}=u;W&&(P=P?P.concat(W):W),a==null?(s($,p,w),s(D,p,w),M(u.children,p,D,y,k,L,P,S)):N>0&&N&64&&R&&a.dynamicChildren?(Y(a.dynamicChildren,R,p,y,k,L,P),(u.key!=null||y&&u===y.subTree)&&Zr(a,u,!0)):_e(a,u,p,D,y,k,L,P,S)},ee=(a,u,p,w,y,k,L,P,S)=>{u.slotScopeIds=P,a==null?u.shapeFlag&512?y.ctx.activate(u,p,w,L,S):H(u,p,w,y,k,L,S):Le(a,u,S)},H=(a,u,p,w,y,k,L)=>{const P=a.component=uc(a,w,y);if(Xn(a)&&(P.ctx.renderer=Et),fc(P),P.asyncDep){if(y&&y.registerDep(P,ue),!a.el){const S=P.subTree=V(Ae);g(null,S,u,p)}return}ue(P,a,u,p,y,k,L)},Le=(a,u,p)=>{const w=u.component=a.component;if(kl(a,u,p))if(w.asyncDep&&!w.asyncResolved){be(w,u,p);return}else w.next=u,bl(w.update),w.update();else u.el=a.el,w.vnode=u},ue=(a,u,p,w,y,k,L)=>{const P=()=>{if(a.isMounted){let{next:D,bu:N,u:R,parent:W,vnode:te}=a,pe=D,fe;bt(a,!1),D?(D.el=te.el,be(a,D,L)):D=te,N&&cs(N),(fe=D.props&&D.props.onVnodeBeforeUpdate)&&Fe(fe,W,D,te),bt(a,!0);const ye=as(a),Re=a.subTree;a.subTree=ye,F(Re,ye,m(Re.el),vn(Re),a,y,k),D.el=ye.el,pe===null&&Cl(a,ye.el),R&&Te(R,y),(fe=D.props&&D.props.onVnodeUpdated)&&Te(()=>Fe(fe,W,D,te),y)}else{let D;const{el:N,props:R}=u,{bm:W,m:te,parent:pe}=a,fe=Bt(u);if(bt(a,!1),W&&cs(W),!fe&&(D=R&&R.onVnodeBeforeMount)&&Fe(D,pe,u),bt(a,!0),N&&is){const ye=()=>{a.subTree=as(a),is(N,a.subTree,a,y,null)};fe?u.type.__asyncLoader().then(()=>!a.isUnmounted&&ye()):ye()}else{const ye=a.subTree=as(a);F(null,ye,p,w,a,y,k),u.el=ye.el}if(te&&Te(te,y),!fe&&(D=R&&R.onVnodeMounted)){const ye=u;Te(()=>Fe(D,pe,ye),y)}(u.shapeFlag&256||pe&&Bt(pe.vnode)&&pe.vnode.shapeFlag&256)&&a.a&&Te(a.a,y),a.isMounted=!0,u=p=w=null}},S=a.effect=new Fs(P,()=>Ws($),a.scope),$=a.update=()=>S.run();$.id=a.uid,bt(a,!0),$()},be=(a,u,p)=>{u.component=a;const w=a.vnode.props;a.vnode=u,a.next=null,ql(a,u.props,w,p),Ql(a,u.children,p),Wt(),wo(),qt()},_e=(a,u,p,w,y,k,L,P,S=!1)=>{const $=a&&a.children,D=a?a.shapeFlag:0,N=u.children,{patchFlag:R,shapeFlag:W}=u;if(R>0){if(R&128){pn($,N,p,w,y,k,L,P,S);return}else if(R&256){mt($,N,p,w,y,k,L,P,S);return}}W&8?(D&16&&tt($,y,k),N!==$&&h(p,N)):D&16?W&16?pn($,N,p,w,y,k,L,P,S):tt($,y,k,!0):(D&8&&h(p,""),W&16&&M(N,p,w,y,k,L,P,S))},mt=(a,u,p,w,y,k,L,P,S)=>{a=a||It,u=u||It;const $=a.length,D=u.length,N=Math.min($,D);let R;for(R=0;RD?tt(a,y,k,!0,!1,N):M(u,p,w,y,k,L,P,S,N)},pn=(a,u,p,w,y,k,L,P,S)=>{let $=0;const D=u.length;let N=a.length-1,R=D-1;for(;$<=N&&$<=R;){const W=a[$],te=u[$]=S?ut(u[$]):Ue(u[$]);if(Pt(W,te))F(W,te,p,null,y,k,L,P,S);else break;$++}for(;$<=N&&$<=R;){const W=a[N],te=u[R]=S?ut(u[R]):Ue(u[R]);if(Pt(W,te))F(W,te,p,null,y,k,L,P,S);else break;N--,R--}if($>N){if($<=R){const W=R+1,te=WR)for(;$<=N;)Ge(a[$],y,k,!0),$++;else{const W=$,te=$,pe=new Map;for($=te;$<=R;$++){const Me=u[$]=S?ut(u[$]):Ue(u[$]);Me.key!=null&&pe.set(Me.key,$)}let fe,ye=0;const Re=R-te+1;let Lt=!1,ao=0;const Qt=new Array(Re);for($=0;$=Re){Ge(Me,y,k,!0);continue}let Ye;if(Me.key!=null)Ye=pe.get(Me.key);else for(fe=te;fe<=R;fe++)if(Qt[fe-te]===0&&Pt(Me,u[fe])){Ye=fe;break}Ye===void 0?Ge(Me,y,k,!0):(Qt[Ye-te]=$+1,Ye>=ao?ao=Ye:Lt=!0,F(Me,u[Ye],p,null,y,k,L,P,S),ye++)}const uo=Lt?nc(Qt):It;for(fe=uo.length-1,$=Re-1;$>=0;$--){const Me=te+$,Ye=u[Me],fo=Me+1{const{el:k,type:L,transition:P,children:S,shapeFlag:$}=a;if($&6){gt(a.component.subTree,u,p,w);return}if($&128){a.suspense.move(u,p,w);return}if($&64){L.move(a,u,p,Et);return}if(L===q){s(k,u,p);for(let N=0;NP.enter(k),y);else{const{leave:N,delayLeave:R,afterLeave:W}=P,te=()=>s(k,u,p),pe=()=>{N(k,()=>{te(),W&&W()})};R?R(k,te,pe):pe()}else s(k,u,p)},Ge=(a,u,p,w=!1,y=!1)=>{const{type:k,props:L,ref:P,children:S,dynamicChildren:$,shapeFlag:D,patchFlag:N,dirs:R}=a;if(P!=null&&In(P,null,p,a,!0),D&256){u.ctx.deactivate(a);return}const W=D&1&&R,te=!Bt(a);let pe;if(te&&(pe=L&&L.onVnodeBeforeUnmount)&&Fe(pe,u,a),D&6)$i(a.component,p,w);else{if(D&128){a.suspense.unmount(p,w);return}W&&Qe(a,null,u,"beforeUnmount"),D&64?a.type.remove(a,u,p,y,Et,w):$&&(k!==q||N>0&&N&64)?tt($,u,p,!1,!0):(k===q&&N&384||!y&&D&16)&&tt(S,u,p),w&&lo(a)}(te&&(pe=L&&L.onVnodeUnmounted)||W)&&Te(()=>{pe&&Fe(pe,u,a),W&&Qe(a,null,u,"unmounted")},p)},lo=a=>{const{type:u,el:p,anchor:w,transition:y}=a;if(u===q){xi(p,w);return}if(u===Ft){G(a);return}const k=()=>{o(p),y&&!y.persisted&&y.afterLeave&&y.afterLeave()};if(a.shapeFlag&1&&y&&!y.persisted){const{leave:L,delayLeave:P}=y,S=()=>L(p,k);P?P(a.el,k,S):S()}else k()},xi=(a,u)=>{let p;for(;a!==u;)p=x(a),o(a),a=p;o(u)},$i=(a,u,p)=>{const{bum:w,scope:y,update:k,subTree:L,um:P}=a;w&&cs(w),y.stop(),k&&(k.active=!1,Ge(L,a,u,p)),P&&Te(P,u),Te(()=>{a.isUnmounted=!0},u),u&&u.pendingBranch&&!u.isUnmounted&&a.asyncDep&&!a.asyncResolved&&a.suspenseId===u.pendingId&&(u.deps--,u.deps===0&&u.resolve())},tt=(a,u,p,w=!1,y=!1,k=0)=>{for(let L=k;La.shapeFlag&6?vn(a.component.subTree):a.shapeFlag&128?a.suspense.next():x(a.anchor||a.el),co=(a,u,p)=>{a==null?u._vnode&&Ge(u._vnode,null,null,!0):F(u._vnode||null,a,u,null,null,null,p),wo(),Tn(),u._vnode=a},Et={p:F,um:Ge,m:gt,r:lo,mt:H,mc:M,pc:_e,pbc:Y,n:vn,o:e};let rs,is;return t&&([rs,is]=t(Et)),{render:co,hydrate:rs,createApp:Xl(co,rs)}}function bt({effect:e,update:t},n){e.allowRecurse=t.allowRecurse=n}function Zr(e,t,n=!1){const s=e.children,o=t.children;if(K(s)&&K(o))for(let r=0;r>1,e[n[l]]0&&(t[s]=n[r-1]),n[r]=s)}}for(r=n.length,i=n[r-1];r-- >0;)n[r]=i,i=t[i];return n}const sc=e=>e.__isTeleport,q=Symbol(void 0),an=Symbol(void 0),Ae=Symbol(void 0),Ft=Symbol(void 0),tn=[];let ze=null;function d(e=!1){tn.push(ze=e?null:[])}function oc(){tn.pop(),ze=tn[tn.length-1]||null}let un=1;function Mo(e){un+=e}function ei(e){return e.dynamicChildren=un>0?ze||It:null,oc(),un>0&&ze&&ze.push(e),e}function v(e,t,n,s,o,r){return ei(b(e,t,n,s,o,r,!0))}function Q(e,t,n,s,o){return ei(V(e,t,n,s,o,!0))}function An(e){return e?e.__v_isVNode===!0:!1}function Pt(e,t){return e.type===t.type&&e.key===t.key}const es="__vInternal",ti=({key:e})=>e!=null?e:null,kn=({ref:e,ref_key:t,ref_for:n})=>e!=null?we(e)||ke(e)||X(e)?{i:Ve,r:e,k:t,f:!!n}:e:null;function b(e,t=null,n=null,s=0,o=null,r=e===q?0:1,i=!1,l=!1){const c={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&ti(t),ref:t&&kn(t),scopeId:Yn,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetAnchor:null,staticCount:0,shapeFlag:r,patchFlag:s,dynamicProps:o,dynamicChildren:null,appContext:null};return l?(Xs(c,n),r&128&&e.normalize(c)):n&&(c.shapeFlag|=we(n)?8:16),un>0&&!i&&ze&&(c.patchFlag>0||r&6)&&c.patchFlag!==32&&ze.push(c),c}const V=rc;function rc(e,t=null,n=null,s=0,o=null,r=!1){if((!e||e===jr)&&(e=Ae),An(e)){const l=_t(e,t,!0);return n&&Xs(l,n),un>0&&!r&&ze&&(l.shapeFlag&6?ze[ze.indexOf(e)]=l:ze.push(l)),l.patchFlag|=-2,l}if(vc(e)&&(e=e.__vccOpts),t){t=ic(t);let{class:l,style:c}=t;l&&!we(l)&&(t.class=he(l)),ge(c)&&(kr(c)&&!K(c)&&(c=$e({},c)),t.style=Dn(c))}const i=we(e)?1:Sl(e)?128:sc(e)?64:ge(e)?4:X(e)?2:0;return b(e,t,n,s,o,i,r,!0)}function ic(e){return e?kr(e)||es in e?$e({},e):e:null}function _t(e,t,n=!1){const{props:s,ref:o,patchFlag:r,children:i}=e,l=t?Cn(s||{},t):s;return{__v_isVNode:!0,__v_skip:!0,type:e.type,props:l,key:l&&ti(l),ref:t&&t.ref?n&&o?K(o)?o.concat(kn(t)):[o,kn(t)]:kn(t):o,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:i,target:e.target,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==q?r===-1?16:r|16:r,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:e.transition,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&_t(e.ssContent),ssFallback:e.ssFallback&&_t(e.ssFallback),el:e.el,anchor:e.anchor}}function Oe(e=" ",t=0){return V(an,null,e,t)}function lc(e,t){const n=V(Ft,null,e);return n.staticCount=t,n}function U(e="",t=!1){return t?(d(),Q(Ae,null,e)):V(Ae,null,e)}function Ue(e){return e==null||typeof e=="boolean"?V(Ae):K(e)?V(q,null,e.slice()):typeof e=="object"?ut(e):V(an,null,String(e))}function ut(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:_t(e)}function Xs(e,t){let n=0;const{shapeFlag:s}=e;if(t==null)t=null;else if(K(t))n=16;else if(typeof t=="object")if(s&65){const o=t.default;o&&(o._c&&(o._d=!1),Xs(e,o()),o._c&&(o._d=!0));return}else{n=32;const o=t._;!o&&!(es in t)?t._ctx=Ve:o===3&&Ve&&(Ve.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else X(t)?(t={default:t,_ctx:Ve},n=32):(t=String(t),s&64?(n=16,t=[Oe(t)]):n=8);e.children=t,e.shapeFlag|=n}function Cn(...e){const t={};for(let n=0;nxe||Ve,jt=e=>{xe=e,e.scope.on()},Vt=()=>{xe&&xe.scope.off(),xe=null};function ni(e){return e.vnode.shapeFlag&4}let fn=!1;function fc(e,t=!1){fn=t;const{props:n,children:s}=e.vnode,o=ni(e);Wl(e,n,o,t),Yl(e,s);const r=o?dc(e,t):void 0;return fn=!1,r}function dc(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=en(new Proxy(e.ctx,Dl));const{setup:s}=n;if(s){const o=e.setupContext=s.length>1?_c(e):null;jt(e),Wt();const r=dt(s,e,0,[e.props,o]);if(qt(),Vt(),fr(r)){if(r.then(Vt,Vt),t)return r.then(i=>{Io(e,i,t)}).catch(i=>{Wn(i,e,0)});e.asyncDep=r}else Io(e,r,t)}else si(e,t)}function Io(e,t,n){X(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:ge(t)&&(e.setupState=Tr(t)),si(e,n)}let Ao;function si(e,t,n){const s=e.type;if(!e.render){if(!t&&Ao&&!s.render){const o=s.template||Qs(e).template;if(o){const{isCustomElement:r,compilerOptions:i}=e.appContext.config,{delimiters:l,compilerOptions:c}=s,f=$e($e({isCustomElement:r,delimiters:l},i),c);s.render=Ao(o,f)}}e.render=s.render||Ke}jt(e),Wt(),Rl(e),qt(),Vt()}function hc(e){return new Proxy(e.attrs,{get(t,n){return Ne(e,"get","$attrs"),t[n]}})}function _c(e){const t=s=>{e.exposed=s||{}};let n;return{get attrs(){return n||(n=hc(e))},slots:e.slots,emit:e.emit,expose:t}}function eo(e){if(e.exposed)return e.exposeProxy||(e.exposeProxy=new Proxy(Tr(en(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in Ln)return Ln[n](e)}}))}function pc(e,t=!0){return X(e)?e.displayName||e.name:e.name||t&&e.__name}function vc(e){return X(e)&&"__vccOpts"in e}const re=(e,t)=>vl(e,t,fn);function Nn(e,t,n){const s=arguments.length;return s===2?ge(t)&&!K(t)?An(t)?V(e,null,[t]):V(e,t):V(e,null,t):(s>3?n=Array.prototype.slice.call(arguments,2):s===3&&An(n)&&(n=[n]),V(e,t,n))}const mc="3.2.40",gc="http://www.w3.org/2000/svg",kt=typeof document<"u"?document:null,No=kt&&kt.createElement("template"),bc={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,s)=>{const o=t?kt.createElementNS(gc,e):kt.createElement(e,n?{is:n}:void 0);return e==="select"&&s&&s.multiple!=null&&o.setAttribute("multiple",s.multiple),o},createText:e=>kt.createTextNode(e),createComment:e=>kt.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>kt.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,s,o,r){const i=n?n.previousSibling:t.lastChild;if(o&&(o===r||o.nextSibling))for(;t.insertBefore(o.cloneNode(!0),n),!(o===r||!(o=o.nextSibling)););else{No.innerHTML=s?`${e}`:e;const l=No.content;if(s){const c=l.firstChild;for(;c.firstChild;)l.appendChild(c.firstChild);l.removeChild(c)}t.insertBefore(l,n)}return[i?i.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}};function yc(e,t,n){const s=e._vtc;s&&(t=(t?[t,...s]:[...s]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}function wc(e,t,n){const s=e.style,o=we(n);if(n&&!o){for(const r in n)Ss(s,r,n[r]);if(t&&!we(t))for(const r in t)n[r]==null&&Ss(s,r,"")}else{const r=s.display;o?t!==n&&(s.cssText=n):t&&e.removeAttribute("style"),"_vod"in e&&(s.display=r)}}const Oo=/\s*!important$/;function Ss(e,t,n){if(K(n))n.forEach(s=>Ss(e,t,s));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const s=xc(e,t);Oo.test(n)?e.setProperty(Kt(s),n.replace(Oo,""),"important"):e[s]=n}}const Bo=["Webkit","Moz","ms"],fs={};function xc(e,t){const n=fs[t];if(n)return n;let s=Ze(t);if(s!=="filter"&&s in e)return fs[t]=s;s=jn(s);for(let o=0;o{let e=Date.now,t=!1;if(typeof window<"u"){Date.now()>document.createEvent("Event").timeStamp&&(e=performance.now.bind(performance));const n=navigator.userAgent.match(/firefox\/(\d+)/i);t=!!(n&&Number(n[1])<=53)}return[e,t]})();let Vs=0;const Cc=Promise.resolve(),Sc=()=>{Vs=0},Vc=()=>Vs||(Cc.then(Sc),Vs=oi());function Tc(e,t,n,s){e.addEventListener(t,n,s)}function Ec(e,t,n,s){e.removeEventListener(t,n,s)}function Lc(e,t,n,s,o=null){const r=e._vei||(e._vei={}),i=r[t];if(s&&i)i.value=s;else{const[l,c]=Mc(t);if(s){const f=r[t]=Ic(s,o);Tc(e,l,f,c)}else i&&(Ec(e,l,i,c),r[t]=void 0)}}const Ho=/(?:Once|Passive|Capture)$/;function Mc(e){let t;if(Ho.test(e)){t={};let s;for(;s=e.match(Ho);)e=e.slice(0,e.length-s[0].length),t[s[0].toLowerCase()]=!0}return[e[2]===":"?e.slice(3):Kt(e.slice(2)),t]}function Ic(e,t){const n=s=>{const o=s.timeStamp||oi();(kc||o>=n.attached-1)&&He(Ac(s,n.value),t,5,[s])};return n.value=e,n.attached=Vc(),n}function Ac(e,t){if(K(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(s=>o=>!o._stopped&&s&&s(o))}else return t}const Do=/^on[a-z]/,Nc=(e,t,n,s,o=!1,r,i,l,c)=>{t==="class"?yc(e,s,o):t==="style"?wc(e,n,s):hn(t)?Is(t)||Lc(e,t,n,s,i):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):Oc(e,t,s,o))?Pc(e,t,s,r,i,l,c):(t==="true-value"?e._trueValue=s:t==="false-value"&&(e._falseValue=s),$c(e,t,s,o))};function Oc(e,t,n,s){return s?!!(t==="innerHTML"||t==="textContent"||t in e&&Do.test(t)&&X(n)):t==="spellcheck"||t==="draggable"||t==="translate"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA"||Do.test(t)&&we(n)?!1:t in e}function Bc(e){const t=Zs();if(!t)return;const n=()=>Ts(t.subTree,e(t.proxy));Or(n),De(()=>{const s=new MutationObserver(n);s.observe(t.subTree.el.parentNode,{childList:!0}),pt(()=>s.disconnect())})}function Ts(e,t){if(e.shapeFlag&128){const n=e.suspense;e=n.activeBranch,n.pendingBranch&&!n.isHydrating&&n.effects.push(()=>{Ts(n.activeBranch,t)})}for(;e.component;)e=e.component.subTree;if(e.shapeFlag&1&&e.el)Ro(e.el,t);else if(e.type===q)e.children.forEach(n=>Ts(n,t));else if(e.type===Ft){let{el:n,anchor:s}=e;for(;n&&(Ro(n,t),n!==s);)n=n.nextSibling}}function Ro(e,t){if(e.nodeType===1){const n=e.style;for(const s in t)n.setProperty(`--${s}`,t[s])}}const ct="transition",Jt="animation",ts=(e,{slots:t})=>Nn(Fr,Fc(e),t);ts.displayName="Transition";const ri={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String};ts.props=$e({},Fr.props,ri);const yt=(e,t=[])=>{K(e)?e.forEach(n=>n(...t)):e&&e(...t)},Uo=e=>e?K(e)?e.some(t=>t.length>1):e.length>1:!1;function Fc(e){const t={};for(const A in e)A in ri||(t[A]=e[A]);if(e.css===!1)return t;const{name:n="v",type:s,duration:o,enterFromClass:r=`${n}-enter-from`,enterActiveClass:i=`${n}-enter-active`,enterToClass:l=`${n}-enter-to`,appearFromClass:c=r,appearActiveClass:f=i,appearToClass:h=l,leaveFromClass:m=`${n}-leave-from`,leaveActiveClass:x=`${n}-leave-active`,leaveToClass:C=`${n}-leave-to`}=e,j=Hc(o),F=j&&j[0],J=j&&j[1],{onBeforeEnter:g,onEnter:T,onEnterCancelled:z,onLeave:G,onLeaveCancelled:ne,onBeforeAppear:de=g,onAppear:oe=T,onAppearCancelled:M=z}=t,Z=(A,ee,H)=>{wt(A,ee?h:l),wt(A,ee?f:i),H&&H()},Y=(A,ee)=>{A._isLeaving=!1,wt(A,m),wt(A,C),wt(A,x),ee&&ee()},le=A=>(ee,H)=>{const Le=A?oe:T,ue=()=>Z(ee,A,H);yt(Le,[ee,ue]),jo(()=>{wt(ee,A?c:r),at(ee,A?h:l),Uo(Le)||zo(ee,s,F,ue)})};return $e(t,{onBeforeEnter(A){yt(g,[A]),at(A,r),at(A,i)},onBeforeAppear(A){yt(de,[A]),at(A,c),at(A,f)},onEnter:le(!1),onAppear:le(!0),onLeave(A,ee){A._isLeaving=!0;const H=()=>Y(A,ee);at(A,m),Uc(),at(A,x),jo(()=>{!A._isLeaving||(wt(A,m),at(A,C),Uo(G)||zo(A,s,J,H))}),yt(G,[A,H])},onEnterCancelled(A){Z(A,!1),yt(z,[A])},onAppearCancelled(A){Z(A,!0),yt(M,[A])},onLeaveCancelled(A){Y(A),yt(ne,[A])}})}function Hc(e){if(e==null)return null;if(ge(e))return[ds(e.enter),ds(e.leave)];{const t=ds(e);return[t,t]}}function ds(e){return _r(e)}function at(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.add(n)),(e._vtc||(e._vtc=new Set)).add(t)}function wt(e,t){t.split(/\s+/).forEach(s=>s&&e.classList.remove(s));const{_vtc:n}=e;n&&(n.delete(t),n.size||(e._vtc=void 0))}function jo(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let Dc=0;function zo(e,t,n,s){const o=e._endId=++Dc,r=()=>{o===e._endId&&s()};if(n)return setTimeout(r,n);const{type:i,timeout:l,propCount:c}=Rc(e,t);if(!i)return s();const f=i+"end";let h=0;const m=()=>{e.removeEventListener(f,x),r()},x=C=>{C.target===e&&++h>=c&&m()};setTimeout(()=>{h(n[j]||"").split(", "),o=s(ct+"Delay"),r=s(ct+"Duration"),i=Ko(o,r),l=s(Jt+"Delay"),c=s(Jt+"Duration"),f=Ko(l,c);let h=null,m=0,x=0;t===ct?i>0&&(h=ct,m=i,x=r.length):t===Jt?f>0&&(h=Jt,m=f,x=c.length):(m=Math.max(i,f),h=m>0?i>f?ct:Jt:null,x=h?h===ct?r.length:c.length:0);const C=h===ct&&/\b(transform|all)(,|$)/.test(n[ct+"Property"]);return{type:h,timeout:m,propCount:x,hasTransform:C}}function Ko(e,t){for(;e.lengthWo(n)+Wo(e[s])))}function Wo(e){return Number(e.slice(0,-1).replace(",","."))*1e3}function Uc(){return document.body.offsetHeight}const jc=["ctrl","shift","alt","meta"],zc={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>jc.some(n=>e[`${n}Key`]&&!t.includes(n))},Kc=(e,t)=>(n,...s)=>{for(let o=0;o{const t=qc().createApp(...e),{mount:n}=t;return t.mount=s=>{const o=Yc(s);if(o)return n(o,!0,o instanceof SVGElement)},t};function Yc(e){return we(e)?document.querySelector(e):e}const O=(e,t)=>{const n=e.__vccOpts||e;for(const[s,o]of t)n[s]=o;return n},Qc="modulepreload",Jc=function(e){return"/"+e},Go={},Xc=function(t,n,s){return!n||n.length===0?t():Promise.all(n.map(o=>{if(o=Jc(o),o in Go)return;Go[o]=!0;const r=o.endsWith(".css"),i=r?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${o}"]${i}`))return;const l=document.createElement("link");if(l.rel=r?"stylesheet":Qc,r||(l.as="script",l.crossOrigin=""),l.href=o,document.head.appendChild(l),r)return new Promise((c,f)=>{l.addEventListener("load",c),l.addEventListener("error",()=>f(new Error(`Unable to preload CSS for ${o}`)))})})).then(()=>t())};const Zc=JSON.parse('{"lang":"en-US","title":"The Paper Pilot","description":"The Paper Pilot portfolio site","base":"/","head":[],"appearance":true,"themeConfig":{"outline":"deep","nav":[{"text":"Guide to Incrementals","link":"/guide-to-incrementals/","activeMatch":"^/guide-to-incrementals"},{"text":"Projects","link":"/projects/","activeMatch":"^/projects"},{"text":"Profectus","link":"https://moddingtree.com"}],"socialLinks":[{"icon":"github","link":"https://github.com/thepaperpilot"},{"icon":"linkedin","link":"https://www.linkedin.com/pub/anthony-lawn/a9/a98/2"},{"icon":"discord","link":"https://discord.gg/F3xveHV"}],"sidebar":{"guide-to-incrementals":[{"text":"Ludology","collapsible":true,"items":[{"text":"Defining the Genre","link":"/guide-to-incrementals/ludology/definition"},{"text":"Appeal to Players","link":"/guide-to-incrementals/ludology/appeal-games"},{"text":"Appeal to Developers","link":"/guide-to-incrementals/ludology/appeal-developers"},{"text":"What is Content?","link":"/guide-to-incrementals/ludology/content"}]}],"projects":[{"text":"Play Now","items":[{"text":"Kronos","link":"https://thepaperpilot.org/kronos/"},{"text":"Game Dev Tree","link":"https://thepaperpilot.org/gamedevtree/"},{"text":"Lit","link":"https://thepaperpilot.org/lit/"},{"text":"The Ascension Tree","link":"https://thepaperpilot.org/the_ascension_tree/"},{"text":"Dream Hero","link":"https://thepaperpilot.org/dream/"},{"text":"My Itch Page","link":"https://thepaperpilot.itch.io/"}]},{"text":"Downloads","items":[{"text":"Dice Armor","link":"/projects/dice/"},{"text":"Capture the Citadel","link":"/projects/citadel/"}]},{"text":"Non-Games","items":[{"text":"V-ecs","link":"/projects/vecs/"},{"text":"OptiSpeech","link":"/projects/optispeech/"},{"text":"Babble Buds","link":"/projects/babble/"}]}]}},"locales":{},"langs":{},"scrollOffset":90,"cleanUrls":"with-subfolders"}'),ns=/^[a-z]+:/i,Yo="vitepress-theme-appearance",Ee=typeof window<"u",ii={relativePath:"",title:"404",description:"Not Found",headers:[],frontmatter:{sidebar:!1,layout:"page"},lastUpdated:0};function ea(e,t){t.sort((n,s)=>{const o=s.split("/").length-n.split("/").length;return o!==0?o:s.length-n.length});for(const n of t)if(e.startsWith(n))return n}function Qo(e,t){const n=ea(t,Object.keys(e));return n?e[n]:void 0}function ta(e){const{locales:t}=e.themeConfig||{},n=e.locales;return t&&n?Object.keys(t).reduce((s,o)=>(s[o]={label:t[o].label,lang:n[o].lang},s),{}):{}}function na(e,t){t=oa(e,t);const n=Qo(e.locales||{},t),s=Qo(e.themeConfig.locales||{},t);return Object.assign({},e,n,{themeConfig:Object.assign({},e.themeConfig,s,{locales:{}}),lang:(n||e).lang,locales:{},langs:ta(e)})}function li(e,t){var r;const n=t.title||e.title,s=(r=t.titleTemplate)!=null?r:e.titleTemplate;if(typeof s=="string"&&s.includes(":title"))return s.replace(/:title/g,n);const o=sa(e.title,s);return`${n}${o}`}function sa(e,t){return t===!1?"":t===!0||t===void 0?` | ${e}`:e===t?"":` | ${t}`}function oa(e,t){if(!Ee)return t;const n=e.base,s=n.endsWith("/")?n.slice(0,-1):n;return t.slice(s.length)}function ra(e,t){const[n,s]=t;if(n!=="meta")return!1;const o=Object.entries(s)[0];return o==null?!1:e.some(([r,i])=>r===n&&i[o[0]]===o[1])}function ia(e,t){return[...e.filter(n=>!ra(t,n)),...t]}function la(e,t){return`${e}${t}`.replace(/\/+/g,"/")}function dn(e){return ns.test(e)?e:la(zt.value.base,e)}function ci(e){let t=e.replace(/\.html$/,"");if(t=decodeURIComponent(t),t.endsWith("/")&&(t+="index"),Ee){const n="/";t=(t.slice(n.length).replace(/\//g,"_")||"index")+".md";const s=__VP_HASH_MAP__[t.toLowerCase()];t=`${n}assets/${t}.${s}.js`}else t=`./${t.slice(1).replace(/\//g,"_")}.md.js`;return t}const ai=Symbol(),zt=dl(Zc);function ca(e){const t=re(()=>na(zt.value,e.path));return{site:t,theme:re(()=>t.value.themeConfig),page:re(()=>e.data),frontmatter:re(()=>e.data.frontmatter),lang:re(()=>t.value.lang),localePath:re(()=>{const{langs:n,lang:s}=t.value,o=Object.keys(n).find(r=>n[r].lang===s);return dn(o||"/")}),title:re(()=>li(t.value,e.data)),description:re(()=>e.data.description||t.value.description)}}function ae(){const e=Xe(ai);if(!e)throw new Error("vitepress data not properly injected in app");return e}const ui=Symbol(),Jo="http://a.com",aa=()=>({path:"/",component:null,data:ii});function ua(e,t){const n=Kn(aa()),s={route:n,go:o};async function o(l=Ee?location.href:"/"){var f,h;await((f=s.onBeforeRouteChange)==null?void 0:f.call(s,l));const c=new URL(l,Jo);zt.value.cleanUrls==="disabled"&&!c.pathname.endsWith("/")&&!c.pathname.endsWith(".html")&&(c.pathname+=".html",l=c.pathname+c.search+c.hash),Ee&&(history.replaceState({scrollPosition:window.scrollY},document.title),history.pushState(null,"",l)),await i(l),await((h=s.onAfterRouteChanged)==null?void 0:h.call(s,l))}let r=null;async function i(l,c=0,f=!1){const h=new URL(l,Jo),m=r=h.pathname;try{let x=await e(m);if(r===m){r=null;const{default:C,__pageData:j}=x;if(!C)throw new Error(`Invalid route component: ${C}`);n.path=Ee?m:dn(m),n.component=en(C),n.data=en(j),Ee&&qn(()=>{if(h.hash&&!c){let F=null;try{F=document.querySelector(decodeURIComponent(h.hash))}catch(J){console.warn(J)}if(F){Xo(F,h.hash);return}}window.scrollTo(0,c)})}}catch(x){if(!/fetch/.test(x.message)&&!/^\/404(\.html|\/)?$/.test(l)&&console.error(x),!f)try{const C=await fetch(zt.value.base+"hashmap.json");window.__VP_HASH_MAP__=await C.json(),await i(l,c,!0);return}catch{}r===m&&(r=null,n.path=Ee?m:dn(m),n.component=t?en(t):null,n.data=ii)}}return Ee&&(window.addEventListener("click",l=>{if(l.target.closest("button"))return;const f=l.target.closest("a");if(f&&!f.closest(".vp-raw")){const{href:h,origin:m,pathname:x,hash:C,search:j,target:F}=f,J=window.location,g=x.match(/\.\w+$/);!l.ctrlKey&&!l.shiftKey&&!l.altKey&&!l.metaKey&&F!=="_blank"&&m===J.origin&&!(g&&g[0]!==".html")&&(l.preventDefault(),x===J.pathname&&j===J.search?C&&C!==J.hash&&(history.pushState(null,"",C),window.dispatchEvent(new Event("hashchange")),Xo(f,C,f.classList.contains("header-anchor"))):o(h))}},{capture:!0}),window.addEventListener("popstate",l=>{i(location.href,l.state&&l.state.scrollPosition||0)}),window.addEventListener("hashchange",l=>{l.preventDefault()})),s}function fa(){const e=Xe(ui);if(!e)throw new Error("useRouter() is called without provider.");return e}function vt(){return fa().route}function Xo(e,t,n=!1){let s=null;try{s=e.classList.contains("header-anchor")?e:document.querySelector(decodeURIComponent(t))}catch(o){console.warn(o)}if(s){let o=zt.value.scrollOffset;typeof o=="string"&&(o=document.querySelector(o).getBoundingClientRect().bottom+24);const r=parseInt(window.getComputedStyle(s).paddingTop,10),i=window.scrollY+s.getBoundingClientRect().top-o+r;!n||Math.abs(i-window.scrollY)>window.innerHeight?window.scrollTo(0,i):window.scrollTo({left:0,top:i,behavior:"smooth"})}}const da=B({name:"VitePressContent",props:{onContentUpdated:Function},setup(e){const t=vt();return qs(()=>{var n;(n=e.onContentUpdated)==null||n.call(e)}),()=>Nn("div",{style:{position:"relative"}},[t.component?Nn(t.component):null])}}),fi=/#.*$/,ha=/(index)?\.(md|html)$/,_a=typeof window<"u",pa=me(_a?location.hash:"");function va(e){return ns.test(e)}function ma(e,t){let n,s=!1;return()=>{n&&clearTimeout(n),s?n=setTimeout(e,t):(e(),s=!0,setTimeout(()=>{s=!1},t))}}function Gt(e,t,n=!1){if(t===void 0)return!1;if(e=er(`/${e}`),n)return new RegExp(t).test(e);if(er(t)!==e)return!1;const s=t.match(fi);return s?pa.value===s[0]:!0}function Zo(e){return/^\//.test(e)?e:`/${e}`}function er(e){return decodeURI(e).replace(fi,"").replace(ha,"")}function On(e){if(va(e))return e;const{site:t}=ae(),{pathname:n,search:s,hash:o}=new URL(e,"http://example.com"),r=n.endsWith("/")||n.endsWith(".html")?e:`${n.replace(/(\.md)?$/,t.value.cleanUrls==="disabled"?".html":"")}${s}${o}`;return dn(r)}function di(e,t){if(Array.isArray(e))return e;t=Zo(t);for(const n in e)if(t.startsWith(Zo(n)))return e[n];return[]}function ga(e){const t=[];function n(s){for(const o of s)o.link&&t.push({...o,link:o.link}),"items"in o&&n(o.items)}for(const s of e)n(s.items);return t}function et(){const e=vt(),{theme:t,frontmatter:n}=ae(),s=me(!1),o=re(()=>{const h=t.value.sidebar,m=e.data.relativePath;return h?di(h,m):[]}),r=re(()=>n.value.sidebar!==!1&&o.value.length>0&&n.value.layout!=="home"),i=re(()=>n.value.layout!=="home"&&n.value.aside!==!1);function l(){s.value=!0}function c(){s.value=!1}function f(){s.value?c():l()}return{isOpen:s,sidebar:o,hasSidebar:r,hasAside:i,open:l,close:c,toggle:f}}function ba(e,t){let n;Ut(()=>{n=e.value?document.activeElement:void 0}),De(()=>{window.addEventListener("keyup",s)}),pt(()=>{window.removeEventListener("keyup",s)});function s(o){o.key==="Escape"&&e.value&&(t(),n==null||n.focus())}}const ya=B({__name:"VPSkipLink",setup(e){const t=vt(),n=me();st(()=>t.path,()=>n.value.focus());function s({target:o}){const r=document.querySelector(o.hash);if(r){const i=()=>{r.removeAttribute("tabindex"),r.removeEventListener("blur",i)};r.setAttribute("tabindex","-1"),r.addEventListener("blur",i),r.focus(),window.scrollTo(0,0)}}return(o,r)=>(d(),v(q,null,[b("span",{ref_key:"backToTop",ref:n,tabindex:"-1"},null,512),b("a",{href:"#VPContent",class:"VPSkipLink visually-hidden",onClick:s}," Skip to content ")],64))}});const wa=O(ya,[["__scopeId","data-v-151f2593"]]),xa={key:0,class:"VPBackdrop"},$a=B({__name:"VPBackdrop",props:{show:{type:Boolean}},setup(e){return(t,n)=>(d(),Q(ts,{name:"fade"},{default:I(()=>[e.show?(d(),v("div",xa)):U("",!0)]),_:1}))}});const Pa=O($a,[["__scopeId","data-v-0164f098"]]);function ka(){const e=me(!1);function t(){e.value=!0,window.addEventListener("resize",o)}function n(){e.value=!1,window.removeEventListener("resize",o)}function s(){e.value?n():t()}function o(){window.outerWidth>=768&&n()}const r=vt();return st(()=>r.path,n),{isScreenOpen:e,openScreen:t,closeScreen:n,toggleScreen:s}}const Ca=["src","alt"],Sa={inheritAttrs:!1},Va=B({...Sa,__name:"VPImage",props:{image:null},setup(e){return(t,n)=>{const s=Tt("VPImage",!0);return e.image?(d(),v(q,{key:0},[typeof e.image=="string"||"src"in e.image?(d(),v("img",Cn({key:0,class:"VPImage"},typeof e.image=="string"?t.$attrs:{...e.image,...t.$attrs},{src:_(dn)(typeof e.image=="string"?e.image:e.image.src),alt:typeof e.image=="string"?"":e.image.alt||""}),null,16,Ca)):(d(),v(q,{key:1},[V(s,Cn({class:"dark",image:e.image.dark},t.$attrs),null,16,["image"]),V(s,Cn({class:"light",image:e.image.light},t.$attrs),null,16,["image"])],64))],64)):U("",!0)}}});const hi=O(Va,[["__scopeId","data-v-8e4dd84f"]]),Ta=["href"],Ea=B({__name:"VPNavBarTitle",setup(e){const{site:t,theme:n}=ae(),{hasSidebar:s}=et();return(o,r)=>(d(),v("div",{class:he(["VPNavBarTitle",{"has-sidebar":_(s)}])},[b("a",{class:"title",href:_(t).base},[E(o.$slots,"nav-bar-title-before",{},void 0,!0),V(hi,{class:"logo",image:_(n).logo},null,8,["image"]),_(n).siteTitle?(d(),v(q,{key:0},[Oe(ie(_(n).siteTitle),1)],64)):_(n).siteTitle===void 0?(d(),v(q,{key:1},[Oe(ie(_(t).title),1)],64)):U("",!0),E(o.$slots,"nav-bar-title-after",{},void 0,!0)],8,Ta)],2))}});const La=O(Ea,[["__scopeId","data-v-d5925166"]]);const Ma={key:0,class:"VPNavBarSearch"},Ia={type:"button",class:"DocSearch DocSearch-Button","aria-label":"Search"},Aa={class:"DocSearch-Button-Container"},Na=b("svg",{class:"DocSearch-Search-Icon",width:"20",height:"20",viewBox:"0 0 20 20"},[b("path",{d:"M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z",stroke:"currentColor",fill:"none","fill-rule":"evenodd","stroke-linecap":"round","stroke-linejoin":"round"})],-1),Oa={class:"DocSearch-Button-Placeholder"},Ba=b("span",{class:"DocSearch-Button-Keys"},[b("kbd",{class:"DocSearch-Button-Key"}),b("kbd",{class:"DocSearch-Button-Key"},"K")],-1),Fa=B({__name:"VPNavBarSearch",setup(e){Bc(i=>({"5943dbe8":o.value}));const t=()=>null,{theme:n}=ae(),s=me(!1),o=me("'Meta'");De(()=>{if(!n.value.algolia)return;o.value=/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)?"'\u2318'":"'Ctrl'";const i=c=>{c.key==="k"&&(c.ctrlKey||c.metaKey)&&(c.preventDefault(),r(),l())},l=()=>{window.removeEventListener("keydown",i)};window.addEventListener("keydown",i),pt(l)});function r(){s.value||(s.value=!0)}return(i,l)=>{var c;return _(n).algolia?(d(),v("div",Ma,[s.value?(d(),Q(_(t),{key:0})):(d(),v("div",{key:1,id:"docsearch",onClick:r},[b("button",Ia,[b("span",Aa,[Na,b("span",Oa,ie(((c=_(n).algolia)==null?void 0:c.buttonText)||"Search"),1)]),Ba])]))])):U("",!0)}}});const Ha={},Da={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",height:"24px",viewBox:"0 0 24 24",width:"24px"},Ra=b("path",{d:"M0 0h24v24H0V0z",fill:"none"},null,-1),Ua=b("path",{d:"M9 5v2h6.59L4 18.59 5.41 20 17 8.41V15h2V5H9z"},null,-1),ja=[Ra,Ua];function za(e,t){return d(),v("svg",Da,ja)}const Ka=O(Ha,[["render",za]]),Wa=B({__name:"VPLink",props:{href:null,noIcon:{type:Boolean}},setup(e){const t=e,n=re(()=>t.href&&ns.test(t.href));return(s,o)=>(d(),Q(Ys(e.href?"a":"span"),{class:he(["VPLink",{link:e.href}]),href:e.href?_(On)(e.href):void 0,target:_(n)?"_blank":void 0,rel:_(n)?"noreferrer":void 0},{default:I(()=>[E(s.$slots,"default",{},void 0,!0),_(n)&&!e.noIcon?(d(),Q(Ka,{key:0,class:"icon"})):U("",!0)]),_:3},8,["class","href","target","rel"]))}});const Yt=O(Wa,[["__scopeId","data-v-3c355974"]]),qa=B({__name:"VPNavBarMenuLink",props:{item:null},setup(e){const{page:t}=ae();return(n,s)=>(d(),Q(Yt,{class:he({VPNavBarMenuLink:!0,active:_(Gt)(_(t).relativePath,e.item.activeMatch||e.item.link,!!e.item.activeMatch)}),href:e.item.link,noIcon:!0},{default:I(()=>[Oe(ie(e.item.text),1)]),_:1},8,["class","href"]))}});const Ga=O(qa,[["__scopeId","data-v-47a2263e"]]),to=me();let _i=!1,_s=0;function Ya(e){const t=me(!1);if(typeof window<"u"){!_i&&Qa(),_s++;const n=st(to,s=>{var o,r,i;s===e.el.value||((o=e.el.value)==null?void 0:o.contains(s))?(t.value=!0,(r=e.onFocus)==null||r.call(e)):(t.value=!1,(i=e.onBlur)==null||i.call(e))});pt(()=>{n(),_s--,_s||Ja()})}return Us(t)}function Qa(){document.addEventListener("focusin",pi),_i=!0,to.value=document.activeElement}function Ja(){document.removeEventListener("focusin",pi)}function pi(){to.value=document.activeElement}const Xa={},Za={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},eu=b("path",{d:"M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"},null,-1),tu=[eu];function nu(e,t){return d(),v("svg",Za,tu)}const vi=O(Xa,[["render",nu]]),su={},ou={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},ru=b("circle",{cx:"12",cy:"12",r:"2"},null,-1),iu=b("circle",{cx:"19",cy:"12",r:"2"},null,-1),lu=b("circle",{cx:"5",cy:"12",r:"2"},null,-1),cu=[ru,iu,lu];function au(e,t){return d(),v("svg",ou,cu)}const uu=O(su,[["render",au]]),fu={class:"VPMenuLink"},du=B({__name:"VPMenuLink",props:{item:null},setup(e){const{page:t}=ae();return(n,s)=>(d(),v("div",fu,[V(Yt,{class:he({active:_(Gt)(_(t).relativePath,e.item.activeMatch||e.item.link)}),href:e.item.link},{default:I(()=>[Oe(ie(e.item.text),1)]),_:1},8,["class","href"])]))}});const ss=O(du,[["__scopeId","data-v-e8e0fb1d"]]),hu={class:"VPMenuGroup"},_u={key:0,class:"title"},pu=B({__name:"VPMenuGroup",props:{text:null,items:null},setup(e){return(t,n)=>(d(),v("div",hu,[e.text?(d(),v("p",_u,ie(e.text),1)):U("",!0),(d(!0),v(q,null,Ce(e.items,s=>(d(),v(q,null,["link"in s?(d(),Q(ss,{key:0,item:s},null,8,["item"])):U("",!0)],64))),256))]))}});const vu=O(pu,[["__scopeId","data-v-9ca52130"]]),mu={class:"VPMenu"},gu={key:0,class:"items"},bu=B({__name:"VPMenu",props:{items:null},setup(e){return(t,n)=>(d(),v("div",mu,[e.items?(d(),v("div",gu,[(d(!0),v(q,null,Ce(e.items,s=>(d(),v(q,{key:s.text},["link"in s?(d(),Q(ss,{key:0,item:s},null,8,["item"])):(d(),Q(vu,{key:1,text:s.text,items:s.items},null,8,["text","items"]))],64))),128))])):U("",!0),E(t.$slots,"default",{},void 0,!0)]))}});const yu=O(bu,[["__scopeId","data-v-1c5d0cfc"]]),wu=["aria-expanded","aria-label"],xu={key:0,class:"text"},$u={class:"menu"},Pu=B({__name:"VPFlyout",props:{icon:null,button:null,label:null,items:null},setup(e){const t=me(!1),n=me();Ya({el:n,onBlur:s});function s(){t.value=!1}return(o,r)=>(d(),v("div",{class:"VPFlyout",ref_key:"el",ref:n,onMouseenter:r[1]||(r[1]=i=>t.value=!0),onMouseleave:r[2]||(r[2]=i=>t.value=!1)},[b("button",{type:"button",class:"button","aria-haspopup":"true","aria-expanded":t.value,"aria-label":e.label,onClick:r[0]||(r[0]=i=>t.value=!t.value)},[e.button||e.icon?(d(),v("span",xu,[e.icon?(d(),Q(Ys(e.icon),{key:0,class:"option-icon"})):U("",!0),Oe(" "+ie(e.button)+" ",1),V(vi,{class:"text-icon"})])):(d(),Q(uu,{key:1,class:"icon"}))],8,wu),b("div",$u,[V(yu,{items:e.items},{default:I(()=>[E(o.$slots,"default",{},void 0,!0)]),_:3},8,["items"])])],544))}});const no=O(Pu,[["__scopeId","data-v-6ffb57d3"]]),ku=B({__name:"VPNavBarMenuGroup",props:{item:null},setup(e){const{page:t}=ae();return(n,s)=>(d(),Q(no,{class:he({VPNavBarMenuGroup:!0,active:_(Gt)(_(t).relativePath,e.item.activeMatch,!!e.item.activeMatch)}),button:e.item.text,items:e.item.items},null,8,["class","button","items"]))}}),Cu=e=>(We("data-v-f83db6ba"),e=e(),qe(),e),Su={key:0,"aria-labelledby":"main-nav-aria-label",class:"VPNavBarMenu"},Vu=Cu(()=>b("span",{id:"main-nav-aria-label",class:"visually-hidden"},"Main Navigation",-1)),Tu=B({__name:"VPNavBarMenu",setup(e){const{theme:t}=ae();return(n,s)=>_(t).nav?(d(),v("nav",Su,[Vu,(d(!0),v(q,null,Ce(_(t).nav,o=>(d(),v(q,{key:o.text},["link"in o?(d(),Q(Ga,{key:0,item:o},null,8,["item"])):(d(),Q(ku,{key:1,item:o},null,8,["item"]))],64))),128))])):U("",!0)}});const Eu=O(Tu,[["__scopeId","data-v-f83db6ba"]]),Lu={},Mu={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Iu=b("path",{d:"M0 0h24v24H0z",fill:"none"},null,-1),Au=b("path",{d:" M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z ",class:"css-c4d79v"},null,-1),Nu=[Iu,Au];function Ou(e,t){return d(),v("svg",Mu,Nu)}const mi=O(Lu,[["render",Ou]]),Bu={class:"items"},Fu={class:"title"},Hu=B({__name:"VPNavBarTranslations",setup(e){const{theme:t}=ae();return(n,s)=>_(t).localeLinks?(d(),Q(no,{key:0,class:"VPNavBarTranslations",icon:mi},{default:I(()=>[b("div",Bu,[b("p",Fu,ie(_(t).localeLinks.text),1),(d(!0),v(q,null,Ce(_(t).localeLinks.items,o=>(d(),Q(ss,{key:o.link,item:o},null,8,["item"]))),128))])]),_:1})):U("",!0)}});const Du=O(Hu,[["__scopeId","data-v-db824e91"]]);const Ru={},Uu={class:"VPSwitch",type:"button",role:"switch"},ju={class:"check"},zu={key:0,class:"icon"};function Ku(e,t){return d(),v("button",Uu,[b("span",ju,[e.$slots.default?(d(),v("span",zu,[E(e.$slots,"default",{},void 0,!0)])):U("",!0)])])}const Wu=O(Ru,[["render",Ku],["__scopeId","data-v-086e8519"]]),qu={},Gu={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Yu=lc('',9),Qu=[Yu];function Ju(e,t){return d(),v("svg",Gu,Qu)}const Xu=O(qu,[["render",Ju]]),Zu={},ef={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},tf=b("path",{d:"M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"},null,-1),nf=[tf];function sf(e,t){return d(),v("svg",ef,nf)}const of=O(Zu,[["render",sf]]),rf=B({__name:"VPSwitchAppearance",setup(e){const t=me(!1),n=typeof localStorage<"u"?s():()=>{};De(()=>{t.value=document.documentElement.classList.contains("dark")});function s(){const o=window.matchMedia("(prefers-color-scheme: dark)"),r=document.documentElement.classList;let i=localStorage.getItem(Yo)||"auto",l=i==="auto"?o.matches:i==="dark";o.onchange=h=>{i==="auto"&&f(l=h.matches)};function c(){f(l=!l),i=l?o.matches?"auto":"dark":o.matches?"light":"auto",localStorage.setItem(Yo,i)}function f(h){t.value=h,r[h?"add":"remove"]("dark")}return c}return(o,r)=>(d(),Q(Wu,{class:"VPSwitchAppearance","aria-label":"toggle dark mode","aria-checked":t.value,onClick:_(n)},{default:I(()=>[V(Xu,{class:"sun"}),V(of,{class:"moon"})]),_:1},8,["aria-checked","onClick"]))}});const so=O(rf,[["__scopeId","data-v-1899cd41"]]),lf={key:0,class:"VPNavBarAppearance"},cf=B({__name:"VPNavBarAppearance",setup(e){const{site:t}=ae();return(n,s)=>_(t).appearance?(d(),v("div",lf,[V(so)])):U("",!0)}});const af=O(cf,[["__scopeId","data-v-a3e7452b"]]),uf={discord:'Discord',facebook:'Facebook',github:'GitHub',instagram:'Instagram',linkedin:'LinkedIn',slack:'Slack',twitter:'Twitter',youtube:'YouTube'},ff=["href","innerHTML"],df=B({__name:"VPSocialLink",props:{icon:null,link:null},setup(e){const t=e,n=re(()=>typeof t.icon=="object"?t.icon.svg:uf[t.icon]);return(s,o)=>(d(),v("a",{class:"VPSocialLink",href:e.link,target:"_blank",rel:"noopener",innerHTML:_(n)},null,8,ff))}});const hf=O(df,[["__scopeId","data-v-e57698f6"]]),_f={class:"VPSocialLinks"},pf=B({__name:"VPSocialLinks",props:{links:null},setup(e){return(t,n)=>(d(),v("div",_f,[(d(!0),v(q,null,Ce(e.links,({link:s,icon:o})=>(d(),Q(hf,{key:s,icon:o,link:s},null,8,["icon","link"]))),128))]))}});const oo=O(pf,[["__scopeId","data-v-f6988cfb"]]),vf=B({__name:"VPNavBarSocialLinks",setup(e){const{theme:t}=ae();return(n,s)=>_(t).socialLinks?(d(),Q(oo,{key:0,class:"VPNavBarSocialLinks",links:_(t).socialLinks},null,8,["links"])):U("",!0)}});const mf=O(vf,[["__scopeId","data-v-738bef5a"]]),gf=e=>(We("data-v-e4361c82"),e=e(),qe(),e),bf={key:0,class:"group"},yf={class:"trans-title"},wf={key:1,class:"group"},xf={class:"item appearance"},$f=gf(()=>b("p",{class:"label"},"Appearance",-1)),Pf={class:"appearance-action"},kf={key:2,class:"group"},Cf={class:"item social-links"},Sf=B({__name:"VPNavBarExtra",setup(e){const{site:t,theme:n}=ae(),s=re(()=>n.value.localeLinks||t.value.appearance||n.value.socialLinks);return(o,r)=>_(s)?(d(),Q(no,{key:0,class:"VPNavBarExtra",label:"extra navigation"},{default:I(()=>[_(n).localeLinks?(d(),v("div",bf,[b("p",yf,ie(_(n).localeLinks.text),1),(d(!0),v(q,null,Ce(_(n).localeLinks.items,i=>(d(),Q(ss,{key:i.link,item:i},null,8,["item"]))),128))])):U("",!0),_(t).appearance?(d(),v("div",wf,[b("div",xf,[$f,b("div",Pf,[V(so)])])])):U("",!0),_(n).socialLinks?(d(),v("div",kf,[b("div",Cf,[V(oo,{class:"social-links-list",links:_(n).socialLinks},null,8,["links"])])])):U("",!0)]),_:1})):U("",!0)}});const Vf=O(Sf,[["__scopeId","data-v-e4361c82"]]),Tf=e=>(We("data-v-e5dd9c1c"),e=e(),qe(),e),Ef=["aria-expanded"],Lf=Tf(()=>b("span",{class:"container"},[b("span",{class:"top"}),b("span",{class:"middle"}),b("span",{class:"bottom"})],-1)),Mf=[Lf],If=B({__name:"VPNavBarHamburger",props:{active:{type:Boolean}},emits:["click"],setup(e){return(t,n)=>(d(),v("button",{type:"button",class:he(["VPNavBarHamburger",{active:e.active}]),"aria-label":"mobile navigation","aria-expanded":e.active,"aria-controls":"VPNavScreen",onClick:n[0]||(n[0]=s=>t.$emit("click"))},Mf,10,Ef))}});const Af=O(If,[["__scopeId","data-v-e5dd9c1c"]]),Nf={class:"container"},Of={class:"content"},Bf=B({__name:"VPNavBar",props:{isScreenOpen:{type:Boolean}},emits:["toggle-screen"],setup(e){const{hasSidebar:t}=et();return(n,s)=>(d(),v("div",{class:he(["VPNavBar",{"has-sidebar":_(t)}])},[b("div",Nf,[V(La,null,{"nav-bar-title-before":I(()=>[E(n.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":I(()=>[E(n.$slots,"nav-bar-title-after",{},void 0,!0)]),_:3}),b("div",Of,[E(n.$slots,"nav-bar-content-before",{},void 0,!0),V(Fa,{class:"search"}),V(Eu,{class:"menu"}),V(Du,{class:"translations"}),V(af,{class:"appearance"}),V(mf,{class:"social-links"}),V(Vf,{class:"extra"}),E(n.$slots,"nav-bar-content-after",{},void 0,!0),V(Af,{class:"hamburger",active:e.isScreenOpen,onClick:s[0]||(s[0]=o=>n.$emit("toggle-screen"))},null,8,["active"])])])],2))}});const Ff=O(Bf,[["__scopeId","data-v-6f1d18b5"]]);function Hf(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t1),Ht=[],Fn=!1,io=-1,nn=void 0,Ct=void 0,sn=void 0,gi=function(t){return Ht.some(function(n){return!!(n.options.allowTouchMove&&n.options.allowTouchMove(t))})},Hn=function(t){var n=t||window.event;return gi(n.target)||n.touches.length>1?!0:(n.preventDefault&&n.preventDefault(),!1)},Df=function(t){if(sn===void 0){var n=!!t&&t.reserveScrollBarGap===!0,s=window.innerWidth-document.documentElement.clientWidth;if(n&&s>0){var o=parseInt(window.getComputedStyle(document.body).getPropertyValue("padding-right"),10);sn=document.body.style.paddingRight,document.body.style.paddingRight=o+s+"px"}}nn===void 0&&(nn=document.body.style.overflow,document.body.style.overflow="hidden")},Rf=function(){sn!==void 0&&(document.body.style.paddingRight=sn,sn=void 0),nn!==void 0&&(document.body.style.overflow=nn,nn=void 0)},Uf=function(){return window.requestAnimationFrame(function(){if(Ct===void 0){Ct={position:document.body.style.position,top:document.body.style.top,left:document.body.style.left};var t=window,n=t.scrollY,s=t.scrollX,o=t.innerHeight;document.body.style.position="fixed",document.body.style.top=-n,document.body.style.left=-s,setTimeout(function(){return window.requestAnimationFrame(function(){var r=o-window.innerHeight;r&&n>=o&&(document.body.style.top=-(n+r))})},300)}})},jf=function(){if(Ct!==void 0){var t=-parseInt(document.body.style.top,10),n=-parseInt(document.body.style.left,10);document.body.style.position=Ct.position,document.body.style.top=Ct.top,document.body.style.left=Ct.left,window.scrollTo(n,t),Ct=void 0}},zf=function(t){return t?t.scrollHeight-t.scrollTop<=t.clientHeight:!1},Kf=function(t,n){var s=t.targetTouches[0].clientY-io;return gi(t.target)?!1:n&&n.scrollTop===0&&s>0||zf(n)&&s<0?Hn(t):(t.stopPropagation(),!0)},Wf=function(t,n){if(!t){console.error("disableBodyScroll unsuccessful - targetElement must be provided when calling disableBodyScroll on IOS devices.");return}if(!Ht.some(function(o){return o.targetElement===t})){var s={targetElement:t,options:n||{}};Ht=[].concat(Hf(Ht),[s]),Bn?Uf():Df(n),Bn&&(t.ontouchstart=function(o){o.targetTouches.length===1&&(io=o.targetTouches[0].clientY)},t.ontouchmove=function(o){o.targetTouches.length===1&&Kf(o,t)},Fn||(document.addEventListener("touchmove",Hn,ro?{passive:!1}:void 0),Fn=!0))}},qf=function(){Bn&&(Ht.forEach(function(t){t.targetElement.ontouchstart=null,t.targetElement.ontouchmove=null}),Fn&&(document.removeEventListener("touchmove",Hn,ro?{passive:!1}:void 0),Fn=!1),io=-1),Bn?jf():Rf(),Ht=[]};const Gf=B({__name:"VPNavScreenMenuLink",props:{text:null,link:null},setup(e){const t=Xe("close-screen");return(n,s)=>(d(),Q(Yt,{class:"VPNavScreenMenuLink",href:e.link,onClick:_(t)},{default:I(()=>[Oe(ie(e.text),1)]),_:1},8,["href","onClick"]))}});const Yf=O(Gf,[["__scopeId","data-v-b7098508"]]),Qf={},Jf={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Xf=b("path",{d:"M18.9,10.9h-6v-6c0-0.6-0.4-1-1-1s-1,0.4-1,1v6h-6c-0.6,0-1,0.4-1,1s0.4,1,1,1h6v6c0,0.6,0.4,1,1,1s1-0.4,1-1v-6h6c0.6,0,1-0.4,1-1S19.5,10.9,18.9,10.9z"},null,-1),Zf=[Xf];function ed(e,t){return d(),v("svg",Jf,Zf)}const td=O(Qf,[["render",ed]]),nd=B({__name:"VPNavScreenMenuGroupLink",props:{text:null,link:null},setup(e){const t=Xe("close-screen");return(n,s)=>(d(),Q(Yt,{class:"VPNavScreenMenuGroupLink",href:e.link,onClick:_(t)},{default:I(()=>[Oe(ie(e.text),1)]),_:1},8,["href","onClick"]))}});const bi=O(nd,[["__scopeId","data-v-7f173864"]]),sd={class:"VPNavScreenMenuGroupSection"},od={key:0,class:"title"},rd=B({__name:"VPNavScreenMenuGroupSection",props:{text:null,items:null},setup(e){return(t,n)=>(d(),v("div",sd,[e.text?(d(),v("p",od,ie(e.text),1)):U("",!0),(d(!0),v(q,null,Ce(e.items,s=>(d(),Q(bi,{key:s.text,text:s.text,link:s.link},null,8,["text","link"]))),128))]))}});const id=O(rd,[["__scopeId","data-v-7478538b"]]),ld=["aria-controls","aria-expanded"],cd={class:"button-text"},ad=["id"],ud={key:1,class:"group"},fd=B({__name:"VPNavScreenMenuGroup",props:{text:null,items:null},setup(e){const t=e,n=me(!1),s=re(()=>`NavScreenGroup-${t.text.replace(" ","-").toLowerCase()}`);function o(){n.value=!n.value}return(r,i)=>(d(),v("div",{class:he(["VPNavScreenMenuGroup",{open:n.value}])},[b("button",{class:"button","aria-controls":_(s),"aria-expanded":n.value,onClick:o},[b("span",cd,ie(e.text),1),V(td,{class:"button-icon"})],8,ld),b("div",{id:_(s),class:"items"},[(d(!0),v(q,null,Ce(e.items,l=>(d(),v(q,{key:l.text},["link"in l?(d(),v("div",{key:l.text,class:"item"},[V(bi,{text:l.text,link:l.link},null,8,["text","link"])])):(d(),v("div",ud,[V(id,{text:l.text,items:l.items},null,8,["text","items"])]))],64))),128))],8,ad)],2))}});const dd=O(fd,[["__scopeId","data-v-5bc84358"]]),hd={key:0,class:"VPNavScreenMenu"},_d=B({__name:"VPNavScreenMenu",setup(e){const{theme:t}=ae();return(n,s)=>_(t).nav?(d(),v("nav",hd,[(d(!0),v(q,null,Ce(_(t).nav,o=>(d(),v(q,{key:o.text},["link"in o?(d(),Q(Yf,{key:0,text:o.text,link:o.link},null,8,["text","link"])):(d(),Q(dd,{key:1,text:o.text||"",items:o.items},null,8,["text","items"]))],64))),128))])):U("",!0)}}),pd=e=>(We("data-v-7bc19822"),e=e(),qe(),e),vd={key:0,class:"VPNavScreenAppearance"},md=pd(()=>b("p",{class:"text"},"Appearance",-1)),gd=B({__name:"VPNavScreenAppearance",setup(e){const{site:t}=ae();return(n,s)=>_(t).appearance?(d(),v("div",vd,[md,V(so)])):U("",!0)}});const bd=O(gd,[["__scopeId","data-v-7bc19822"]]),yd={class:"list"},wd=["href"],xd=B({__name:"VPNavScreenTranslations",setup(e){const{theme:t}=ae(),n=me(!1);function s(){n.value=!n.value}return(o,r)=>_(t).localeLinks?(d(),v("div",{key:0,class:he(["VPNavScreenTranslations",{open:n.value}])},[b("button",{class:"title",onClick:s},[V(mi,{class:"icon lang"}),Oe(" "+ie(_(t).localeLinks.text)+" ",1),V(vi,{class:"icon chevron"})]),b("ul",yd,[(d(!0),v(q,null,Ce(_(t).localeLinks.items,i=>(d(),v("li",{key:i.link,class:"item"},[b("a",{class:"link",href:i.link},ie(i.text),9,wd)]))),128))])],2)):U("",!0)}});const $d=O(xd,[["__scopeId","data-v-6bfcad30"]]),Pd=B({__name:"VPNavScreenSocialLinks",setup(e){const{theme:t}=ae();return(n,s)=>_(t).socialLinks?(d(),Q(oo,{key:0,class:"VPNavScreenSocialLinks",links:_(t).socialLinks},null,8,["links"])):U("",!0)}}),kd={class:"container"},Cd=B({__name:"VPNavScreen",props:{open:{type:Boolean}},setup(e){const t=me(null);function n(){Wf(t.value,{reserveScrollBarGap:!0})}function s(){qf()}return(o,r)=>(d(),Q(ts,{name:"fade",onEnter:n,onAfterLeave:s},{default:I(()=>[e.open?(d(),v("div",{key:0,class:"VPNavScreen",ref_key:"screen",ref:t},[b("div",kd,[E(o.$slots,"nav-screen-content-before",{},void 0,!0),V(_d,{class:"menu"}),V($d,{class:"translations"}),V(bd,{class:"appearance"}),V(Pd,{class:"social-links"}),E(o.$slots,"nav-screen-content-after",{},void 0,!0)])],512)):U("",!0)]),_:3}))}});const Sd=O(Cd,[["__scopeId","data-v-3428b523"]]),Vd=B({__name:"VPNav",setup(e){const{isScreenOpen:t,closeScreen:n,toggleScreen:s}=ka(),{hasSidebar:o}=et();return Qn("close-screen",n),(r,i)=>(d(),v("header",{class:he(["VPNav",{"no-sidebar":!_(o)}])},[V(Ff,{"is-screen-open":_(t),onToggleScreen:_(s)},{"nav-bar-title-before":I(()=>[E(r.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":I(()=>[E(r.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":I(()=>[E(r.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":I(()=>[E(r.$slots,"nav-bar-content-after",{},void 0,!0)]),_:3},8,["is-screen-open","onToggleScreen"]),V(Sd,{open:_(t)},{"nav-screen-content-before":I(()=>[E(r.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":I(()=>[E(r.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3},8,["open"])],2))}});const Td=O(Vd,[["__scopeId","data-v-a71a30f1"]]),Ed={},Ld={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Md=b("path",{d:"M17,11H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,11,17,11z"},null,-1),Id=b("path",{d:"M21,7H3C2.4,7,2,6.6,2,6s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,7,21,7z"},null,-1),Ad=b("path",{d:"M21,15H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,15,21,15z"},null,-1),Nd=b("path",{d:"M17,19H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,19,17,19z"},null,-1),Od=[Md,Id,Ad,Nd];function Bd(e,t){return d(),v("svg",Ld,Od)}const Fd=O(Ed,[["render",Bd]]),Hd=e=>(We("data-v-aac27d5e"),e=e(),qe(),e),Dd={key:0,class:"VPLocalNav"},Rd=["aria-expanded"],Ud=Hd(()=>b("span",{class:"menu-text"},"Menu",-1)),jd=B({__name:"VPLocalNav",props:{open:{type:Boolean}},emits:["open-menu"],setup(e){const{hasSidebar:t}=et();function n(){window.scrollTo({top:0,left:0,behavior:"smooth"})}return(s,o)=>_(t)?(d(),v("div",Dd,[b("button",{class:"menu","aria-expanded":e.open,"aria-controls":"VPSidebarNav",onClick:o[0]||(o[0]=r=>s.$emit("open-menu"))},[V(Fd,{class:"menu-icon"}),Ud],8,Rd),b("a",{class:"top-link",href:"#",onClick:n}," Return to top ")])):U("",!0)}});const zd=O(jd,[["__scopeId","data-v-aac27d5e"]]),Kd={},Wd={version:"1.1",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},qd=b("path",{d:"M19,2H5C3.3,2,2,3.3,2,5v14c0,1.7,1.3,3,3,3h14c1.7,0,3-1.3,3-3V5C22,3.3,20.7,2,19,2z M20,19c0,0.6-0.4,1-1,1H5c-0.6,0-1-0.4-1-1V5c0-0.6,0.4-1,1-1h14c0.6,0,1,0.4,1,1V19z"},null,-1),Gd=b("path",{d:"M16,11h-3V8c0-0.6-0.4-1-1-1s-1,0.4-1,1v3H8c-0.6,0-1,0.4-1,1s0.4,1,1,1h3v3c0,0.6,0.4,1,1,1s1-0.4,1-1v-3h3c0.6,0,1-0.4,1-1S16.6,11,16,11z"},null,-1),Yd=[qd,Gd];function Qd(e,t){return d(),v("svg",Wd,Yd)}const Jd=O(Kd,[["render",Qd]]),Xd={},Zd={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 24 24"},eh=b("path",{d:"M19,2H5C3.3,2,2,3.3,2,5v14c0,1.7,1.3,3,3,3h14c1.7,0,3-1.3,3-3V5C22,3.3,20.7,2,19,2zM20,19c0,0.6-0.4,1-1,1H5c-0.6,0-1-0.4-1-1V5c0-0.6,0.4-1,1-1h14c0.6,0,1,0.4,1,1V19z"},null,-1),th=b("path",{d:"M16,11H8c-0.6,0-1,0.4-1,1s0.4,1,1,1h8c0.6,0,1-0.4,1-1S16.6,11,16,11z"},null,-1),nh=[eh,th];function sh(e,t){return d(),v("svg",Zd,nh)}const oh=O(Xd,[["render",sh]]),rh=B({__name:"VPSidebarLink",props:{item:null,depth:{default:1}},setup(e){const{page:t,frontmatter:n}=ae(),s=re(()=>n.value.sidebarDepth||1/0),o=Xe("close-sidebar");return(r,i)=>{const l=Tt("VPSidebarLink",!0);return d(),v(q,null,[V(Yt,{class:he(["link",{active:_(Gt)(_(t).relativePath,e.item.link)}]),style:Dn({paddingLeft:16*(e.depth-1)+"px"}),href:e.item.link,onClick:_(o)},{default:I(()=>[b("span",{class:he(["link-text",{light:e.depth>1}])},ie(e.item.text),3)]),_:1},8,["class","style","href","onClick"]),"items"in e.item&&e.depth<_(s)?(d(!0),v(q,{key:0},Ce(e.item.items,c=>(d(),Q(l,{key:c.link,item:c,depth:e.depth+1},null,8,["item","depth"]))),128)):U("",!0)],64)}}});const ih=O(rh,[["__scopeId","data-v-2cfe069a"]]),lh=["role"],ch={class:"title-text"},ah={class:"action"},uh={class:"items"},fh=B({__name:"VPSidebarGroup",props:{text:null,items:null,collapsible:{type:Boolean},collapsed:{type:Boolean}},setup(e){const t=e,n=me(!1);Ut(()=>{n.value=!!(t.collapsible&&t.collapsed)});const{page:s}=ae();Ut(()=>{t.items.some(r=>Gt(s.value.relativePath,r.link))&&(n.value=!1)});function o(){t.collapsible&&(n.value=!n.value)}return(r,i)=>(d(),v("section",{class:he(["VPSidebarGroup",{collapsible:e.collapsible,collapsed:n.value}])},[e.text?(d(),v("div",{key:0,class:"title",role:e.collapsible?"button":void 0,onClick:o},[b("h2",ch,ie(e.text),1),b("div",ah,[V(oh,{class:"icon minus"}),V(Jd,{class:"icon plus"})])],8,lh)):U("",!0),b("div",uh,[(d(!0),v(q,null,Ce(e.items,l=>(d(),Q(ih,{key:l.link,item:l},null,8,["item"]))),128))])],2))}});const dh=O(fh,[["__scopeId","data-v-35f99ef5"]]),hh=e=>(We("data-v-f332cb62"),e=e(),qe(),e),_h={class:"nav",id:"VPSidebarNav","aria-labelledby":"sidebar-aria-label",tabindex:"-1"},ph=hh(()=>b("span",{class:"visually-hidden",id:"sidebar-aria-label"}," Sidebar Navigation ",-1)),vh=B({__name:"VPSidebar",props:{open:{type:Boolean}},setup(e){const t=e,{sidebar:n,hasSidebar:s}=et();let o=me(null);return Or(async()=>{var r;t.open&&(await qn(),(r=o.value)==null||r.focus())}),(r,i)=>_(s)?(d(),v("aside",{key:0,class:he(["VPSidebar",{open:e.open}]),ref_key:"navEl",ref:o,onClick:i[0]||(i[0]=Kc(()=>{},["stop"]))},[b("nav",_h,[ph,(d(!0),v(q,null,Ce(_(n),l=>(d(),v("div",{key:l.text,class:"group"},[V(dh,{text:l.text,items:l.items,collapsible:l.collapsible,collapsed:l.collapsed},null,8,["text","items","collapsible","collapsed"])]))),128))])],2)):U("",!0)}});const mh=O(vh,[["__scopeId","data-v-f332cb62"]]),gh={},bh={class:"VPPage"};function yh(e,t){const n=Tt("Content");return d(),v("div",bh,[V(n)])}const wh=O(gh,[["render",yh]]),xh=B({__name:"VPButton",props:{tag:null,size:null,theme:null,text:null,href:null},setup(e){const t=e,n=re(()=>{var r,i;return[(r=t.size)!=null?r:"medium",(i=t.theme)!=null?i:"brand"]}),s=re(()=>t.href&&ns.test(t.href)),o=re(()=>t.tag?t.tag:t.href?"a":"button");return(r,i)=>(d(),Q(Ys(_(o)),{class:he(["VPButton",_(n)]),href:e.href?_(On)(e.href):void 0,target:_(s)?"_blank":void 0,rel:_(s)?"noreferrer":void 0},{default:I(()=>[Oe(ie(e.text),1)]),_:1},8,["class","href","target","rel"]))}});const $h=O(xh,[["__scopeId","data-v-53dbb8eb"]]),Ph=e=>(We("data-v-923ba72e"),e=e(),qe(),e),kh={class:"container"},Ch={class:"main"},Sh={key:0,class:"name"},Vh={class:"clip"},Th={key:1,class:"text"},Eh={key:2,class:"tagline"},Lh={key:3,class:"actions"},Mh={key:0,class:"image"},Ih={class:"image-container"},Ah=Ph(()=>b("div",{class:"image-bg"},null,-1)),Nh=B({__name:"VPHero",props:{name:null,text:null,tagline:null,image:null,actions:null},setup(e){return(t,n)=>(d(),v("div",{class:he(["VPHero",{"has-image":e.image}])},[b("div",kh,[b("div",Ch,[e.name?(d(),v("h1",Sh,[b("span",Vh,ie(e.name),1)])):U("",!0),e.text?(d(),v("p",Th,ie(e.text),1)):U("",!0),e.tagline?(d(),v("p",Eh,ie(e.tagline),1)):U("",!0),e.actions?(d(),v("div",Lh,[(d(!0),v(q,null,Ce(e.actions,s=>(d(),v("div",{key:s.link,class:"action"},[V($h,{tag:"a",size:"medium",theme:s.theme,text:s.text,href:s.link},null,8,["theme","text","href"])]))),128))])):U("",!0)]),e.image?(d(),v("div",Mh,[b("div",Ih,[Ah,V(hi,{class:"image-src",image:e.image},null,8,["image"])])])):U("",!0)])],2))}});const Oh=O(Nh,[["__scopeId","data-v-923ba72e"]]),Bh=B({__name:"VPHomeHero",setup(e){const{frontmatter:t}=ae();return(n,s)=>_(t).hero?(d(),Q(Oh,{key:0,class:"VPHomeHero",name:_(t).hero.name,text:_(t).hero.text,tagline:_(t).hero.tagline,image:_(t).hero.image,actions:_(t).hero.actions},null,8,["name","text","tagline","image","actions"])):U("",!0)}}),Fh={class:"VPFeature"},Hh={key:0,class:"icon"},Dh={class:"title"},Rh={class:"details"},Uh=B({__name:"VPFeature",props:{icon:null,title:null,details:null},setup(e){return(t,n)=>(d(),v("article",Fh,[e.icon?(d(),v("div",Hh,ie(e.icon),1)):U("",!0),b("h2",Dh,ie(e.title),1),b("p",Rh,ie(e.details),1)]))}});const jh=O(Uh,[["__scopeId","data-v-d99b2f77"]]),zh={key:0,class:"VPFeatures"},Kh={class:"container"},Wh={class:"items"},qh=B({__name:"VPFeatures",props:{features:null},setup(e){const t=e,n=re(()=>{const s=t.features.length;if(s){if(s===2)return"grid-2";if(s===3)return"grid-3";if(s%3===0)return"grid-6";if(s%2===0)return"grid-4"}else return});return(s,o)=>e.features?(d(),v("div",zh,[b("div",Kh,[b("div",Wh,[(d(!0),v(q,null,Ce(e.features,r=>(d(),v("div",{key:r.title,class:he(["item",[_(n)]])},[V(jh,{icon:r.icon,title:r.title,details:r.details},null,8,["icon","title","details"])],2))),128))])])])):U("",!0)}});const Gh=O(qh,[["__scopeId","data-v-6a6451ec"]]),Yh=B({__name:"VPHomeFeatures",setup(e){const{frontmatter:t}=ae();return(n,s)=>_(t).features?(d(),Q(Gh,{key:0,class:"VPHomeFeatures",features:_(t).features},null,8,["features"])):U("",!0)}}),Qh={class:"VPHome"},Jh=B({__name:"VPHome",setup(e){return(t,n)=>{const s=Tt("Content");return d(),v("div",Qh,[E(t.$slots,"home-hero-before",{},void 0,!0),V(Bh),E(t.$slots,"home-hero-after",{},void 0,!0),E(t.$slots,"home-features-before",{},void 0,!0),V(Yh),E(t.$slots,"home-features-after",{},void 0,!0),V(s)])}}});const Xh=O(Jh,[["__scopeId","data-v-1db23833"]]);var nr;const _n=typeof window<"u";_n&&((nr=window==null?void 0:window.navigator)==null?void 0:nr.userAgent)&&/iP(ad|hone|od)/.test(window.navigator.userAgent);function Zh(e){return e}function e_(e){return Fi()?(Hi(e),!0):!1}function t_(e){return typeof e=="function"?re(e):me(e)}function n_(e,t=!0){Zs()?De(e):t?e():qn(e)}const s_=_n?window:void 0;_n&&window.document;_n&&window.navigator;_n&&window.location;function o_(e,t=!1){const n=me(),s=()=>n.value=Boolean(e());return s(),n_(s,t),n}function sr(e,t={}){const{window:n=s_}=t,s=o_(()=>n&&"matchMedia"in n&&typeof n.matchMedia=="function");let o;const r=me(!1),i=()=>{!o||("removeEventListener"in o?o.removeEventListener("change",l):o.removeListener(l))},l=()=>{!s.value||(i(),o=n.matchMedia(t_(e).value),r.value=o.matches,"addEventListener"in o?o.addEventListener("change",l):o.addListener(l))};return Ut(l),e_(()=>i()),r}const Es=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},Ls="__vueuse_ssr_handlers__";Es[Ls]=Es[Ls]||{};Es[Ls];var or;(function(e){e.UP="UP",e.RIGHT="RIGHT",e.DOWN="DOWN",e.LEFT="LEFT",e.NONE="NONE"})(or||(or={}));var r_=Object.defineProperty,rr=Object.getOwnPropertySymbols,i_=Object.prototype.hasOwnProperty,l_=Object.prototype.propertyIsEnumerable,ir=(e,t,n)=>t in e?r_(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,c_=(e,t)=>{for(var n in t||(t={}))i_.call(t,n)&&ir(e,n,t[n]);if(rr)for(var n of rr(t))l_.call(t,n)&&ir(e,n,t[n]);return e};const a_={easeInSine:[.12,0,.39,0],easeOutSine:[.61,1,.88,1],easeInOutSine:[.37,0,.63,1],easeInQuad:[.11,0,.5,0],easeOutQuad:[.5,1,.89,1],easeInOutQuad:[.45,0,.55,1],easeInCubic:[.32,0,.67,0],easeOutCubic:[.33,1,.68,1],easeInOutCubic:[.65,0,.35,1],easeInQuart:[.5,0,.75,0],easeOutQuart:[.25,1,.5,1],easeInOutQuart:[.76,0,.24,1],easeInQuint:[.64,0,.78,0],easeOutQuint:[.22,1,.36,1],easeInOutQuint:[.83,0,.17,1],easeInExpo:[.7,0,.84,0],easeOutExpo:[.16,1,.3,1],easeInOutExpo:[.87,0,.13,1],easeInCirc:[.55,0,1,.45],easeOutCirc:[0,.55,.45,1],easeInOutCirc:[.85,0,.15,1],easeInBack:[.36,0,.66,-.56],easeOutBack:[.34,1.56,.64,1],easeInOutBack:[.68,-.6,.32,1.6]};c_({linear:Zh},a_);function u_(){const{hasSidebar:e}=et(),t=sr("(min-width: 960px)"),n=sr("(min-width: 1280px)");return{isAsideEnabled:re(()=>!n.value&&!t.value?!1:e.value?n.value:t.value)}}const f_=71;function d_(e){if(e===!1)return[];let t=[];return document.querySelectorAll("h2, h3, h4, h5, h6").forEach(n=>{n.textContent&&n.id&&t.push({level:Number(n.tagName[1]),title:n.innerText.replace(/\s+#\s*$/,""),link:`#${n.id}`})}),h_(t,e)}function h_(e,t=2){return __(e,typeof t=="number"?[t,t]:t==="deep"?[2,6]:t)}function __(e,t){const n=[];return e=e.map(s=>({...s})),e.forEach((s,o)=>{s.level>=t[0]&&s.level<=t[1]&&p_(o,e,t)&&n.push(s)}),n}function p_(e,t,n){if(e===0)return!0;const s=t[e];for(let o=e-1;o>=0;o--){const r=t[o];if(r.level=n[0]&&r.level<=n[1])return r.children==null&&(r.children=[]),r.children.push(s),!1}return!0}function v_(e,t){const{isAsideEnabled:n}=u_(),s=ma(r,100);let o=null;De(()=>{requestAnimationFrame(r),window.addEventListener("scroll",s)}),qs(()=>{i(location.hash)}),pt(()=>{window.removeEventListener("scroll",s)});function r(){if(!n.value)return;const l=[].slice.call(e.value.querySelectorAll(".outline-link")),c=[].slice.call(document.querySelectorAll(".content .header-anchor")).filter(C=>l.some(j=>j.hash===C.hash&&C.offsetParent!==null)),f=window.scrollY,h=window.innerHeight,m=document.body.offsetHeight,x=Math.abs(f+h-m)<1;if(c.length&&x){i(c[c.length-1].hash);return}for(let C=0;C{const s=Tt("VPDocAsideOutlineItem",!0);return d(),v("ul",{class:he(e.root?"root":"nested")},[(d(!0),v(q,null,Ce(e.headers,({children:o,link:r,title:i})=>(d(),v("li",null,[b("a",{class:"outline-link",href:r,onClick:n[0]||(n[0]=(...l)=>e.onClick&&e.onClick(...l))},ie(i),9,g_),o!=null&&o.length?(d(),Q(s,{key:0,headers:o,onClick:e.onClick},null,8,["headers","onClick"])):U("",!0)]))),256))],2)}}});const y_=O(b_,[["__scopeId","data-v-1188541a"]]),w_=e=>(We("data-v-2865c0b0"),e=e(),qe(),e),x_={class:"content"},$_={class:"outline-title"},P_={"aria-labelledby":"doc-outline-aria-label"},k_=w_(()=>b("span",{class:"visually-hidden",id:"doc-outline-aria-label"}," Table of Contents for current page ",-1)),C_=B({__name:"VPDocAsideOutline",setup(e){const{frontmatter:t,theme:n}=ae(),s=re(()=>{var h;return(h=t.value.outline)!=null?h:n.value.outline}),o=Xe("onContentUpdated");o.value=()=>{r.value=d_(s.value)};const r=me([]),i=re(()=>r.value.length>0),l=me(),c=me();v_(l,c);function f({target:h}){const m="#"+h.href.split("#")[1],x=document.querySelector(decodeURIComponent(m));x==null||x.focus()}return(h,m)=>(d(),v("div",{class:he(["VPDocAsideOutline",{"has-outline":_(i)}]),ref_key:"container",ref:l},[b("div",x_,[b("div",{class:"outline-marker",ref_key:"marker",ref:c},null,512),b("div",$_,ie(_(n).outlineTitle||"On this page"),1),b("nav",P_,[k_,V(y_,{headers:r.value,root:!0,onClick:f},null,8,["headers"])])])],2))}});const S_=O(C_,[["__scopeId","data-v-2865c0b0"]]),V_={class:"VPDocAsideCarbonAds"},T_=B({__name:"VPDocAsideCarbonAds",setup(e){const t=()=>null;return(n,s)=>(d(),v("div",V_,[V(_(t))]))}}),E_=e=>(We("data-v-afc4c1a1"),e=e(),qe(),e),L_={class:"VPDocAside"},M_=E_(()=>b("div",{class:"spacer"},null,-1)),I_=B({__name:"VPDocAside",setup(e){const{theme:t}=ae();return(n,s)=>(d(),v("div",L_,[E(n.$slots,"aside-top",{},void 0,!0),E(n.$slots,"aside-outline-before",{},void 0,!0),V(S_),E(n.$slots,"aside-outline-after",{},void 0,!0),M_,E(n.$slots,"aside-ads-before",{},void 0,!0),_(t).carbonAds?(d(),Q(T_,{key:0})):U("",!0),E(n.$slots,"aside-ads-after",{},void 0,!0),E(n.$slots,"aside-bottom",{},void 0,!0)]))}});const A_=O(I_,[["__scopeId","data-v-afc4c1a1"]]);function N_(){const{theme:e,page:t}=ae();return re(()=>{const{text:n="Edit this page",pattern:s}=e.value.editLink||{},{relativePath:o}=t.value;return{url:s.replace(/:path/g,o),text:n}})}function O_(){const{page:e,theme:t,frontmatter:n}=ae();return re(()=>{const s=di(t.value.sidebar,e.value.relativePath),o=ga(s),r=o.findIndex(i=>Gt(e.value.relativePath,i.link));return{prev:n.value.prev?{...o[r-1],text:n.value.prev}:o[r-1],next:n.value.next?{...o[r+1],text:n.value.next}:o[r+1]}})}const B_={},F_={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},H_=b("path",{d:"M18,23H4c-1.7,0-3-1.3-3-3V6c0-1.7,1.3-3,3-3h7c0.6,0,1,0.4,1,1s-0.4,1-1,1H4C3.4,5,3,5.4,3,6v14c0,0.6,0.4,1,1,1h14c0.6,0,1-0.4,1-1v-7c0-0.6,0.4-1,1-1s1,0.4,1,1v7C21,21.7,19.7,23,18,23z"},null,-1),D_=b("path",{d:"M8,17c-0.3,0-0.5-0.1-0.7-0.3C7,16.5,6.9,16.1,7,15.8l1-4c0-0.2,0.1-0.3,0.3-0.5l9.5-9.5c1.2-1.2,3.2-1.2,4.4,0c1.2,1.2,1.2,3.2,0,4.4l-9.5,9.5c-0.1,0.1-0.3,0.2-0.5,0.3l-4,1C8.2,17,8.1,17,8,17zM9.9,12.5l-0.5,2.1l2.1-0.5l9.3-9.3c0.4-0.4,0.4-1.1,0-1.6c-0.4-0.4-1.2-0.4-1.6,0l0,0L9.9,12.5z M18.5,2.5L18.5,2.5L18.5,2.5z"},null,-1),R_=[H_,D_];function U_(e,t){return d(),v("svg",F_,R_)}const j_=O(B_,[["render",U_]]),z_={class:"VPLastUpdated"},K_=["datatime"],W_=B({__name:"VPDocFooterLastUpdated",setup(e){const{theme:t,page:n}=ae(),s=re(()=>new Date(n.value.lastUpdated)),o=re(()=>s.value.toISOString()),r=me("");return De(()=>{Ut(()=>{r.value=s.value.toLocaleString(window.navigator.language)})}),(i,l)=>{var c;return d(),v("p",z_,[Oe(ie((c=_(t).lastUpdatedText)!=null?c:"Last updated")+": ",1),b("time",{datatime:_(o)},ie(r.value),9,K_)])}}});const q_=O(W_,[["__scopeId","data-v-f7d51a9c"]]),G_={key:0,class:"VPDocFooter"},Y_={key:0,class:"edit-info"},Q_={key:0,class:"edit-link"},J_={key:1,class:"last-updated"},X_={key:1,class:"prev-next"},Z_={class:"pager"},e1=["href"],t1={class:"desc"},n1={class:"title"},s1=["href"],o1={class:"desc"},r1={class:"title"},i1=B({__name:"VPDocFooter",setup(e){const{theme:t,page:n,frontmatter:s}=ae(),o=N_(),r=O_(),i=re(()=>t.value.editLink&&s.value.editLink!==!1),l=re(()=>n.value.lastUpdated&&s.value.lastUpdated!==!1),c=re(()=>i.value||l.value||r.value.prev||r.value.next);return(f,h)=>{var m,x,C,j;return _(c)?(d(),v("footer",G_,[_(i)||_(l)?(d(),v("div",Y_,[_(i)?(d(),v("div",Q_,[V(Yt,{class:"edit-link-button",href:_(o).url,"no-icon":!0},{default:I(()=>[V(j_,{class:"edit-link-icon"}),Oe(" "+ie(_(o).text),1)]),_:1},8,["href"])])):U("",!0),_(l)?(d(),v("div",J_,[V(q_)])):U("",!0)])):U("",!0),_(r).prev||_(r).next?(d(),v("div",X_,[b("div",Z_,[_(r).prev?(d(),v("a",{key:0,class:"pager-link prev",href:_(On)(_(r).prev.link)},[b("span",t1,ie((x=(m=_(t).docFooter)==null?void 0:m.prev)!=null?x:"Previous page"),1),b("span",n1,ie(_(r).prev.text),1)],8,e1)):U("",!0)]),b("div",{class:he(["pager",{"has-prev":_(r).prev}])},[_(r).next?(d(),v("a",{key:0,class:"pager-link next",href:_(On)(_(r).next.link)},[b("span",o1,ie((j=(C=_(t).docFooter)==null?void 0:C.next)!=null?j:"Next page"),1),b("span",r1,ie(_(r).next.text),1)],8,s1)):U("",!0)],2)])):U("",!0)])):U("",!0)}}});const l1=O(i1,[["__scopeId","data-v-a54a85bd"]]),c1=e=>(We("data-v-37ebe389"),e=e(),qe(),e),a1={class:"container"},u1={key:0,class:"aside"},f1=c1(()=>b("div",{class:"aside-curtain"},null,-1)),d1={class:"aside-container"},h1={class:"aside-content"},_1={class:"content"},p1={class:"content-container"},v1={class:"main"},m1=B({__name:"VPDoc",setup(e){const t=vt(),{hasSidebar:n,hasAside:s}=et(),o=re(()=>t.path.replace(/[./]+/g,"_").replace(/_html$/,"")),r=me();return Qn("onContentUpdated",r),(i,l)=>{const c=Tt("Content");return d(),v("div",{class:he(["VPDoc",{"has-sidebar":_(n),"has-aside":_(s)}])},[b("div",a1,[_(s)?(d(),v("div",u1,[f1,b("div",d1,[b("div",h1,[V(A_,null,{"aside-top":I(()=>[E(i.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":I(()=>[E(i.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":I(()=>[E(i.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":I(()=>[E(i.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":I(()=>[E(i.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":I(()=>[E(i.$slots,"aside-ads-after",{},void 0,!0)]),_:3})])])])):U("",!0),b("div",_1,[b("div",p1,[E(i.$slots,"doc-before",{},void 0,!0),b("main",v1,[V(c,{class:he(["vp-doc",_(o)]),onContentUpdated:r.value},null,8,["class","onContentUpdated"])]),E(i.$slots,"doc-footer-before",{},void 0,!0),V(l1),E(i.$slots,"doc-after",{},void 0,!0)])])])],2)}}});const g1=O(m1,[["__scopeId","data-v-37ebe389"]]),b1=B({__name:"VPContent",setup(e){const t=vt(),{frontmatter:n}=ae(),{hasSidebar:s}=et(),o=Xe("NotFound");return(r,i)=>(d(),v("div",{class:he(["VPContent",{"has-sidebar":_(s),"is-home":_(n).layout==="home"}]),id:"VPContent"},[_(t).component===_(o)?(d(),Q(_(o),{key:0})):_(n).layout==="page"?(d(),Q(wh,{key:1})):_(n).layout==="home"?(d(),Q(Xh,{key:2},{"home-hero-before":I(()=>[E(r.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-after":I(()=>[E(r.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":I(()=>[E(r.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":I(()=>[E(r.$slots,"home-features-after",{},void 0,!0)]),_:3})):(d(),Q(g1,{key:3},{"doc-footer-before":I(()=>[E(r.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":I(()=>[E(r.$slots,"doc-before",{},void 0,!0)]),"doc-after":I(()=>[E(r.$slots,"doc-after",{},void 0,!0)]),"aside-top":I(()=>[E(r.$slots,"aside-top",{},void 0,!0)]),"aside-outline-before":I(()=>[E(r.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":I(()=>[E(r.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":I(()=>[E(r.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":I(()=>[E(r.$slots,"aside-ads-after",{},void 0,!0)]),"aside-bottom":I(()=>[E(r.$slots,"aside-bottom",{},void 0,!0)]),_:3}))],2))}});const y1=O(b1,[["__scopeId","data-v-c95df128"]]),w1={class:"container"},x1=["innerHTML"],$1=["innerHTML"],P1=B({__name:"VPFooter",setup(e){const{theme:t}=ae(),{hasSidebar:n}=et();return(s,o)=>_(t).footer?(d(),v("footer",{key:0,class:he(["VPFooter",{"has-sidebar":_(n)}])},[b("div",w1,[_(t).footer.message?(d(),v("p",{key:0,class:"message",innerHTML:_(t).footer.message},null,8,x1)):U("",!0),_(t).footer.copyright?(d(),v("p",{key:1,class:"copyright",innerHTML:_(t).footer.copyright},null,8,$1)):U("",!0)])],2)):U("",!0)}});const k1=O(P1,[["__scopeId","data-v-9f24cc86"]]),C1={key:0,class:"Layout"},S1=B({__name:"Layout",setup(e){const{isOpen:t,open:n,close:s}=et(),o=vt();st(()=>o.path,s),ba(t,s),Qn("close-sidebar",s);const{frontmatter:r}=ae();return(i,l)=>{const c=Tt("Content");return _(r).layout!==!1?(d(),v("div",C1,[E(i.$slots,"layout-top",{},void 0,!0),V(wa),V(Pa,{class:"backdrop",show:_(t),onClick:_(s)},null,8,["show","onClick"]),V(Td,null,{"nav-bar-title-before":I(()=>[E(i.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":I(()=>[E(i.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":I(()=>[E(i.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":I(()=>[E(i.$slots,"nav-bar-content-after",{},void 0,!0)]),"nav-screen-content-before":I(()=>[E(i.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":I(()=>[E(i.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3}),V(zd,{open:_(t),onOpenMenu:_(n)},null,8,["open","onOpenMenu"]),V(mh,{open:_(t)},null,8,["open"]),V(y1,null,{"home-hero-before":I(()=>[E(i.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-after":I(()=>[E(i.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":I(()=>[E(i.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":I(()=>[E(i.$slots,"home-features-after",{},void 0,!0)]),"doc-footer-before":I(()=>[E(i.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":I(()=>[E(i.$slots,"doc-before",{},void 0,!0)]),"doc-after":I(()=>[E(i.$slots,"doc-after",{},void 0,!0)]),"aside-top":I(()=>[E(i.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":I(()=>[E(i.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":I(()=>[E(i.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":I(()=>[E(i.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":I(()=>[E(i.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":I(()=>[E(i.$slots,"aside-ads-after",{},void 0,!0)]),_:3}),V(k1),E(i.$slots,"layout-bottom",{},void 0,!0)])):(d(),Q(c,{key:1}))}}});const V1=O(S1,[["__scopeId","data-v-c6a644e1"]]),os=e=>(We("data-v-95656537"),e=e(),qe(),e),T1={class:"NotFound"},E1=os(()=>b("p",{class:"code"},"404",-1)),L1=os(()=>b("h1",{class:"title"},"PAGE NOT FOUND",-1)),M1=os(()=>b("div",{class:"divider"},null,-1)),I1=os(()=>b("blockquote",{class:"quote"}," But if you don't change your direction, and if you keep looking, you may end up where you are heading. ",-1)),A1={class:"action"},N1=["href"],O1=B({__name:"NotFound",setup(e){const{site:t}=ae();return(n,s)=>(d(),v("div",T1,[E1,L1,M1,I1,b("div",A1,[b("a",{class:"link",href:_(t).base,"aria-label":"go to home"}," Take me home ",8,N1)])]))}});const B1=O(O1,[["__scopeId","data-v-95656537"]]);const Dt={Layout:V1,NotFound:B1};function F1(e,t){let n=[],s=!0;const o=r=>{if(s){s=!1;return}n.forEach(i=>document.head.removeChild(i)),n=[],r.forEach(i=>{const l=H1(i);document.head.appendChild(l),n.push(l)})};Ut(()=>{const r=e.data,i=t.value,l=r&&r.description,c=r&&r.frontmatter.head||[];document.title=li(i,r),document.querySelector("meta[name=description]").setAttribute("content",l||i.description),o(ia(i.head,R1(c)))})}function H1([e,t,n]){const s=document.createElement(e);for(const o in t)s.setAttribute(o,t[o]);return n&&(s.innerHTML=n),s}function D1(e){return e[0]==="meta"&&e[1]&&e[1].name==="description"}function R1(e){return e.filter(t=>!D1(t))}const ps=new Set,yi=()=>document.createElement("link"),U1=e=>{const t=yi();t.rel="prefetch",t.href=e,document.head.appendChild(t)},j1=e=>{const t=new XMLHttpRequest;t.open("GET",e,t.withCredentials=!0),t.send()};let Pn;const z1=Ee&&(Pn=yi())&&Pn.relList&&Pn.relList.supports&&Pn.relList.supports("prefetch")?U1:j1;function K1(){if(!Ee||!window.IntersectionObserver)return;let e;if((e=navigator.connection)&&(e.saveData||/2g/.test(e.effectiveType)))return;const t=window.requestIdleCallback||setTimeout;let n=null;const s=()=>{n&&n.disconnect(),n=new IntersectionObserver(r=>{r.forEach(i=>{if(i.isIntersecting){const l=i.target;n.unobserve(l);const{pathname:c}=l;if(!ps.has(c)){ps.add(c);const f=ci(c);z1(f)}}})}),t(()=>{document.querySelectorAll("#app a").forEach(r=>{const{target:i,hostname:l,pathname:c}=r,f=c.match(/\.\w+$/);f&&f[0]!==".html"||i!=="_blank"&&l===location.hostname&&(c!==location.pathname?n.observe(r):ps.add(c))})})};De(s);const o=vt();st(()=>o.path,s),pt(()=>{n&&n.disconnect()})}const W1=B({setup(e,{slots:t}){const n=me(!1);return De(()=>{n.value=!0}),()=>n.value&&t.default?t.default():null}});function q1(){if(Ee){const e=new Map;window.addEventListener("click",t=>{var s;const n=t.target;if(n.matches('div[class*="language-"] > button.copy')){const o=n.parentElement,r=(s=n.nextElementSibling)==null?void 0:s.nextElementSibling;if(!o||!r)return;const i=/language-(shellscript|shell|bash|sh|zsh)/.test(o.classList.toString());let{innerText:l=""}=r;i&&(l=l.replace(/^ *(\$|>) /gm,"")),G1(l).then(()=>{n.classList.add("copied"),clearTimeout(e.get(n));const c=setTimeout(()=>{n.classList.remove("copied"),n.blur(),e.delete(n)},2e3);e.set(n,c)})}})}}async function G1(e){try{return navigator.clipboard.writeText(e)}catch{const t=document.createElement("textarea"),n=document.activeElement;t.value=e,t.setAttribute("readonly",""),t.style.contain="strict",t.style.position="absolute",t.style.left="-9999px",t.style.fontSize="12pt";const s=document.getSelection(),o=s?s.rangeCount>0&&s.getRangeAt(0):null;document.body.appendChild(t),t.select(),t.selectionStart=0,t.selectionEnd=e.length,document.execCommand("copy"),document.body.removeChild(t),o&&(s.removeAllRanges(),s.addRange(o)),n&&n.focus()}}const wi=Dt.NotFound||(()=>"404 Not Found"),Y1=B({name:"VitePressApp",setup(){const{site:e}=ae();return De(()=>{st(()=>e.value.lang,t=>{document.documentElement.lang=t},{immediate:!0})}),K1(),q1(),Dt.setup&&Dt.setup(),()=>Nn(Dt.Layout)}});function Q1(){const e=X1(),t=J1();t.provide(ui,e);const n=ca(e.route);return t.provide(ai,n),t.provide("NotFound",wi),t.component("Content",da),t.component("ClientOnly",W1),Object.defineProperty(t.config.globalProperties,"$frontmatter",{get(){return n.frontmatter.value}}),Dt.enhanceApp&&Dt.enhanceApp({app:t,router:e,siteData:zt}),{app:t,router:e,data:n}}function J1(){return Gc(Y1)}function X1(){let e=Ee,t;return ua(n=>{let s=ci(n);return e&&(t=s),(e||t===s)&&(s=s.replace(/\.js$/,".lean.js")),Ee&&(e=!1),Xc(()=>import(s),[])},wi)}if(Ee){const{app:e,router:t,data:n}=Q1();t.go().then(()=>{F1(t.route,n.site),e.mount("#app")})}export{O as _,lc as a,b,v as c,Q1 as createApp,Oe as d,d as o}; diff --git a/assets/app.a576d425.js b/assets/app.a576d425.js deleted file mode 100644 index 063a401e6..000000000 --- a/assets/app.a576d425.js +++ /dev/null @@ -1 +0,0 @@ -function Ms(e,t){const n=Object.create(null),s=e.split(",");for(let o=0;o!!n[o.toLowerCase()]:o=>!!n[o]}const Pi="itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly",ki=Ms(Pi);function cr(e){return!!e||e===""}function Dn(e){if(K(e)){const t={};for(let n=0;n{if(n){const s=n.split(Si);s.length>1&&(t[s[0].trim()]=s[1].trim())}}),t}function he(e){let t="";if(we(e))t=e;else if(K(e))for(let n=0;nwe(e)?e:e==null?"":K(e)||ge(e)&&(e.toString===dr||!X(e.toString))?JSON.stringify(e,ar,2):String(e),ar=(e,t)=>t&&t.__v_isRef?ar(e,t.value):At(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((n,[s,o])=>(n[`${s} =>`]=o,n),{})}:ur(t)?{[`Set(${t.size})`]:[...t.values()]}:ge(t)&&!K(t)&&!hr(t)?String(t):t,ve={},It=[],Ke=()=>{},Ti=()=>!1,Ei=/^on[^a-z]/,hn=e=>Ei.test(e),Is=e=>e.startsWith("onUpdate:"),$e=Object.assign,As=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},Li=Object.prototype.hasOwnProperty,se=(e,t)=>Li.call(e,t),K=Array.isArray,At=e=>Rn(e)==="[object Map]",ur=e=>Rn(e)==="[object Set]",X=e=>typeof e=="function",we=e=>typeof e=="string",Ns=e=>typeof e=="symbol",ge=e=>e!==null&&typeof e=="object",fr=e=>ge(e)&&X(e.then)&&X(e.catch),dr=Object.prototype.toString,Rn=e=>dr.call(e),Mi=e=>Rn(e).slice(8,-1),hr=e=>Rn(e)==="[object Object]",Os=e=>we(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,Zt=Ms(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),Un=e=>{const t=Object.create(null);return n=>t[n]||(t[n]=e(n))},Ii=/-(\w)/g,Ze=Un(e=>e.replace(Ii,(t,n)=>n?n.toUpperCase():"")),Ai=/\B([A-Z])/g,Kt=Un(e=>e.replace(Ai,"-$1").toLowerCase()),jn=Un(e=>e.charAt(0).toUpperCase()+e.slice(1)),ls=Un(e=>e?`on${jn(e)}`:""),on=(e,t)=>!Object.is(e,t),cs=(e,t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,value:n})},_r=e=>{const t=parseFloat(e);return isNaN(t)?e:t};let ho;const Ni=()=>ho||(ho=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});let Ie;class Oi{constructor(t=!1){this.active=!0,this.effects=[],this.cleanups=[],!t&&Ie&&(this.parent=Ie,this.index=(Ie.scopes||(Ie.scopes=[])).push(this)-1)}run(t){if(this.active){const n=Ie;try{return Ie=this,t()}finally{Ie=n}}}on(){Ie=this}off(){Ie=this.parent}stop(t){if(this.active){let n,s;for(n=0,s=this.effects.length;n{const t=new Set(e);return t.w=0,t.n=0,t},pr=e=>(e.w&ht)>0,vr=e=>(e.n&ht)>0,Di=({deps:e})=>{if(e.length)for(let t=0;t{const{deps:t}=e;if(t.length){let n=0;for(let s=0;s{(f==="length"||f>=s)&&l.push(c)});else switch(n!==void 0&&l.push(i.get(n)),t){case"add":K(e)?Os(n)&&l.push(i.get("length")):(l.push(i.get(St)),At(e)&&l.push(i.get(gs)));break;case"delete":K(e)||(l.push(i.get(St)),At(e)&&l.push(i.get(gs)));break;case"set":At(e)&&l.push(i.get(St));break}if(l.length===1)l[0]&&bs(l[0]);else{const c=[];for(const f of l)f&&c.push(...f);bs(Bs(c))}}function bs(e,t){const n=K(e)?e:[...e];for(const s of n)s.computed&&po(s);for(const s of n)s.computed||po(s)}function po(e,t){(e!==je||e.allowRecurse)&&(e.scheduler?e.scheduler():e.run())}const Ui=Ms("__proto__,__v_isRef,__isVue"),br=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(Ns)),ji=Hs(),zi=Hs(!1,!0),Ki=Hs(!0),vo=Wi();function Wi(){const e={};return["includes","indexOf","lastIndexOf"].forEach(t=>{e[t]=function(...n){const s=ce(this);for(let r=0,i=this.length;r{e[t]=function(...n){Wt();const s=ce(this)[t].apply(this,n);return qt(),s}}),e}function Hs(e=!1,t=!1){return function(s,o,r){if(o==="__v_isReactive")return!e;if(o==="__v_isReadonly")return e;if(o==="__v_isShallow")return t;if(o==="__v_raw"&&r===(e?t?cl:Pr:t?$r:xr).get(s))return s;const i=K(s);if(!e&&i&&se(vo,o))return Reflect.get(vo,o,r);const l=Reflect.get(s,o,r);return(Ns(o)?br.has(o):Ui(o))||(e||Ne(s,"get",o),t)?l:ke(l)?i&&Os(o)?l:l.value:ge(l)?e?Us(l):Kn(l):l}}const qi=yr(),Gi=yr(!0);function yr(e=!1){return function(n,s,o,r){let i=n[s];if(Rt(i)&&ke(i)&&!ke(o))return!1;if(!e&&(!Vn(o)&&!Rt(o)&&(i=ce(i),o=ce(o)),!K(n)&&ke(i)&&!ke(o)))return i.value=o,!0;const l=K(n)&&Os(s)?Number(s)e,zn=e=>Reflect.getPrototypeOf(e);function mn(e,t,n=!1,s=!1){e=e.__v_raw;const o=ce(e),r=ce(t);n||(t!==r&&Ne(o,"get",t),Ne(o,"get",r));const{has:i}=zn(o),l=s?Ds:n?zs:rn;if(i.call(o,t))return l(e.get(t));if(i.call(o,r))return l(e.get(r));e!==o&&e.get(t)}function gn(e,t=!1){const n=this.__v_raw,s=ce(n),o=ce(e);return t||(e!==o&&Ne(s,"has",e),Ne(s,"has",o)),e===o?n.has(e):n.has(e)||n.has(o)}function bn(e,t=!1){return e=e.__v_raw,!t&&Ne(ce(e),"iterate",St),Reflect.get(e,"size",e)}function mo(e){e=ce(e);const t=ce(this);return zn(t).has.call(t,e)||(t.add(e),ot(t,"add",e,e)),this}function go(e,t){t=ce(t);const n=ce(this),{has:s,get:o}=zn(n);let r=s.call(n,e);r||(e=ce(e),r=s.call(n,e));const i=o.call(n,e);return n.set(e,t),r?on(t,i)&&ot(n,"set",e,t):ot(n,"add",e,t),this}function bo(e){const t=ce(this),{has:n,get:s}=zn(t);let o=n.call(t,e);o||(e=ce(e),o=n.call(t,e)),s&&s.call(t,e);const r=t.delete(e);return o&&ot(t,"delete",e,void 0),r}function yo(){const e=ce(this),t=e.size!==0,n=e.clear();return t&&ot(e,"clear",void 0,void 0),n}function yn(e,t){return function(s,o){const r=this,i=r.__v_raw,l=ce(i),c=t?Ds:e?zs:rn;return!e&&Ne(l,"iterate",St),i.forEach((f,h)=>s.call(o,c(f),c(h),r))}}function wn(e,t,n){return function(...s){const o=this.__v_raw,r=ce(o),i=At(r),l=e==="entries"||e===Symbol.iterator&&i,c=e==="keys"&&i,f=o[e](...s),h=n?Ds:t?zs:rn;return!t&&Ne(r,"iterate",c?gs:St),{next(){const{value:m,done:x}=f.next();return x?{value:m,done:x}:{value:l?[h(m[0]),h(m[1])]:h(m),done:x}},[Symbol.iterator](){return this}}}}function it(e){return function(...t){return e==="delete"?!1:this}}function el(){const e={get(r){return mn(this,r)},get size(){return bn(this)},has:gn,add:mo,set:go,delete:bo,clear:yo,forEach:yn(!1,!1)},t={get(r){return mn(this,r,!1,!0)},get size(){return bn(this)},has:gn,add:mo,set:go,delete:bo,clear:yo,forEach:yn(!1,!0)},n={get(r){return mn(this,r,!0)},get size(){return bn(this,!0)},has(r){return gn.call(this,r,!0)},add:it("add"),set:it("set"),delete:it("delete"),clear:it("clear"),forEach:yn(!0,!1)},s={get(r){return mn(this,r,!0,!0)},get size(){return bn(this,!0)},has(r){return gn.call(this,r,!0)},add:it("add"),set:it("set"),delete:it("delete"),clear:it("clear"),forEach:yn(!0,!0)};return["keys","values","entries",Symbol.iterator].forEach(r=>{e[r]=wn(r,!1,!1),n[r]=wn(r,!0,!1),t[r]=wn(r,!1,!0),s[r]=wn(r,!0,!0)}),[e,n,t,s]}const[tl,nl,sl,ol]=el();function Rs(e,t){const n=t?e?ol:sl:e?nl:tl;return(s,o,r)=>o==="__v_isReactive"?!e:o==="__v_isReadonly"?e:o==="__v_raw"?s:Reflect.get(se(n,o)&&o in s?n:s,o,r)}const rl={get:Rs(!1,!1)},il={get:Rs(!1,!0)},ll={get:Rs(!0,!1)},xr=new WeakMap,$r=new WeakMap,Pr=new WeakMap,cl=new WeakMap;function al(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function ul(e){return e.__v_skip||!Object.isExtensible(e)?0:al(Mi(e))}function Kn(e){return Rt(e)?e:js(e,!1,wr,rl,xr)}function fl(e){return js(e,!1,Zi,il,$r)}function Us(e){return js(e,!0,Xi,ll,Pr)}function js(e,t,n,s,o){if(!ge(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const r=o.get(e);if(r)return r;const i=ul(e);if(i===0)return e;const l=new Proxy(e,i===2?s:n);return o.set(e,l),l}function Nt(e){return Rt(e)?Nt(e.__v_raw):!!(e&&e.__v_isReactive)}function Rt(e){return!!(e&&e.__v_isReadonly)}function Vn(e){return!!(e&&e.__v_isShallow)}function kr(e){return Nt(e)||Rt(e)}function ce(e){const t=e&&e.__v_raw;return t?ce(t):e}function en(e){return Sn(e,"__v_skip",!0),e}const rn=e=>ge(e)?Kn(e):e,zs=e=>ge(e)?Us(e):e;function Cr(e){ft&&je&&(e=ce(e),gr(e.dep||(e.dep=Bs())))}function Sr(e,t){e=ce(e),e.dep&&bs(e.dep)}function ke(e){return!!(e&&e.__v_isRef===!0)}function me(e){return Vr(e,!1)}function dl(e){return Vr(e,!0)}function Vr(e,t){return ke(e)?e:new hl(e,t)}class hl{constructor(t,n){this.__v_isShallow=n,this.dep=void 0,this.__v_isRef=!0,this._rawValue=n?t:ce(t),this._value=n?t:rn(t)}get value(){return Cr(this),this._value}set value(t){const n=this.__v_isShallow||Vn(t)||Rt(t);t=n?t:ce(t),on(t,this._rawValue)&&(this._rawValue=t,this._value=n?t:rn(t),Sr(this))}}function _(e){return ke(e)?e.value:e}const _l={get:(e,t,n)=>_(Reflect.get(e,t,n)),set:(e,t,n,s)=>{const o=e[t];return ke(o)&&!ke(n)?(o.value=n,!0):Reflect.set(e,t,n,s)}};function Tr(e){return Nt(e)?e:new Proxy(e,_l)}var Er;class pl{constructor(t,n,s,o){this._setter=n,this.dep=void 0,this.__v_isRef=!0,this[Er]=!1,this._dirty=!0,this.effect=new Fs(t,()=>{this._dirty||(this._dirty=!0,Sr(this))}),this.effect.computed=this,this.effect.active=this._cacheable=!o,this.__v_isReadonly=s}get value(){const t=ce(this);return Cr(t),(t._dirty||!t._cacheable)&&(t._dirty=!1,t._value=t.effect.run()),t._value}set value(t){this._setter(t)}}Er="__v_isReadonly";function vl(e,t,n=!1){let s,o;const r=X(e);return r?(s=e,o=Ke):(s=e.get,o=e.set),new pl(s,o,r||!o,n)}function dt(e,t,n,s){let o;try{o=s?e(...s):e()}catch(r){Wn(r,t,n)}return o}function He(e,t,n,s){if(X(e)){const r=dt(e,t,n,s);return r&&fr(r)&&r.catch(i=>{Wn(i,t,n)}),r}const o=[];for(let r=0;r>>1;cn(Pe[s])Je&&Pe.splice(t,1)}function yl(e){K(e)?Ot.push(...e):(!nt||!nt.includes(e,e.allowRecurse?$t+1:$t))&&Ot.push(e),Mr()}function wo(e,t=ln?Je+1:0){for(;tcn(n)-cn(s)),$t=0;$te.id==null?1/0:e.id,wl=(e,t)=>{const n=cn(e)-cn(t);if(n===0){if(e.pre&&!t.pre)return-1;if(t.pre&&!e.pre)return 1}return n};function Ir(e){ys=!1,ln=!0,Pe.sort(wl);const t=Ke;try{for(Je=0;JeC.trim())),m&&(o=n.map(_r))}let l,c=s[l=ls(t)]||s[l=ls(Ze(t))];!c&&r&&(c=s[l=ls(Kt(t))]),c&&He(c,e,6,o);const f=s[l+"Once"];if(f){if(!e.emitted)e.emitted={};else if(e.emitted[l])return;e.emitted[l]=!0,He(f,e,6,o)}}function Ar(e,t,n=!1){const s=t.emitsCache,o=s.get(e);if(o!==void 0)return o;const r=e.emits;let i={},l=!1;if(!X(e)){const c=f=>{const h=Ar(f,t,!0);h&&(l=!0,$e(i,h))};!n&&t.mixins.length&&t.mixins.forEach(c),e.extends&&c(e.extends),e.mixins&&e.mixins.forEach(c)}return!r&&!l?(ge(e)&&s.set(e,null),null):(K(r)?r.forEach(c=>i[c]=null):$e(i,r),ge(e)&&s.set(e,i),i)}function Gn(e,t){return!e||!hn(t)?!1:(t=t.slice(2).replace(/Once$/,""),se(e,t[0].toLowerCase()+t.slice(1))||se(e,Kt(t))||se(e,t))}let Ve=null,Yn=null;function En(e){const t=Ve;return Ve=e,Yn=e&&e.type.__scopeId||null,t}function We(e){Yn=e}function qe(){Yn=null}function I(e,t=Ve,n){if(!t||e._n)return e;const s=(...o)=>{s._d&&Mo(-1);const r=En(t),i=e(...o);return En(r),s._d&&Mo(1),i};return s._n=!0,s._c=!0,s._d=!0,s}function as(e){const{type:t,vnode:n,proxy:s,withProxy:o,props:r,propsOptions:[i],slots:l,attrs:c,emit:f,render:h,renderCache:m,data:x,setupState:C,ctx:j,inheritAttrs:F}=e;let J,g;const T=En(e);try{if(n.shapeFlag&4){const G=o||s;J=Ue(h.call(G,G,m,r,C,x,j)),g=c}else{const G=t;J=Ue(G.length>1?G(r,{attrs:c,slots:l,emit:f}):G(r,null)),g=t.props?c:$l(c)}}catch(G){tn.length=0,Wn(G,e,1),J=V(Ae)}let z=J;if(g&&F!==!1){const G=Object.keys(g),{shapeFlag:ne}=z;G.length&&ne&7&&(i&&G.some(Is)&&(g=Pl(g,i)),z=_t(z,g))}return n.dirs&&(z=_t(z),z.dirs=z.dirs?z.dirs.concat(n.dirs):n.dirs),n.transition&&(z.transition=n.transition),J=z,En(T),J}const $l=e=>{let t;for(const n in e)(n==="class"||n==="style"||hn(n))&&((t||(t={}))[n]=e[n]);return t},Pl=(e,t)=>{const n={};for(const s in e)(!Is(s)||!(s.slice(9)in t))&&(n[s]=e[s]);return n};function kl(e,t,n){const{props:s,children:o,component:r}=e,{props:i,children:l,patchFlag:c}=t,f=r.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&c>=0){if(c&1024)return!0;if(c&16)return s?xo(s,i,f):!!i;if(c&8){const h=t.dynamicProps;for(let m=0;me.__isSuspense;function Nr(e,t){t&&t.pendingBranch?K(e)?t.effects.push(...e):t.effects.push(e):yl(e)}function Qn(e,t){if(xe){let n=xe.provides;const s=xe.parent&&xe.parent.provides;s===n&&(n=xe.provides=Object.create(s)),n[e]=t}}function Xe(e,t,n=!1){const s=xe||Ve;if(s){const o=s.parent==null?s.vnode.appContext&&s.vnode.appContext.provides:s.parent.provides;if(o&&e in o)return o[e];if(arguments.length>1)return n&&X(t)?t.call(s.proxy):t}}function Ut(e,t){return Jn(e,null,t)}function Or(e,t){return Jn(e,null,{flush:"post"})}const $o={};function st(e,t,n){return Jn(e,t,n)}function Jn(e,t,{immediate:n,deep:s,flush:o,onTrack:r,onTrigger:i}=ve){const l=xe;let c,f=!1,h=!1;if(ke(e)?(c=()=>e.value,f=Vn(e)):Nt(e)?(c=()=>e,s=!0):K(e)?(h=!0,f=e.some(g=>Nt(g)||Vn(g)),c=()=>e.map(g=>{if(ke(g))return g.value;if(Nt(g))return Mt(g);if(X(g))return dt(g,l,2)})):X(e)?t?c=()=>dt(e,l,2):c=()=>{if(!(l&&l.isUnmounted))return m&&m(),He(e,l,3,[x])}:c=Ke,t&&s){const g=c;c=()=>Mt(g())}let m,x=g=>{m=J.onStop=()=>{dt(g,l,4)}};if(fn)return x=Ke,t?n&&He(t,l,3,[c(),h?[]:void 0,x]):c(),Ke;let C=h?[]:$o;const j=()=>{if(!!J.active)if(t){const g=J.run();(s||f||(h?g.some((T,z)=>on(T,C[z])):on(g,C)))&&(m&&m(),He(t,l,3,[g,C===$o?void 0:C,x]),C=g)}else J.run()};j.allowRecurse=!!t;let F;o==="sync"?F=j:o==="post"?F=()=>Te(j,l&&l.suspense):(j.pre=!0,l&&(j.id=l.uid),F=()=>Ws(j));const J=new Fs(c,F);return t?n?j():C=J.run():o==="post"?Te(J.run.bind(J),l&&l.suspense):J.run(),()=>{J.stop(),l&&l.scope&&As(l.scope.effects,J)}}function Vl(e,t,n){const s=this.proxy,o=we(e)?e.includes(".")?Br(s,e):()=>s[e]:e.bind(s,s);let r;X(t)?r=t:(r=t.handler,n=t);const i=xe;jt(this);const l=Jn(o,r.bind(s),n);return i?jt(i):Vt(),l}function Br(e,t){const n=t.split(".");return()=>{let s=e;for(let o=0;o{Mt(n,t)});else if(hr(e))for(const n in e)Mt(e[n],t);return e}function Tl(){const e={isMounted:!1,isLeaving:!1,isUnmounting:!1,leavingVNodes:new Map};return De(()=>{e.isMounted=!0}),Ur(()=>{e.isUnmounting=!0}),e}const Be=[Function,Array],El={name:"BaseTransition",props:{mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:Be,onEnter:Be,onAfterEnter:Be,onEnterCancelled:Be,onBeforeLeave:Be,onLeave:Be,onAfterLeave:Be,onLeaveCancelled:Be,onBeforeAppear:Be,onAppear:Be,onAfterAppear:Be,onAppearCancelled:Be},setup(e,{slots:t}){const n=Zs(),s=Tl();let o;return()=>{const r=t.default&&Dr(t.default(),!0);if(!r||!r.length)return;let i=r[0];if(r.length>1){for(const F of r)if(F.type!==Ae){i=F;break}}const l=ce(e),{mode:c}=l;if(s.isLeaving)return us(i);const f=Po(i);if(!f)return us(i);const h=ws(f,l,s,n);xs(f,h);const m=n.subTree,x=m&&Po(m);let C=!1;const{getTransitionKey:j}=f.type;if(j){const F=j();o===void 0?o=F:F!==o&&(o=F,C=!0)}if(x&&x.type!==Ae&&(!Pt(f,x)||C)){const F=ws(x,l,s,n);if(xs(x,F),c==="out-in")return s.isLeaving=!0,F.afterLeave=()=>{s.isLeaving=!1,n.update()},us(i);c==="in-out"&&f.type!==Ae&&(F.delayLeave=(J,g,T)=>{const z=Hr(s,x);z[String(x.key)]=x,J._leaveCb=()=>{g(),J._leaveCb=void 0,delete h.delayedLeave},h.delayedLeave=T})}return i}}},Fr=El;function Hr(e,t){const{leavingVNodes:n}=e;let s=n.get(t.type);return s||(s=Object.create(null),n.set(t.type,s)),s}function ws(e,t,n,s){const{appear:o,mode:r,persisted:i=!1,onBeforeEnter:l,onEnter:c,onAfterEnter:f,onEnterCancelled:h,onBeforeLeave:m,onLeave:x,onAfterLeave:C,onLeaveCancelled:j,onBeforeAppear:F,onAppear:J,onAfterAppear:g,onAppearCancelled:T}=t,z=String(e.key),G=Hr(n,e),ne=(M,Z)=>{M&&He(M,s,9,Z)},de=(M,Z)=>{const Y=Z[1];ne(M,Z),K(M)?M.every(le=>le.length<=1)&&Y():M.length<=1&&Y()},oe={mode:r,persisted:i,beforeEnter(M){let Z=l;if(!n.isMounted)if(o)Z=F||l;else return;M._leaveCb&&M._leaveCb(!0);const Y=G[z];Y&&Pt(e,Y)&&Y.el._leaveCb&&Y.el._leaveCb(),ne(Z,[M])},enter(M){let Z=c,Y=f,le=h;if(!n.isMounted)if(o)Z=J||c,Y=g||f,le=T||h;else return;let A=!1;const ee=M._enterCb=H=>{A||(A=!0,H?ne(le,[M]):ne(Y,[M]),oe.delayedLeave&&oe.delayedLeave(),M._enterCb=void 0)};Z?de(Z,[M,ee]):ee()},leave(M,Z){const Y=String(e.key);if(M._enterCb&&M._enterCb(!0),n.isUnmounting)return Z();ne(m,[M]);let le=!1;const A=M._leaveCb=ee=>{le||(le=!0,Z(),ee?ne(j,[M]):ne(C,[M]),M._leaveCb=void 0,G[Y]===e&&delete G[Y])};G[Y]=e,x?de(x,[M,A]):A()},clone(M){return ws(M,t,n,s)}};return oe}function us(e){if(Xn(e))return e=_t(e),e.children=null,e}function Po(e){return Xn(e)?e.children?e.children[0]:void 0:e}function xs(e,t){e.shapeFlag&6&&e.component?xs(e.component.subTree,t):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function Dr(e,t=!1,n){let s=[],o=0;for(let r=0;r1)for(let r=0;r!!e.type.__asyncLoader,Xn=e=>e.type.__isKeepAlive;function Ll(e,t){Rr(e,"a",t)}function Ml(e,t){Rr(e,"da",t)}function Rr(e,t,n=xe){const s=e.__wdc||(e.__wdc=()=>{let o=n;for(;o;){if(o.isDeactivated)return;o=o.parent}return e()});if(Zn(t,s,n),n){let o=n.parent;for(;o&&o.parent;)Xn(o.parent.vnode)&&Il(s,t,n,o),o=o.parent}}function Il(e,t,n,s){const o=Zn(t,e,s,!0);pt(()=>{As(s[t],o)},n)}function Zn(e,t,n=xe,s=!1){if(n){const o=n[e]||(n[e]=[]),r=t.__weh||(t.__weh=(...i)=>{if(n.isUnmounted)return;Wt(),jt(n);const l=He(t,n,e,i);return Vt(),qt(),l});return s?o.unshift(r):o.push(r),r}}const rt=e=>(t,n=xe)=>(!fn||e==="sp")&&Zn(e,(...s)=>t(...s),n),Al=rt("bm"),De=rt("m"),Nl=rt("bu"),qs=rt("u"),Ur=rt("bum"),pt=rt("um"),Ol=rt("sp"),Bl=rt("rtg"),Fl=rt("rtc");function Hl(e,t=xe){Zn("ec",e,t)}function Qe(e,t,n,s){const o=e.dirs,r=t&&t.dirs;for(let i=0;it(i,l,void 0,r&&r[l]));else{const i=Object.keys(e);o=new Array(i.length);for(let l=0,c=i.length;lAn(t)?!(t.type===Ae||t.type===q&&!Kr(t.children)):!0)?e:null}const $s=e=>e?ni(e)?eo(e)||e.proxy:$s(e.parent):null,Ln=$e(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>$s(e.parent),$root:e=>$s(e.root),$emit:e=>e.emit,$options:e=>Qs(e),$forceUpdate:e=>e.f||(e.f=()=>Ws(e.update)),$nextTick:e=>e.n||(e.n=qn.bind(e.proxy)),$watch:e=>Vl.bind(e)}),Dl={get({_:e},t){const{ctx:n,setupState:s,data:o,props:r,accessCache:i,type:l,appContext:c}=e;let f;if(t[0]!=="$"){const C=i[t];if(C!==void 0)switch(C){case 1:return s[t];case 2:return o[t];case 4:return n[t];case 3:return r[t]}else{if(s!==ve&&se(s,t))return i[t]=1,s[t];if(o!==ve&&se(o,t))return i[t]=2,o[t];if((f=e.propsOptions[0])&&se(f,t))return i[t]=3,r[t];if(n!==ve&&se(n,t))return i[t]=4,n[t];Ps&&(i[t]=0)}}const h=Ln[t];let m,x;if(h)return t==="$attrs"&&Ne(e,"get",t),h(e);if((m=l.__cssModules)&&(m=m[t]))return m;if(n!==ve&&se(n,t))return i[t]=4,n[t];if(x=c.config.globalProperties,se(x,t))return x[t]},set({_:e},t,n){const{data:s,setupState:o,ctx:r}=e;return o!==ve&&se(o,t)?(o[t]=n,!0):s!==ve&&se(s,t)?(s[t]=n,!0):se(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(r[t]=n,!0)},has({_:{data:e,setupState:t,accessCache:n,ctx:s,appContext:o,propsOptions:r}},i){let l;return!!n[i]||e!==ve&&se(e,i)||t!==ve&&se(t,i)||(l=r[0])&&se(l,i)||se(s,i)||se(Ln,i)||se(o.config.globalProperties,i)},defineProperty(e,t,n){return n.get!=null?e._.accessCache[t]=0:se(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}};let Ps=!0;function Rl(e){const t=Qs(e),n=e.proxy,s=e.ctx;Ps=!1,t.beforeCreate&&Co(t.beforeCreate,e,"bc");const{data:o,computed:r,methods:i,watch:l,provide:c,inject:f,created:h,beforeMount:m,mounted:x,beforeUpdate:C,updated:j,activated:F,deactivated:J,beforeDestroy:g,beforeUnmount:T,destroyed:z,unmounted:G,render:ne,renderTracked:de,renderTriggered:oe,errorCaptured:M,serverPrefetch:Z,expose:Y,inheritAttrs:le,components:A,directives:ee,filters:H}=t;if(f&&Ul(f,s,null,e.appContext.config.unwrapInjectedRef),i)for(const be in i){const _e=i[be];X(_e)&&(s[be]=_e.bind(n))}if(o){const be=o.call(n,n);ge(be)&&(e.data=Kn(be))}if(Ps=!0,r)for(const be in r){const _e=r[be],mt=X(_e)?_e.bind(n,n):X(_e.get)?_e.get.bind(n,n):Ke,pn=!X(_e)&&X(_e.set)?_e.set.bind(n):Ke,gt=re({get:mt,set:pn});Object.defineProperty(s,be,{enumerable:!0,configurable:!0,get:()=>gt.value,set:Ge=>gt.value=Ge})}if(l)for(const be in l)Wr(l[be],s,n,be);if(c){const be=X(c)?c.call(n):c;Reflect.ownKeys(be).forEach(_e=>{Qn(_e,be[_e])})}h&&Co(h,e,"c");function ue(be,_e){K(_e)?_e.forEach(mt=>be(mt.bind(n))):_e&&be(_e.bind(n))}if(ue(Al,m),ue(De,x),ue(Nl,C),ue(qs,j),ue(Ll,F),ue(Ml,J),ue(Hl,M),ue(Fl,de),ue(Bl,oe),ue(Ur,T),ue(pt,G),ue(Ol,Z),K(Y))if(Y.length){const be=e.exposed||(e.exposed={});Y.forEach(_e=>{Object.defineProperty(be,_e,{get:()=>n[_e],set:mt=>n[_e]=mt})})}else e.exposed||(e.exposed={});ne&&e.render===Ke&&(e.render=ne),le!=null&&(e.inheritAttrs=le),A&&(e.components=A),ee&&(e.directives=ee)}function Ul(e,t,n=Ke,s=!1){K(e)&&(e=ks(e));for(const o in e){const r=e[o];let i;ge(r)?"default"in r?i=Xe(r.from||o,r.default,!0):i=Xe(r.from||o):i=Xe(r),ke(i)&&s?Object.defineProperty(t,o,{enumerable:!0,configurable:!0,get:()=>i.value,set:l=>i.value=l}):t[o]=i}}function Co(e,t,n){He(K(e)?e.map(s=>s.bind(t.proxy)):e.bind(t.proxy),t,n)}function Wr(e,t,n,s){const o=s.includes(".")?Br(n,s):()=>n[s];if(we(e)){const r=t[e];X(r)&&st(o,r)}else if(X(e))st(o,e.bind(n));else if(ge(e))if(K(e))e.forEach(r=>Wr(r,t,n,s));else{const r=X(e.handler)?e.handler.bind(n):t[e.handler];X(r)&&st(o,r,e)}}function Qs(e){const t=e.type,{mixins:n,extends:s}=t,{mixins:o,optionsCache:r,config:{optionMergeStrategies:i}}=e.appContext,l=r.get(t);let c;return l?c=l:!o.length&&!n&&!s?c=t:(c={},o.length&&o.forEach(f=>Mn(c,f,i,!0)),Mn(c,t,i)),ge(t)&&r.set(t,c),c}function Mn(e,t,n,s=!1){const{mixins:o,extends:r}=t;r&&Mn(e,r,n,!0),o&&o.forEach(i=>Mn(e,i,n,!0));for(const i in t)if(!(s&&i==="expose")){const l=jl[i]||n&&n[i];e[i]=l?l(e[i],t[i]):t[i]}return e}const jl={data:So,props:xt,emits:xt,methods:xt,computed:xt,beforeCreate:Se,created:Se,beforeMount:Se,mounted:Se,beforeUpdate:Se,updated:Se,beforeDestroy:Se,beforeUnmount:Se,destroyed:Se,unmounted:Se,activated:Se,deactivated:Se,errorCaptured:Se,serverPrefetch:Se,components:xt,directives:xt,watch:Kl,provide:So,inject:zl};function So(e,t){return t?e?function(){return $e(X(e)?e.call(this,this):e,X(t)?t.call(this,this):t)}:t:e}function zl(e,t){return xt(ks(e),ks(t))}function ks(e){if(K(e)){const t={};for(let n=0;n0)&&!(i&16)){if(i&8){const h=e.vnode.dynamicProps;for(let m=0;m{c=!0;const[x,C]=Gr(m,t,!0);$e(i,x),C&&l.push(...C)};!n&&t.mixins.length&&t.mixins.forEach(h),e.extends&&h(e.extends),e.mixins&&e.mixins.forEach(h)}if(!r&&!c)return ge(e)&&s.set(e,It),It;if(K(r))for(let h=0;h-1,C[1]=F<0||j-1||se(C,"default"))&&l.push(m)}}}const f=[i,l];return ge(e)&&s.set(e,f),f}function Vo(e){return e[0]!=="$"}function To(e){const t=e&&e.toString().match(/^\s*function (\w+)/);return t?t[1]:e===null?"null":""}function Eo(e,t){return To(e)===To(t)}function Lo(e,t){return K(t)?t.findIndex(n=>Eo(n,e)):X(t)&&Eo(t,e)?0:-1}const Yr=e=>e[0]==="_"||e==="$stable",Js=e=>K(e)?e.map(Ue):[Ue(e)],Gl=(e,t,n)=>{if(t._n)return t;const s=I((...o)=>Js(t(...o)),n);return s._c=!1,s},Qr=(e,t,n)=>{const s=e._ctx;for(const o in e){if(Yr(o))continue;const r=e[o];if(X(r))t[o]=Gl(o,r,s);else if(r!=null){const i=Js(r);t[o]=()=>i}}},Jr=(e,t)=>{const n=Js(t);e.slots.default=()=>n},Yl=(e,t)=>{if(e.vnode.shapeFlag&32){const n=t._;n?(e.slots=ce(t),Sn(t,"_",n)):Qr(t,e.slots={})}else e.slots={},t&&Jr(e,t);Sn(e.slots,es,1)},Ql=(e,t,n)=>{const{vnode:s,slots:o}=e;let r=!0,i=ve;if(s.shapeFlag&32){const l=t._;l?n&&l===1?r=!1:($e(o,t),!n&&l===1&&delete o._):(r=!t.$stable,Qr(t,o)),i=t}else t&&(Jr(e,t),i={default:1});if(r)for(const l in o)!Yr(l)&&!(l in i)&&delete o[l]};function Xr(){return{app:null,config:{isNativeTag:Ti,performance:!1,globalProperties:{},optionMergeStrategies:{},errorHandler:void 0,warnHandler:void 0,compilerOptions:{}},mixins:[],components:{},directives:{},provides:Object.create(null),optionsCache:new WeakMap,propsCache:new WeakMap,emitsCache:new WeakMap}}let Jl=0;function Xl(e,t){return function(s,o=null){X(s)||(s=Object.assign({},s)),o!=null&&!ge(o)&&(o=null);const r=Xr(),i=new Set;let l=!1;const c=r.app={_uid:Jl++,_component:s,_props:o,_container:null,_context:r,_instance:null,version:mc,get config(){return r.config},set config(f){},use(f,...h){return i.has(f)||(f&&X(f.install)?(i.add(f),f.install(c,...h)):X(f)&&(i.add(f),f(c,...h))),c},mixin(f){return r.mixins.includes(f)||r.mixins.push(f),c},component(f,h){return h?(r.components[f]=h,c):r.components[f]},directive(f,h){return h?(r.directives[f]=h,c):r.directives[f]},mount(f,h,m){if(!l){const x=V(s,o);return x.appContext=r,h&&t?t(x,f):e(x,f,m),l=!0,c._container=f,f.__vue_app__=c,eo(x.component)||x.component.proxy}},unmount(){l&&(e(null,c._container),delete c._container.__vue_app__)},provide(f,h){return r.provides[f]=h,c}};return c}}function In(e,t,n,s,o=!1){if(K(e)){e.forEach((x,C)=>In(x,t&&(K(t)?t[C]:t),n,s,o));return}if(Bt(s)&&!o)return;const r=s.shapeFlag&4?eo(s.component)||s.component.proxy:s.el,i=o?null:r,{i:l,r:c}=e,f=t&&t.r,h=l.refs===ve?l.refs={}:l.refs,m=l.setupState;if(f!=null&&f!==c&&(we(f)?(h[f]=null,se(m,f)&&(m[f]=null)):ke(f)&&(f.value=null)),X(c))dt(c,l,12,[i,h]);else{const x=we(c),C=ke(c);if(x||C){const j=()=>{if(e.f){const F=x?h[c]:c.value;o?K(F)&&As(F,r):K(F)?F.includes(r)||F.push(r):x?(h[c]=[r],se(m,c)&&(m[c]=h[c])):(c.value=[r],e.k&&(h[e.k]=c.value))}else x?(h[c]=i,se(m,c)&&(m[c]=i)):C&&(c.value=i,e.k&&(h[e.k]=i))};i?(j.id=-1,Te(j,n)):j()}}}let lt=!1;const xn=e=>/svg/.test(e.namespaceURI)&&e.tagName!=="foreignObject",$n=e=>e.nodeType===8;function Zl(e){const{mt:t,p:n,o:{patchProp:s,createText:o,nextSibling:r,parentNode:i,remove:l,insert:c,createComment:f}}=e,h=(g,T)=>{if(!T.hasChildNodes()){n(null,g,T),Tn(),T._vnode=g;return}lt=!1,m(T.firstChild,g,null,null,null),Tn(),T._vnode=g,lt&&console.error("Hydration completed but contains mismatches.")},m=(g,T,z,G,ne,de=!1)=>{const oe=$n(g)&&g.data==="[",M=()=>F(g,T,z,G,ne,oe),{type:Z,ref:Y,shapeFlag:le,patchFlag:A}=T;let ee=g.nodeType;T.el=g,A===-2&&(de=!1,T.dynamicChildren=null);let H=null;switch(Z){case an:ee!==3?T.children===""?(c(T.el=o(""),i(g),g),H=g):H=M():(g.data!==T.children&&(lt=!0,g.data=T.children),H=r(g));break;case Ae:ee!==8||oe?H=M():H=r(g);break;case Ft:if(oe&&(g=r(g),ee=g.nodeType),ee===1||ee===3){H=g;const Le=!T.children.length;for(let ue=0;ue{de=de||!!T.dynamicChildren;const{type:oe,props:M,patchFlag:Z,shapeFlag:Y,dirs:le}=T,A=oe==="input"&&le||oe==="option";if(A||Z!==-1){if(le&&Qe(T,null,z,"created"),M)if(A||!de||Z&48)for(const H in M)(A&&H.endsWith("value")||hn(H)&&!Zt(H))&&s(g,H,null,M[H],!1,void 0,z);else M.onClick&&s(g,"onClick",null,M.onClick,!1,void 0,z);let ee;if((ee=M&&M.onVnodeBeforeMount)&&Fe(ee,z,T),le&&Qe(T,null,z,"beforeMount"),((ee=M&&M.onVnodeMounted)||le)&&Nr(()=>{ee&&Fe(ee,z,T),le&&Qe(T,null,z,"mounted")},G),Y&16&&!(M&&(M.innerHTML||M.textContent))){let H=C(g.firstChild,T,g,z,G,ne,de);for(;H;){lt=!0;const Le=H;H=H.nextSibling,l(Le)}}else Y&8&&g.textContent!==T.children&&(lt=!0,g.textContent=T.children)}return g.nextSibling},C=(g,T,z,G,ne,de,oe)=>{oe=oe||!!T.dynamicChildren;const M=T.children,Z=M.length;for(let Y=0;Y{const{slotScopeIds:oe}=T;oe&&(ne=ne?ne.concat(oe):oe);const M=i(g),Z=C(r(g),T,M,z,G,ne,de);return Z&&$n(Z)&&Z.data==="]"?r(T.anchor=Z):(lt=!0,c(T.anchor=f("]"),M,Z),Z)},F=(g,T,z,G,ne,de)=>{if(lt=!0,T.el=null,de){const Z=J(g);for(;;){const Y=r(g);if(Y&&Y!==Z)l(Y);else break}}const oe=r(g),M=i(g);return l(g),n(null,T,M,oe,z,G,xn(M),ne),oe},J=g=>{let T=0;for(;g;)if(g=r(g),g&&$n(g)&&(g.data==="["&&T++,g.data==="]")){if(T===0)return r(g);T--}return g};return[h,m]}const Te=Nr;function ec(e){return tc(e,Zl)}function tc(e,t){const n=Ni();n.__VUE__=!0;const{insert:s,remove:o,patchProp:r,createElement:i,createText:l,createComment:c,setText:f,setElementText:h,parentNode:m,nextSibling:x,setScopeId:C=Ke,insertStaticContent:j}=e,F=(a,u,p,w=null,y=null,k=null,L=!1,P=null,S=!!u.dynamicChildren)=>{if(a===u)return;a&&!Pt(a,u)&&(w=vn(a),Ge(a,y,k,!0),a=null),u.patchFlag===-2&&(S=!1,u.dynamicChildren=null);const{type:$,ref:D,shapeFlag:N}=u;switch($){case an:J(a,u,p,w);break;case Ae:g(a,u,p,w);break;case Ft:a==null&&T(u,p,w,L);break;case q:A(a,u,p,w,y,k,L,P,S);break;default:N&1?ne(a,u,p,w,y,k,L,P,S):N&6?ee(a,u,p,w,y,k,L,P,S):(N&64||N&128)&&$.process(a,u,p,w,y,k,L,P,S,Et)}D!=null&&y&&In(D,a&&a.ref,k,u||a,!u)},J=(a,u,p,w)=>{if(a==null)s(u.el=l(u.children),p,w);else{const y=u.el=a.el;u.children!==a.children&&f(y,u.children)}},g=(a,u,p,w)=>{a==null?s(u.el=c(u.children||""),p,w):u.el=a.el},T=(a,u,p,w)=>{[a.el,a.anchor]=j(a.children,u,p,w,a.el,a.anchor)},z=({el:a,anchor:u},p,w)=>{let y;for(;a&&a!==u;)y=x(a),s(a,p,w),a=y;s(u,p,w)},G=({el:a,anchor:u})=>{let p;for(;a&&a!==u;)p=x(a),o(a),a=p;o(u)},ne=(a,u,p,w,y,k,L,P,S)=>{L=L||u.type==="svg",a==null?de(u,p,w,y,k,L,P,S):Z(a,u,y,k,L,P,S)},de=(a,u,p,w,y,k,L,P)=>{let S,$;const{type:D,props:N,shapeFlag:R,transition:W,dirs:te}=a;if(S=a.el=i(a.type,k,N&&N.is,N),R&8?h(S,a.children):R&16&&M(a.children,S,null,w,y,k&&D!=="foreignObject",L,P),te&&Qe(a,null,w,"created"),N){for(const fe in N)fe!=="value"&&!Zt(fe)&&r(S,fe,null,N[fe],k,a.children,w,y,tt);"value"in N&&r(S,"value",null,N.value),($=N.onVnodeBeforeMount)&&Fe($,w,a)}oe(S,a,a.scopeId,L,w),te&&Qe(a,null,w,"beforeMount");const pe=(!y||y&&!y.pendingBranch)&&W&&!W.persisted;pe&&W.beforeEnter(S),s(S,u,p),(($=N&&N.onVnodeMounted)||pe||te)&&Te(()=>{$&&Fe($,w,a),pe&&W.enter(S),te&&Qe(a,null,w,"mounted")},y)},oe=(a,u,p,w,y)=>{if(p&&C(a,p),w)for(let k=0;k{for(let $=S;${const P=u.el=a.el;let{patchFlag:S,dynamicChildren:$,dirs:D}=u;S|=a.patchFlag&16;const N=a.props||ve,R=u.props||ve;let W;p&&bt(p,!1),(W=R.onVnodeBeforeUpdate)&&Fe(W,p,u,a),D&&Qe(u,a,p,"beforeUpdate"),p&&bt(p,!0);const te=y&&u.type!=="foreignObject";if($?Y(a.dynamicChildren,$,P,p,w,te,k):L||_e(a,u,P,null,p,w,te,k,!1),S>0){if(S&16)le(P,u,N,R,p,w,y);else if(S&2&&N.class!==R.class&&r(P,"class",null,R.class,y),S&4&&r(P,"style",N.style,R.style,y),S&8){const pe=u.dynamicProps;for(let fe=0;fe{W&&Fe(W,p,u,a),D&&Qe(u,a,p,"updated")},w)},Y=(a,u,p,w,y,k,L)=>{for(let P=0;P{if(p!==w){if(p!==ve)for(const P in p)!Zt(P)&&!(P in w)&&r(a,P,p[P],null,L,u.children,y,k,tt);for(const P in w){if(Zt(P))continue;const S=w[P],$=p[P];S!==$&&P!=="value"&&r(a,P,$,S,L,u.children,y,k,tt)}"value"in w&&r(a,"value",p.value,w.value)}},A=(a,u,p,w,y,k,L,P,S)=>{const $=u.el=a?a.el:l(""),D=u.anchor=a?a.anchor:l("");let{patchFlag:N,dynamicChildren:R,slotScopeIds:W}=u;W&&(P=P?P.concat(W):W),a==null?(s($,p,w),s(D,p,w),M(u.children,p,D,y,k,L,P,S)):N>0&&N&64&&R&&a.dynamicChildren?(Y(a.dynamicChildren,R,p,y,k,L,P),(u.key!=null||y&&u===y.subTree)&&Zr(a,u,!0)):_e(a,u,p,D,y,k,L,P,S)},ee=(a,u,p,w,y,k,L,P,S)=>{u.slotScopeIds=P,a==null?u.shapeFlag&512?y.ctx.activate(u,p,w,L,S):H(u,p,w,y,k,L,S):Le(a,u,S)},H=(a,u,p,w,y,k,L)=>{const P=a.component=uc(a,w,y);if(Xn(a)&&(P.ctx.renderer=Et),fc(P),P.asyncDep){if(y&&y.registerDep(P,ue),!a.el){const S=P.subTree=V(Ae);g(null,S,u,p)}return}ue(P,a,u,p,y,k,L)},Le=(a,u,p)=>{const w=u.component=a.component;if(kl(a,u,p))if(w.asyncDep&&!w.asyncResolved){be(w,u,p);return}else w.next=u,bl(w.update),w.update();else u.el=a.el,w.vnode=u},ue=(a,u,p,w,y,k,L)=>{const P=()=>{if(a.isMounted){let{next:D,bu:N,u:R,parent:W,vnode:te}=a,pe=D,fe;bt(a,!1),D?(D.el=te.el,be(a,D,L)):D=te,N&&cs(N),(fe=D.props&&D.props.onVnodeBeforeUpdate)&&Fe(fe,W,D,te),bt(a,!0);const ye=as(a),Re=a.subTree;a.subTree=ye,F(Re,ye,m(Re.el),vn(Re),a,y,k),D.el=ye.el,pe===null&&Cl(a,ye.el),R&&Te(R,y),(fe=D.props&&D.props.onVnodeUpdated)&&Te(()=>Fe(fe,W,D,te),y)}else{let D;const{el:N,props:R}=u,{bm:W,m:te,parent:pe}=a,fe=Bt(u);if(bt(a,!1),W&&cs(W),!fe&&(D=R&&R.onVnodeBeforeMount)&&Fe(D,pe,u),bt(a,!0),N&&is){const ye=()=>{a.subTree=as(a),is(N,a.subTree,a,y,null)};fe?u.type.__asyncLoader().then(()=>!a.isUnmounted&&ye()):ye()}else{const ye=a.subTree=as(a);F(null,ye,p,w,a,y,k),u.el=ye.el}if(te&&Te(te,y),!fe&&(D=R&&R.onVnodeMounted)){const ye=u;Te(()=>Fe(D,pe,ye),y)}(u.shapeFlag&256||pe&&Bt(pe.vnode)&&pe.vnode.shapeFlag&256)&&a.a&&Te(a.a,y),a.isMounted=!0,u=p=w=null}},S=a.effect=new Fs(P,()=>Ws($),a.scope),$=a.update=()=>S.run();$.id=a.uid,bt(a,!0),$()},be=(a,u,p)=>{u.component=a;const w=a.vnode.props;a.vnode=u,a.next=null,ql(a,u.props,w,p),Ql(a,u.children,p),Wt(),wo(),qt()},_e=(a,u,p,w,y,k,L,P,S=!1)=>{const $=a&&a.children,D=a?a.shapeFlag:0,N=u.children,{patchFlag:R,shapeFlag:W}=u;if(R>0){if(R&128){pn($,N,p,w,y,k,L,P,S);return}else if(R&256){mt($,N,p,w,y,k,L,P,S);return}}W&8?(D&16&&tt($,y,k),N!==$&&h(p,N)):D&16?W&16?pn($,N,p,w,y,k,L,P,S):tt($,y,k,!0):(D&8&&h(p,""),W&16&&M(N,p,w,y,k,L,P,S))},mt=(a,u,p,w,y,k,L,P,S)=>{a=a||It,u=u||It;const $=a.length,D=u.length,N=Math.min($,D);let R;for(R=0;RD?tt(a,y,k,!0,!1,N):M(u,p,w,y,k,L,P,S,N)},pn=(a,u,p,w,y,k,L,P,S)=>{let $=0;const D=u.length;let N=a.length-1,R=D-1;for(;$<=N&&$<=R;){const W=a[$],te=u[$]=S?ut(u[$]):Ue(u[$]);if(Pt(W,te))F(W,te,p,null,y,k,L,P,S);else break;$++}for(;$<=N&&$<=R;){const W=a[N],te=u[R]=S?ut(u[R]):Ue(u[R]);if(Pt(W,te))F(W,te,p,null,y,k,L,P,S);else break;N--,R--}if($>N){if($<=R){const W=R+1,te=WR)for(;$<=N;)Ge(a[$],y,k,!0),$++;else{const W=$,te=$,pe=new Map;for($=te;$<=R;$++){const Me=u[$]=S?ut(u[$]):Ue(u[$]);Me.key!=null&&pe.set(Me.key,$)}let fe,ye=0;const Re=R-te+1;let Lt=!1,ao=0;const Qt=new Array(Re);for($=0;$=Re){Ge(Me,y,k,!0);continue}let Ye;if(Me.key!=null)Ye=pe.get(Me.key);else for(fe=te;fe<=R;fe++)if(Qt[fe-te]===0&&Pt(Me,u[fe])){Ye=fe;break}Ye===void 0?Ge(Me,y,k,!0):(Qt[Ye-te]=$+1,Ye>=ao?ao=Ye:Lt=!0,F(Me,u[Ye],p,null,y,k,L,P,S),ye++)}const uo=Lt?nc(Qt):It;for(fe=uo.length-1,$=Re-1;$>=0;$--){const Me=te+$,Ye=u[Me],fo=Me+1{const{el:k,type:L,transition:P,children:S,shapeFlag:$}=a;if($&6){gt(a.component.subTree,u,p,w);return}if($&128){a.suspense.move(u,p,w);return}if($&64){L.move(a,u,p,Et);return}if(L===q){s(k,u,p);for(let N=0;NP.enter(k),y);else{const{leave:N,delayLeave:R,afterLeave:W}=P,te=()=>s(k,u,p),pe=()=>{N(k,()=>{te(),W&&W()})};R?R(k,te,pe):pe()}else s(k,u,p)},Ge=(a,u,p,w=!1,y=!1)=>{const{type:k,props:L,ref:P,children:S,dynamicChildren:$,shapeFlag:D,patchFlag:N,dirs:R}=a;if(P!=null&&In(P,null,p,a,!0),D&256){u.ctx.deactivate(a);return}const W=D&1&&R,te=!Bt(a);let pe;if(te&&(pe=L&&L.onVnodeBeforeUnmount)&&Fe(pe,u,a),D&6)$i(a.component,p,w);else{if(D&128){a.suspense.unmount(p,w);return}W&&Qe(a,null,u,"beforeUnmount"),D&64?a.type.remove(a,u,p,y,Et,w):$&&(k!==q||N>0&&N&64)?tt($,u,p,!1,!0):(k===q&&N&384||!y&&D&16)&&tt(S,u,p),w&&lo(a)}(te&&(pe=L&&L.onVnodeUnmounted)||W)&&Te(()=>{pe&&Fe(pe,u,a),W&&Qe(a,null,u,"unmounted")},p)},lo=a=>{const{type:u,el:p,anchor:w,transition:y}=a;if(u===q){xi(p,w);return}if(u===Ft){G(a);return}const k=()=>{o(p),y&&!y.persisted&&y.afterLeave&&y.afterLeave()};if(a.shapeFlag&1&&y&&!y.persisted){const{leave:L,delayLeave:P}=y,S=()=>L(p,k);P?P(a.el,k,S):S()}else k()},xi=(a,u)=>{let p;for(;a!==u;)p=x(a),o(a),a=p;o(u)},$i=(a,u,p)=>{const{bum:w,scope:y,update:k,subTree:L,um:P}=a;w&&cs(w),y.stop(),k&&(k.active=!1,Ge(L,a,u,p)),P&&Te(P,u),Te(()=>{a.isUnmounted=!0},u),u&&u.pendingBranch&&!u.isUnmounted&&a.asyncDep&&!a.asyncResolved&&a.suspenseId===u.pendingId&&(u.deps--,u.deps===0&&u.resolve())},tt=(a,u,p,w=!1,y=!1,k=0)=>{for(let L=k;La.shapeFlag&6?vn(a.component.subTree):a.shapeFlag&128?a.suspense.next():x(a.anchor||a.el),co=(a,u,p)=>{a==null?u._vnode&&Ge(u._vnode,null,null,!0):F(u._vnode||null,a,u,null,null,null,p),wo(),Tn(),u._vnode=a},Et={p:F,um:Ge,m:gt,r:lo,mt:H,mc:M,pc:_e,pbc:Y,n:vn,o:e};let rs,is;return t&&([rs,is]=t(Et)),{render:co,hydrate:rs,createApp:Xl(co,rs)}}function bt({effect:e,update:t},n){e.allowRecurse=t.allowRecurse=n}function Zr(e,t,n=!1){const s=e.children,o=t.children;if(K(s)&&K(o))for(let r=0;r>1,e[n[l]]0&&(t[s]=n[r-1]),n[r]=s)}}for(r=n.length,i=n[r-1];r-- >0;)n[r]=i,i=t[i];return n}const sc=e=>e.__isTeleport,q=Symbol(void 0),an=Symbol(void 0),Ae=Symbol(void 0),Ft=Symbol(void 0),tn=[];let ze=null;function d(e=!1){tn.push(ze=e?null:[])}function oc(){tn.pop(),ze=tn[tn.length-1]||null}let un=1;function Mo(e){un+=e}function ei(e){return e.dynamicChildren=un>0?ze||It:null,oc(),un>0&&ze&&ze.push(e),e}function v(e,t,n,s,o,r){return ei(b(e,t,n,s,o,r,!0))}function Q(e,t,n,s,o){return ei(V(e,t,n,s,o,!0))}function An(e){return e?e.__v_isVNode===!0:!1}function Pt(e,t){return e.type===t.type&&e.key===t.key}const es="__vInternal",ti=({key:e})=>e!=null?e:null,kn=({ref:e,ref_key:t,ref_for:n})=>e!=null?we(e)||ke(e)||X(e)?{i:Ve,r:e,k:t,f:!!n}:e:null;function b(e,t=null,n=null,s=0,o=null,r=e===q?0:1,i=!1,l=!1){const c={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&ti(t),ref:t&&kn(t),scopeId:Yn,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetAnchor:null,staticCount:0,shapeFlag:r,patchFlag:s,dynamicProps:o,dynamicChildren:null,appContext:null};return l?(Xs(c,n),r&128&&e.normalize(c)):n&&(c.shapeFlag|=we(n)?8:16),un>0&&!i&&ze&&(c.patchFlag>0||r&6)&&c.patchFlag!==32&&ze.push(c),c}const V=rc;function rc(e,t=null,n=null,s=0,o=null,r=!1){if((!e||e===jr)&&(e=Ae),An(e)){const l=_t(e,t,!0);return n&&Xs(l,n),un>0&&!r&&ze&&(l.shapeFlag&6?ze[ze.indexOf(e)]=l:ze.push(l)),l.patchFlag|=-2,l}if(vc(e)&&(e=e.__vccOpts),t){t=ic(t);let{class:l,style:c}=t;l&&!we(l)&&(t.class=he(l)),ge(c)&&(kr(c)&&!K(c)&&(c=$e({},c)),t.style=Dn(c))}const i=we(e)?1:Sl(e)?128:sc(e)?64:ge(e)?4:X(e)?2:0;return b(e,t,n,s,o,i,r,!0)}function ic(e){return e?kr(e)||es in e?$e({},e):e:null}function _t(e,t,n=!1){const{props:s,ref:o,patchFlag:r,children:i}=e,l=t?Cn(s||{},t):s;return{__v_isVNode:!0,__v_skip:!0,type:e.type,props:l,key:l&&ti(l),ref:t&&t.ref?n&&o?K(o)?o.concat(kn(t)):[o,kn(t)]:kn(t):o,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:i,target:e.target,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==q?r===-1?16:r|16:r,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:e.transition,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&_t(e.ssContent),ssFallback:e.ssFallback&&_t(e.ssFallback),el:e.el,anchor:e.anchor}}function Oe(e=" ",t=0){return V(an,null,e,t)}function lc(e,t){const n=V(Ft,null,e);return n.staticCount=t,n}function U(e="",t=!1){return t?(d(),Q(Ae,null,e)):V(Ae,null,e)}function Ue(e){return e==null||typeof e=="boolean"?V(Ae):K(e)?V(q,null,e.slice()):typeof e=="object"?ut(e):V(an,null,String(e))}function ut(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:_t(e)}function Xs(e,t){let n=0;const{shapeFlag:s}=e;if(t==null)t=null;else if(K(t))n=16;else if(typeof t=="object")if(s&65){const o=t.default;o&&(o._c&&(o._d=!1),Xs(e,o()),o._c&&(o._d=!0));return}else{n=32;const o=t._;!o&&!(es in t)?t._ctx=Ve:o===3&&Ve&&(Ve.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else X(t)?(t={default:t,_ctx:Ve},n=32):(t=String(t),s&64?(n=16,t=[Oe(t)]):n=8);e.children=t,e.shapeFlag|=n}function Cn(...e){const t={};for(let n=0;nxe||Ve,jt=e=>{xe=e,e.scope.on()},Vt=()=>{xe&&xe.scope.off(),xe=null};function ni(e){return e.vnode.shapeFlag&4}let fn=!1;function fc(e,t=!1){fn=t;const{props:n,children:s}=e.vnode,o=ni(e);Wl(e,n,o,t),Yl(e,s);const r=o?dc(e,t):void 0;return fn=!1,r}function dc(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=en(new Proxy(e.ctx,Dl));const{setup:s}=n;if(s){const o=e.setupContext=s.length>1?_c(e):null;jt(e),Wt();const r=dt(s,e,0,[e.props,o]);if(qt(),Vt(),fr(r)){if(r.then(Vt,Vt),t)return r.then(i=>{Io(e,i,t)}).catch(i=>{Wn(i,e,0)});e.asyncDep=r}else Io(e,r,t)}else si(e,t)}function Io(e,t,n){X(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:ge(t)&&(e.setupState=Tr(t)),si(e,n)}let Ao;function si(e,t,n){const s=e.type;if(!e.render){if(!t&&Ao&&!s.render){const o=s.template||Qs(e).template;if(o){const{isCustomElement:r,compilerOptions:i}=e.appContext.config,{delimiters:l,compilerOptions:c}=s,f=$e($e({isCustomElement:r,delimiters:l},i),c);s.render=Ao(o,f)}}e.render=s.render||Ke}jt(e),Wt(),Rl(e),qt(),Vt()}function hc(e){return new Proxy(e.attrs,{get(t,n){return Ne(e,"get","$attrs"),t[n]}})}function _c(e){const t=s=>{e.exposed=s||{}};let n;return{get attrs(){return n||(n=hc(e))},slots:e.slots,emit:e.emit,expose:t}}function eo(e){if(e.exposed)return e.exposeProxy||(e.exposeProxy=new Proxy(Tr(en(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in Ln)return Ln[n](e)}}))}function pc(e,t=!0){return X(e)?e.displayName||e.name:e.name||t&&e.__name}function vc(e){return X(e)&&"__vccOpts"in e}const re=(e,t)=>vl(e,t,fn);function Nn(e,t,n){const s=arguments.length;return s===2?ge(t)&&!K(t)?An(t)?V(e,null,[t]):V(e,t):V(e,null,t):(s>3?n=Array.prototype.slice.call(arguments,2):s===3&&An(n)&&(n=[n]),V(e,t,n))}const mc="3.2.40",gc="http://www.w3.org/2000/svg",kt=typeof document<"u"?document:null,No=kt&&kt.createElement("template"),bc={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,s)=>{const o=t?kt.createElementNS(gc,e):kt.createElement(e,n?{is:n}:void 0);return e==="select"&&s&&s.multiple!=null&&o.setAttribute("multiple",s.multiple),o},createText:e=>kt.createTextNode(e),createComment:e=>kt.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>kt.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,s,o,r){const i=n?n.previousSibling:t.lastChild;if(o&&(o===r||o.nextSibling))for(;t.insertBefore(o.cloneNode(!0),n),!(o===r||!(o=o.nextSibling)););else{No.innerHTML=s?`${e}`:e;const l=No.content;if(s){const c=l.firstChild;for(;c.firstChild;)l.appendChild(c.firstChild);l.removeChild(c)}t.insertBefore(l,n)}return[i?i.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}};function yc(e,t,n){const s=e._vtc;s&&(t=(t?[t,...s]:[...s]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}function wc(e,t,n){const s=e.style,o=we(n);if(n&&!o){for(const r in n)Ss(s,r,n[r]);if(t&&!we(t))for(const r in t)n[r]==null&&Ss(s,r,"")}else{const r=s.display;o?t!==n&&(s.cssText=n):t&&e.removeAttribute("style"),"_vod"in e&&(s.display=r)}}const Oo=/\s*!important$/;function Ss(e,t,n){if(K(n))n.forEach(s=>Ss(e,t,s));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const s=xc(e,t);Oo.test(n)?e.setProperty(Kt(s),n.replace(Oo,""),"important"):e[s]=n}}const Bo=["Webkit","Moz","ms"],fs={};function xc(e,t){const n=fs[t];if(n)return n;let s=Ze(t);if(s!=="filter"&&s in e)return fs[t]=s;s=jn(s);for(let o=0;o{let e=Date.now,t=!1;if(typeof window<"u"){Date.now()>document.createEvent("Event").timeStamp&&(e=performance.now.bind(performance));const n=navigator.userAgent.match(/firefox\/(\d+)/i);t=!!(n&&Number(n[1])<=53)}return[e,t]})();let Vs=0;const Cc=Promise.resolve(),Sc=()=>{Vs=0},Vc=()=>Vs||(Cc.then(Sc),Vs=oi());function Tc(e,t,n,s){e.addEventListener(t,n,s)}function Ec(e,t,n,s){e.removeEventListener(t,n,s)}function Lc(e,t,n,s,o=null){const r=e._vei||(e._vei={}),i=r[t];if(s&&i)i.value=s;else{const[l,c]=Mc(t);if(s){const f=r[t]=Ic(s,o);Tc(e,l,f,c)}else i&&(Ec(e,l,i,c),r[t]=void 0)}}const Ho=/(?:Once|Passive|Capture)$/;function Mc(e){let t;if(Ho.test(e)){t={};let s;for(;s=e.match(Ho);)e=e.slice(0,e.length-s[0].length),t[s[0].toLowerCase()]=!0}return[e[2]===":"?e.slice(3):Kt(e.slice(2)),t]}function Ic(e,t){const n=s=>{const o=s.timeStamp||oi();(kc||o>=n.attached-1)&&He(Ac(s,n.value),t,5,[s])};return n.value=e,n.attached=Vc(),n}function Ac(e,t){if(K(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(s=>o=>!o._stopped&&s&&s(o))}else return t}const Do=/^on[a-z]/,Nc=(e,t,n,s,o=!1,r,i,l,c)=>{t==="class"?yc(e,s,o):t==="style"?wc(e,n,s):hn(t)?Is(t)||Lc(e,t,n,s,i):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):Oc(e,t,s,o))?Pc(e,t,s,r,i,l,c):(t==="true-value"?e._trueValue=s:t==="false-value"&&(e._falseValue=s),$c(e,t,s,o))};function Oc(e,t,n,s){return s?!!(t==="innerHTML"||t==="textContent"||t in e&&Do.test(t)&&X(n)):t==="spellcheck"||t==="draggable"||t==="translate"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA"||Do.test(t)&&we(n)?!1:t in e}function Bc(e){const t=Zs();if(!t)return;const n=()=>Ts(t.subTree,e(t.proxy));Or(n),De(()=>{const s=new MutationObserver(n);s.observe(t.subTree.el.parentNode,{childList:!0}),pt(()=>s.disconnect())})}function Ts(e,t){if(e.shapeFlag&128){const n=e.suspense;e=n.activeBranch,n.pendingBranch&&!n.isHydrating&&n.effects.push(()=>{Ts(n.activeBranch,t)})}for(;e.component;)e=e.component.subTree;if(e.shapeFlag&1&&e.el)Ro(e.el,t);else if(e.type===q)e.children.forEach(n=>Ts(n,t));else if(e.type===Ft){let{el:n,anchor:s}=e;for(;n&&(Ro(n,t),n!==s);)n=n.nextSibling}}function Ro(e,t){if(e.nodeType===1){const n=e.style;for(const s in t)n.setProperty(`--${s}`,t[s])}}const ct="transition",Jt="animation",ts=(e,{slots:t})=>Nn(Fr,Fc(e),t);ts.displayName="Transition";const ri={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String};ts.props=$e({},Fr.props,ri);const yt=(e,t=[])=>{K(e)?e.forEach(n=>n(...t)):e&&e(...t)},Uo=e=>e?K(e)?e.some(t=>t.length>1):e.length>1:!1;function Fc(e){const t={};for(const A in e)A in ri||(t[A]=e[A]);if(e.css===!1)return t;const{name:n="v",type:s,duration:o,enterFromClass:r=`${n}-enter-from`,enterActiveClass:i=`${n}-enter-active`,enterToClass:l=`${n}-enter-to`,appearFromClass:c=r,appearActiveClass:f=i,appearToClass:h=l,leaveFromClass:m=`${n}-leave-from`,leaveActiveClass:x=`${n}-leave-active`,leaveToClass:C=`${n}-leave-to`}=e,j=Hc(o),F=j&&j[0],J=j&&j[1],{onBeforeEnter:g,onEnter:T,onEnterCancelled:z,onLeave:G,onLeaveCancelled:ne,onBeforeAppear:de=g,onAppear:oe=T,onAppearCancelled:M=z}=t,Z=(A,ee,H)=>{wt(A,ee?h:l),wt(A,ee?f:i),H&&H()},Y=(A,ee)=>{A._isLeaving=!1,wt(A,m),wt(A,C),wt(A,x),ee&&ee()},le=A=>(ee,H)=>{const Le=A?oe:T,ue=()=>Z(ee,A,H);yt(Le,[ee,ue]),jo(()=>{wt(ee,A?c:r),at(ee,A?h:l),Uo(Le)||zo(ee,s,F,ue)})};return $e(t,{onBeforeEnter(A){yt(g,[A]),at(A,r),at(A,i)},onBeforeAppear(A){yt(de,[A]),at(A,c),at(A,f)},onEnter:le(!1),onAppear:le(!0),onLeave(A,ee){A._isLeaving=!0;const H=()=>Y(A,ee);at(A,m),Uc(),at(A,x),jo(()=>{!A._isLeaving||(wt(A,m),at(A,C),Uo(G)||zo(A,s,J,H))}),yt(G,[A,H])},onEnterCancelled(A){Z(A,!1),yt(z,[A])},onAppearCancelled(A){Z(A,!0),yt(M,[A])},onLeaveCancelled(A){Y(A),yt(ne,[A])}})}function Hc(e){if(e==null)return null;if(ge(e))return[ds(e.enter),ds(e.leave)];{const t=ds(e);return[t,t]}}function ds(e){return _r(e)}function at(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.add(n)),(e._vtc||(e._vtc=new Set)).add(t)}function wt(e,t){t.split(/\s+/).forEach(s=>s&&e.classList.remove(s));const{_vtc:n}=e;n&&(n.delete(t),n.size||(e._vtc=void 0))}function jo(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let Dc=0;function zo(e,t,n,s){const o=e._endId=++Dc,r=()=>{o===e._endId&&s()};if(n)return setTimeout(r,n);const{type:i,timeout:l,propCount:c}=Rc(e,t);if(!i)return s();const f=i+"end";let h=0;const m=()=>{e.removeEventListener(f,x),r()},x=C=>{C.target===e&&++h>=c&&m()};setTimeout(()=>{h(n[j]||"").split(", "),o=s(ct+"Delay"),r=s(ct+"Duration"),i=Ko(o,r),l=s(Jt+"Delay"),c=s(Jt+"Duration"),f=Ko(l,c);let h=null,m=0,x=0;t===ct?i>0&&(h=ct,m=i,x=r.length):t===Jt?f>0&&(h=Jt,m=f,x=c.length):(m=Math.max(i,f),h=m>0?i>f?ct:Jt:null,x=h?h===ct?r.length:c.length:0);const C=h===ct&&/\b(transform|all)(,|$)/.test(n[ct+"Property"]);return{type:h,timeout:m,propCount:x,hasTransform:C}}function Ko(e,t){for(;e.lengthWo(n)+Wo(e[s])))}function Wo(e){return Number(e.slice(0,-1).replace(",","."))*1e3}function Uc(){return document.body.offsetHeight}const jc=["ctrl","shift","alt","meta"],zc={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>jc.some(n=>e[`${n}Key`]&&!t.includes(n))},Kc=(e,t)=>(n,...s)=>{for(let o=0;o{const t=qc().createApp(...e),{mount:n}=t;return t.mount=s=>{const o=Yc(s);if(o)return n(o,!0,o instanceof SVGElement)},t};function Yc(e){return we(e)?document.querySelector(e):e}const O=(e,t)=>{const n=e.__vccOpts||e;for(const[s,o]of t)n[s]=o;return n},Qc="modulepreload",Jc=function(e){return"/"+e},Go={},Xc=function(t,n,s){return!n||n.length===0?t():Promise.all(n.map(o=>{if(o=Jc(o),o in Go)return;Go[o]=!0;const r=o.endsWith(".css"),i=r?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${o}"]${i}`))return;const l=document.createElement("link");if(l.rel=r?"stylesheet":Qc,r||(l.as="script",l.crossOrigin=""),l.href=o,document.head.appendChild(l),r)return new Promise((c,f)=>{l.addEventListener("load",c),l.addEventListener("error",()=>f(new Error(`Unable to preload CSS for ${o}`)))})})).then(()=>t())};const Zc=JSON.parse('{"lang":"en-US","title":"The Paper Pilot","description":"The Paper Pilot portfolio site","base":"/","head":[],"appearance":true,"themeConfig":{"outline":"deep","nav":[{"text":"Guide to Incrementals","link":"/guide-to-incrementals/","activeMatch":"^/guide-to-incrementals"},{"text":"Projects","link":"/projects/","activeMatch":"^/projects"},{"text":"Profectus","link":"https://moddingtree.com"}],"socialLinks":[{"icon":"github","link":"https://github.com/thepaperpilot"},{"icon":"linkedin","link":"https://www.linkedin.com/pub/anthony-lawn/a9/a98/2"},{"icon":"discord","link":"https://discord.gg/F3xveHV"}],"sidebar":{"guide-to-incrementals":[{"text":"Ludology","collapsible":true,"items":[{"text":"Defining the Genre","link":"/guide-to-incrementals/ludology/definition"},{"text":"Appeal to Players","link":"/guide-to-incrementals/ludology/appeal-games"},{"text":"Appeal to Developers","link":"/guide-to-incrementals/ludology/appeal-developers"},{"text":"What is Content?","link":"/guide-to-incrementals/ludology/content"}]}],"projects":[{"text":"Play Now","items":[{"text":"Kronos","link":"/kronos/"},{"text":"Game Dev Tree","link":"/gamedevtree/"},{"text":"Lit","link":"/lit/"},{"text":"The Ascension Tree","link":"/the_ascension_tree/"},{"text":"Dream Hero","link":"/dream/"},{"text":"My Itch Page","link":"https://thepaperpilot.itch.io/"}]},{"text":"Downloads","items":[{"text":"Dice Armor","link":"/projects/dice/"},{"text":"Capture the Citadel","link":"/projects/citadel/"}]},{"text":"Non-Games","items":[{"text":"V-ecs","link":"/projects/vecs/"},{"text":"OptiSpeech","link":"/projects/optispeech/"},{"text":"Babble Buds","link":"/projects/babble/"}]}]}},"locales":{},"langs":{},"scrollOffset":90,"cleanUrls":"with-subfolders"}'),ns=/^[a-z]+:/i,Yo="vitepress-theme-appearance",Ee=typeof window<"u",ii={relativePath:"",title:"404",description:"Not Found",headers:[],frontmatter:{sidebar:!1,layout:"page"},lastUpdated:0};function ea(e,t){t.sort((n,s)=>{const o=s.split("/").length-n.split("/").length;return o!==0?o:s.length-n.length});for(const n of t)if(e.startsWith(n))return n}function Qo(e,t){const n=ea(t,Object.keys(e));return n?e[n]:void 0}function ta(e){const{locales:t}=e.themeConfig||{},n=e.locales;return t&&n?Object.keys(t).reduce((s,o)=>(s[o]={label:t[o].label,lang:n[o].lang},s),{}):{}}function na(e,t){t=oa(e,t);const n=Qo(e.locales||{},t),s=Qo(e.themeConfig.locales||{},t);return Object.assign({},e,n,{themeConfig:Object.assign({},e.themeConfig,s,{locales:{}}),lang:(n||e).lang,locales:{},langs:ta(e)})}function li(e,t){var r;const n=t.title||e.title,s=(r=t.titleTemplate)!=null?r:e.titleTemplate;if(typeof s=="string"&&s.includes(":title"))return s.replace(/:title/g,n);const o=sa(e.title,s);return`${n}${o}`}function sa(e,t){return t===!1?"":t===!0||t===void 0?` | ${e}`:e===t?"":` | ${t}`}function oa(e,t){if(!Ee)return t;const n=e.base,s=n.endsWith("/")?n.slice(0,-1):n;return t.slice(s.length)}function ra(e,t){const[n,s]=t;if(n!=="meta")return!1;const o=Object.entries(s)[0];return o==null?!1:e.some(([r,i])=>r===n&&i[o[0]]===o[1])}function ia(e,t){return[...e.filter(n=>!ra(t,n)),...t]}function la(e,t){return`${e}${t}`.replace(/\/+/g,"/")}function dn(e){return ns.test(e)?e:la(zt.value.base,e)}function ci(e){let t=e.replace(/\.html$/,"");if(t=decodeURIComponent(t),t.endsWith("/")&&(t+="index"),Ee){const n="/";t=(t.slice(n.length).replace(/\//g,"_")||"index")+".md";const s=__VP_HASH_MAP__[t.toLowerCase()];t=`${n}assets/${t}.${s}.js`}else t=`./${t.slice(1).replace(/\//g,"_")}.md.js`;return t}const ai=Symbol(),zt=dl(Zc);function ca(e){const t=re(()=>na(zt.value,e.path));return{site:t,theme:re(()=>t.value.themeConfig),page:re(()=>e.data),frontmatter:re(()=>e.data.frontmatter),lang:re(()=>t.value.lang),localePath:re(()=>{const{langs:n,lang:s}=t.value,o=Object.keys(n).find(r=>n[r].lang===s);return dn(o||"/")}),title:re(()=>li(t.value,e.data)),description:re(()=>e.data.description||t.value.description)}}function ae(){const e=Xe(ai);if(!e)throw new Error("vitepress data not properly injected in app");return e}const ui=Symbol(),Jo="http://a.com",aa=()=>({path:"/",component:null,data:ii});function ua(e,t){const n=Kn(aa()),s={route:n,go:o};async function o(l=Ee?location.href:"/"){var f,h;await((f=s.onBeforeRouteChange)==null?void 0:f.call(s,l));const c=new URL(l,Jo);zt.value.cleanUrls==="disabled"&&!c.pathname.endsWith("/")&&!c.pathname.endsWith(".html")&&(c.pathname+=".html",l=c.pathname+c.search+c.hash),Ee&&(history.replaceState({scrollPosition:window.scrollY},document.title),history.pushState(null,"",l)),await i(l),await((h=s.onAfterRouteChanged)==null?void 0:h.call(s,l))}let r=null;async function i(l,c=0,f=!1){const h=new URL(l,Jo),m=r=h.pathname;try{let x=await e(m);if(r===m){r=null;const{default:C,__pageData:j}=x;if(!C)throw new Error(`Invalid route component: ${C}`);n.path=Ee?m:dn(m),n.component=en(C),n.data=en(j),Ee&&qn(()=>{if(h.hash&&!c){let F=null;try{F=document.querySelector(decodeURIComponent(h.hash))}catch(J){console.warn(J)}if(F){Xo(F,h.hash);return}}window.scrollTo(0,c)})}}catch(x){if(!/fetch/.test(x.message)&&!/^\/404(\.html|\/)?$/.test(l)&&console.error(x),!f)try{const C=await fetch(zt.value.base+"hashmap.json");window.__VP_HASH_MAP__=await C.json(),await i(l,c,!0);return}catch{}r===m&&(r=null,n.path=Ee?m:dn(m),n.component=t?en(t):null,n.data=ii)}}return Ee&&(window.addEventListener("click",l=>{if(l.target.closest("button"))return;const f=l.target.closest("a");if(f&&!f.closest(".vp-raw")){const{href:h,origin:m,pathname:x,hash:C,search:j,target:F}=f,J=window.location,g=x.match(/\.\w+$/);!l.ctrlKey&&!l.shiftKey&&!l.altKey&&!l.metaKey&&F!=="_blank"&&m===J.origin&&!(g&&g[0]!==".html")&&(l.preventDefault(),x===J.pathname&&j===J.search?C&&C!==J.hash&&(history.pushState(null,"",C),window.dispatchEvent(new Event("hashchange")),Xo(f,C,f.classList.contains("header-anchor"))):o(h))}},{capture:!0}),window.addEventListener("popstate",l=>{i(location.href,l.state&&l.state.scrollPosition||0)}),window.addEventListener("hashchange",l=>{l.preventDefault()})),s}function fa(){const e=Xe(ui);if(!e)throw new Error("useRouter() is called without provider.");return e}function vt(){return fa().route}function Xo(e,t,n=!1){let s=null;try{s=e.classList.contains("header-anchor")?e:document.querySelector(decodeURIComponent(t))}catch(o){console.warn(o)}if(s){let o=zt.value.scrollOffset;typeof o=="string"&&(o=document.querySelector(o).getBoundingClientRect().bottom+24);const r=parseInt(window.getComputedStyle(s).paddingTop,10),i=window.scrollY+s.getBoundingClientRect().top-o+r;!n||Math.abs(i-window.scrollY)>window.innerHeight?window.scrollTo(0,i):window.scrollTo({left:0,top:i,behavior:"smooth"})}}const da=B({name:"VitePressContent",props:{onContentUpdated:Function},setup(e){const t=vt();return qs(()=>{var n;(n=e.onContentUpdated)==null||n.call(e)}),()=>Nn("div",{style:{position:"relative"}},[t.component?Nn(t.component):null])}}),fi=/#.*$/,ha=/(index)?\.(md|html)$/,_a=typeof window<"u",pa=me(_a?location.hash:"");function va(e){return ns.test(e)}function ma(e,t){let n,s=!1;return()=>{n&&clearTimeout(n),s?n=setTimeout(e,t):(e(),s=!0,setTimeout(()=>{s=!1},t))}}function Gt(e,t,n=!1){if(t===void 0)return!1;if(e=er(`/${e}`),n)return new RegExp(t).test(e);if(er(t)!==e)return!1;const s=t.match(fi);return s?pa.value===s[0]:!0}function Zo(e){return/^\//.test(e)?e:`/${e}`}function er(e){return decodeURI(e).replace(fi,"").replace(ha,"")}function On(e){if(va(e))return e;const{site:t}=ae(),{pathname:n,search:s,hash:o}=new URL(e,"http://example.com"),r=n.endsWith("/")||n.endsWith(".html")?e:`${n.replace(/(\.md)?$/,t.value.cleanUrls==="disabled"?".html":"")}${s}${o}`;return dn(r)}function di(e,t){if(Array.isArray(e))return e;t=Zo(t);for(const n in e)if(t.startsWith(Zo(n)))return e[n];return[]}function ga(e){const t=[];function n(s){for(const o of s)o.link&&t.push({...o,link:o.link}),"items"in o&&n(o.items)}for(const s of e)n(s.items);return t}function et(){const e=vt(),{theme:t,frontmatter:n}=ae(),s=me(!1),o=re(()=>{const h=t.value.sidebar,m=e.data.relativePath;return h?di(h,m):[]}),r=re(()=>n.value.sidebar!==!1&&o.value.length>0&&n.value.layout!=="home"),i=re(()=>n.value.layout!=="home"&&n.value.aside!==!1);function l(){s.value=!0}function c(){s.value=!1}function f(){s.value?c():l()}return{isOpen:s,sidebar:o,hasSidebar:r,hasAside:i,open:l,close:c,toggle:f}}function ba(e,t){let n;Ut(()=>{n=e.value?document.activeElement:void 0}),De(()=>{window.addEventListener("keyup",s)}),pt(()=>{window.removeEventListener("keyup",s)});function s(o){o.key==="Escape"&&e.value&&(t(),n==null||n.focus())}}const ya=B({__name:"VPSkipLink",setup(e){const t=vt(),n=me();st(()=>t.path,()=>n.value.focus());function s({target:o}){const r=document.querySelector(o.hash);if(r){const i=()=>{r.removeAttribute("tabindex"),r.removeEventListener("blur",i)};r.setAttribute("tabindex","-1"),r.addEventListener("blur",i),r.focus(),window.scrollTo(0,0)}}return(o,r)=>(d(),v(q,null,[b("span",{ref_key:"backToTop",ref:n,tabindex:"-1"},null,512),b("a",{href:"#VPContent",class:"VPSkipLink visually-hidden",onClick:s}," Skip to content ")],64))}});const wa=O(ya,[["__scopeId","data-v-151f2593"]]),xa={key:0,class:"VPBackdrop"},$a=B({__name:"VPBackdrop",props:{show:{type:Boolean}},setup(e){return(t,n)=>(d(),Q(ts,{name:"fade"},{default:I(()=>[e.show?(d(),v("div",xa)):U("",!0)]),_:1}))}});const Pa=O($a,[["__scopeId","data-v-0164f098"]]);function ka(){const e=me(!1);function t(){e.value=!0,window.addEventListener("resize",o)}function n(){e.value=!1,window.removeEventListener("resize",o)}function s(){e.value?n():t()}function o(){window.outerWidth>=768&&n()}const r=vt();return st(()=>r.path,n),{isScreenOpen:e,openScreen:t,closeScreen:n,toggleScreen:s}}const Ca=["src","alt"],Sa={inheritAttrs:!1},Va=B({...Sa,__name:"VPImage",props:{image:null},setup(e){return(t,n)=>{const s=Tt("VPImage",!0);return e.image?(d(),v(q,{key:0},[typeof e.image=="string"||"src"in e.image?(d(),v("img",Cn({key:0,class:"VPImage"},typeof e.image=="string"?t.$attrs:{...e.image,...t.$attrs},{src:_(dn)(typeof e.image=="string"?e.image:e.image.src),alt:typeof e.image=="string"?"":e.image.alt||""}),null,16,Ca)):(d(),v(q,{key:1},[V(s,Cn({class:"dark",image:e.image.dark},t.$attrs),null,16,["image"]),V(s,Cn({class:"light",image:e.image.light},t.$attrs),null,16,["image"])],64))],64)):U("",!0)}}});const hi=O(Va,[["__scopeId","data-v-8e4dd84f"]]),Ta=["href"],Ea=B({__name:"VPNavBarTitle",setup(e){const{site:t,theme:n}=ae(),{hasSidebar:s}=et();return(o,r)=>(d(),v("div",{class:he(["VPNavBarTitle",{"has-sidebar":_(s)}])},[b("a",{class:"title",href:_(t).base},[E(o.$slots,"nav-bar-title-before",{},void 0,!0),V(hi,{class:"logo",image:_(n).logo},null,8,["image"]),_(n).siteTitle?(d(),v(q,{key:0},[Oe(ie(_(n).siteTitle),1)],64)):_(n).siteTitle===void 0?(d(),v(q,{key:1},[Oe(ie(_(t).title),1)],64)):U("",!0),E(o.$slots,"nav-bar-title-after",{},void 0,!0)],8,Ta)],2))}});const La=O(Ea,[["__scopeId","data-v-d5925166"]]);const Ma={key:0,class:"VPNavBarSearch"},Ia={type:"button",class:"DocSearch DocSearch-Button","aria-label":"Search"},Aa={class:"DocSearch-Button-Container"},Na=b("svg",{class:"DocSearch-Search-Icon",width:"20",height:"20",viewBox:"0 0 20 20"},[b("path",{d:"M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z",stroke:"currentColor",fill:"none","fill-rule":"evenodd","stroke-linecap":"round","stroke-linejoin":"round"})],-1),Oa={class:"DocSearch-Button-Placeholder"},Ba=b("span",{class:"DocSearch-Button-Keys"},[b("kbd",{class:"DocSearch-Button-Key"}),b("kbd",{class:"DocSearch-Button-Key"},"K")],-1),Fa=B({__name:"VPNavBarSearch",setup(e){Bc(i=>({"5943dbe8":o.value}));const t=()=>null,{theme:n}=ae(),s=me(!1),o=me("'Meta'");De(()=>{if(!n.value.algolia)return;o.value=/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)?"'\u2318'":"'Ctrl'";const i=c=>{c.key==="k"&&(c.ctrlKey||c.metaKey)&&(c.preventDefault(),r(),l())},l=()=>{window.removeEventListener("keydown",i)};window.addEventListener("keydown",i),pt(l)});function r(){s.value||(s.value=!0)}return(i,l)=>{var c;return _(n).algolia?(d(),v("div",Ma,[s.value?(d(),Q(_(t),{key:0})):(d(),v("div",{key:1,id:"docsearch",onClick:r},[b("button",Ia,[b("span",Aa,[Na,b("span",Oa,ie(((c=_(n).algolia)==null?void 0:c.buttonText)||"Search"),1)]),Ba])]))])):U("",!0)}}});const Ha={},Da={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",height:"24px",viewBox:"0 0 24 24",width:"24px"},Ra=b("path",{d:"M0 0h24v24H0V0z",fill:"none"},null,-1),Ua=b("path",{d:"M9 5v2h6.59L4 18.59 5.41 20 17 8.41V15h2V5H9z"},null,-1),ja=[Ra,Ua];function za(e,t){return d(),v("svg",Da,ja)}const Ka=O(Ha,[["render",za]]),Wa=B({__name:"VPLink",props:{href:null,noIcon:{type:Boolean}},setup(e){const t=e,n=re(()=>t.href&&ns.test(t.href));return(s,o)=>(d(),Q(Ys(e.href?"a":"span"),{class:he(["VPLink",{link:e.href}]),href:e.href?_(On)(e.href):void 0,target:_(n)?"_blank":void 0,rel:_(n)?"noreferrer":void 0},{default:I(()=>[E(s.$slots,"default",{},void 0,!0),_(n)&&!e.noIcon?(d(),Q(Ka,{key:0,class:"icon"})):U("",!0)]),_:3},8,["class","href","target","rel"]))}});const Yt=O(Wa,[["__scopeId","data-v-3c355974"]]),qa=B({__name:"VPNavBarMenuLink",props:{item:null},setup(e){const{page:t}=ae();return(n,s)=>(d(),Q(Yt,{class:he({VPNavBarMenuLink:!0,active:_(Gt)(_(t).relativePath,e.item.activeMatch||e.item.link,!!e.item.activeMatch)}),href:e.item.link,noIcon:!0},{default:I(()=>[Oe(ie(e.item.text),1)]),_:1},8,["class","href"]))}});const Ga=O(qa,[["__scopeId","data-v-47a2263e"]]),to=me();let _i=!1,_s=0;function Ya(e){const t=me(!1);if(typeof window<"u"){!_i&&Qa(),_s++;const n=st(to,s=>{var o,r,i;s===e.el.value||((o=e.el.value)==null?void 0:o.contains(s))?(t.value=!0,(r=e.onFocus)==null||r.call(e)):(t.value=!1,(i=e.onBlur)==null||i.call(e))});pt(()=>{n(),_s--,_s||Ja()})}return Us(t)}function Qa(){document.addEventListener("focusin",pi),_i=!0,to.value=document.activeElement}function Ja(){document.removeEventListener("focusin",pi)}function pi(){to.value=document.activeElement}const Xa={},Za={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},eu=b("path",{d:"M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"},null,-1),tu=[eu];function nu(e,t){return d(),v("svg",Za,tu)}const vi=O(Xa,[["render",nu]]),su={},ou={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},ru=b("circle",{cx:"12",cy:"12",r:"2"},null,-1),iu=b("circle",{cx:"19",cy:"12",r:"2"},null,-1),lu=b("circle",{cx:"5",cy:"12",r:"2"},null,-1),cu=[ru,iu,lu];function au(e,t){return d(),v("svg",ou,cu)}const uu=O(su,[["render",au]]),fu={class:"VPMenuLink"},du=B({__name:"VPMenuLink",props:{item:null},setup(e){const{page:t}=ae();return(n,s)=>(d(),v("div",fu,[V(Yt,{class:he({active:_(Gt)(_(t).relativePath,e.item.activeMatch||e.item.link)}),href:e.item.link},{default:I(()=>[Oe(ie(e.item.text),1)]),_:1},8,["class","href"])]))}});const ss=O(du,[["__scopeId","data-v-e8e0fb1d"]]),hu={class:"VPMenuGroup"},_u={key:0,class:"title"},pu=B({__name:"VPMenuGroup",props:{text:null,items:null},setup(e){return(t,n)=>(d(),v("div",hu,[e.text?(d(),v("p",_u,ie(e.text),1)):U("",!0),(d(!0),v(q,null,Ce(e.items,s=>(d(),v(q,null,["link"in s?(d(),Q(ss,{key:0,item:s},null,8,["item"])):U("",!0)],64))),256))]))}});const vu=O(pu,[["__scopeId","data-v-9ca52130"]]),mu={class:"VPMenu"},gu={key:0,class:"items"},bu=B({__name:"VPMenu",props:{items:null},setup(e){return(t,n)=>(d(),v("div",mu,[e.items?(d(),v("div",gu,[(d(!0),v(q,null,Ce(e.items,s=>(d(),v(q,{key:s.text},["link"in s?(d(),Q(ss,{key:0,item:s},null,8,["item"])):(d(),Q(vu,{key:1,text:s.text,items:s.items},null,8,["text","items"]))],64))),128))])):U("",!0),E(t.$slots,"default",{},void 0,!0)]))}});const yu=O(bu,[["__scopeId","data-v-1c5d0cfc"]]),wu=["aria-expanded","aria-label"],xu={key:0,class:"text"},$u={class:"menu"},Pu=B({__name:"VPFlyout",props:{icon:null,button:null,label:null,items:null},setup(e){const t=me(!1),n=me();Ya({el:n,onBlur:s});function s(){t.value=!1}return(o,r)=>(d(),v("div",{class:"VPFlyout",ref_key:"el",ref:n,onMouseenter:r[1]||(r[1]=i=>t.value=!0),onMouseleave:r[2]||(r[2]=i=>t.value=!1)},[b("button",{type:"button",class:"button","aria-haspopup":"true","aria-expanded":t.value,"aria-label":e.label,onClick:r[0]||(r[0]=i=>t.value=!t.value)},[e.button||e.icon?(d(),v("span",xu,[e.icon?(d(),Q(Ys(e.icon),{key:0,class:"option-icon"})):U("",!0),Oe(" "+ie(e.button)+" ",1),V(vi,{class:"text-icon"})])):(d(),Q(uu,{key:1,class:"icon"}))],8,wu),b("div",$u,[V(yu,{items:e.items},{default:I(()=>[E(o.$slots,"default",{},void 0,!0)]),_:3},8,["items"])])],544))}});const no=O(Pu,[["__scopeId","data-v-6ffb57d3"]]),ku=B({__name:"VPNavBarMenuGroup",props:{item:null},setup(e){const{page:t}=ae();return(n,s)=>(d(),Q(no,{class:he({VPNavBarMenuGroup:!0,active:_(Gt)(_(t).relativePath,e.item.activeMatch,!!e.item.activeMatch)}),button:e.item.text,items:e.item.items},null,8,["class","button","items"]))}}),Cu=e=>(We("data-v-f83db6ba"),e=e(),qe(),e),Su={key:0,"aria-labelledby":"main-nav-aria-label",class:"VPNavBarMenu"},Vu=Cu(()=>b("span",{id:"main-nav-aria-label",class:"visually-hidden"},"Main Navigation",-1)),Tu=B({__name:"VPNavBarMenu",setup(e){const{theme:t}=ae();return(n,s)=>_(t).nav?(d(),v("nav",Su,[Vu,(d(!0),v(q,null,Ce(_(t).nav,o=>(d(),v(q,{key:o.text},["link"in o?(d(),Q(Ga,{key:0,item:o},null,8,["item"])):(d(),Q(ku,{key:1,item:o},null,8,["item"]))],64))),128))])):U("",!0)}});const Eu=O(Tu,[["__scopeId","data-v-f83db6ba"]]),Lu={},Mu={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Iu=b("path",{d:"M0 0h24v24H0z",fill:"none"},null,-1),Au=b("path",{d:" M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z ",class:"css-c4d79v"},null,-1),Nu=[Iu,Au];function Ou(e,t){return d(),v("svg",Mu,Nu)}const mi=O(Lu,[["render",Ou]]),Bu={class:"items"},Fu={class:"title"},Hu=B({__name:"VPNavBarTranslations",setup(e){const{theme:t}=ae();return(n,s)=>_(t).localeLinks?(d(),Q(no,{key:0,class:"VPNavBarTranslations",icon:mi},{default:I(()=>[b("div",Bu,[b("p",Fu,ie(_(t).localeLinks.text),1),(d(!0),v(q,null,Ce(_(t).localeLinks.items,o=>(d(),Q(ss,{key:o.link,item:o},null,8,["item"]))),128))])]),_:1})):U("",!0)}});const Du=O(Hu,[["__scopeId","data-v-db824e91"]]);const Ru={},Uu={class:"VPSwitch",type:"button",role:"switch"},ju={class:"check"},zu={key:0,class:"icon"};function Ku(e,t){return d(),v("button",Uu,[b("span",ju,[e.$slots.default?(d(),v("span",zu,[E(e.$slots,"default",{},void 0,!0)])):U("",!0)])])}const Wu=O(Ru,[["render",Ku],["__scopeId","data-v-086e8519"]]),qu={},Gu={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Yu=lc('',9),Qu=[Yu];function Ju(e,t){return d(),v("svg",Gu,Qu)}const Xu=O(qu,[["render",Ju]]),Zu={},ef={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},tf=b("path",{d:"M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"},null,-1),nf=[tf];function sf(e,t){return d(),v("svg",ef,nf)}const of=O(Zu,[["render",sf]]),rf=B({__name:"VPSwitchAppearance",setup(e){const t=me(!1),n=typeof localStorage<"u"?s():()=>{};De(()=>{t.value=document.documentElement.classList.contains("dark")});function s(){const o=window.matchMedia("(prefers-color-scheme: dark)"),r=document.documentElement.classList;let i=localStorage.getItem(Yo)||"auto",l=i==="auto"?o.matches:i==="dark";o.onchange=h=>{i==="auto"&&f(l=h.matches)};function c(){f(l=!l),i=l?o.matches?"auto":"dark":o.matches?"light":"auto",localStorage.setItem(Yo,i)}function f(h){t.value=h,r[h?"add":"remove"]("dark")}return c}return(o,r)=>(d(),Q(Wu,{class:"VPSwitchAppearance","aria-label":"toggle dark mode","aria-checked":t.value,onClick:_(n)},{default:I(()=>[V(Xu,{class:"sun"}),V(of,{class:"moon"})]),_:1},8,["aria-checked","onClick"]))}});const so=O(rf,[["__scopeId","data-v-1899cd41"]]),lf={key:0,class:"VPNavBarAppearance"},cf=B({__name:"VPNavBarAppearance",setup(e){const{site:t}=ae();return(n,s)=>_(t).appearance?(d(),v("div",lf,[V(so)])):U("",!0)}});const af=O(cf,[["__scopeId","data-v-a3e7452b"]]),uf={discord:'Discord',facebook:'Facebook',github:'GitHub',instagram:'Instagram',linkedin:'LinkedIn',slack:'Slack',twitter:'Twitter',youtube:'YouTube'},ff=["href","innerHTML"],df=B({__name:"VPSocialLink",props:{icon:null,link:null},setup(e){const t=e,n=re(()=>typeof t.icon=="object"?t.icon.svg:uf[t.icon]);return(s,o)=>(d(),v("a",{class:"VPSocialLink",href:e.link,target:"_blank",rel:"noopener",innerHTML:_(n)},null,8,ff))}});const hf=O(df,[["__scopeId","data-v-e57698f6"]]),_f={class:"VPSocialLinks"},pf=B({__name:"VPSocialLinks",props:{links:null},setup(e){return(t,n)=>(d(),v("div",_f,[(d(!0),v(q,null,Ce(e.links,({link:s,icon:o})=>(d(),Q(hf,{key:s,icon:o,link:s},null,8,["icon","link"]))),128))]))}});const oo=O(pf,[["__scopeId","data-v-f6988cfb"]]),vf=B({__name:"VPNavBarSocialLinks",setup(e){const{theme:t}=ae();return(n,s)=>_(t).socialLinks?(d(),Q(oo,{key:0,class:"VPNavBarSocialLinks",links:_(t).socialLinks},null,8,["links"])):U("",!0)}});const mf=O(vf,[["__scopeId","data-v-738bef5a"]]),gf=e=>(We("data-v-e4361c82"),e=e(),qe(),e),bf={key:0,class:"group"},yf={class:"trans-title"},wf={key:1,class:"group"},xf={class:"item appearance"},$f=gf(()=>b("p",{class:"label"},"Appearance",-1)),Pf={class:"appearance-action"},kf={key:2,class:"group"},Cf={class:"item social-links"},Sf=B({__name:"VPNavBarExtra",setup(e){const{site:t,theme:n}=ae(),s=re(()=>n.value.localeLinks||t.value.appearance||n.value.socialLinks);return(o,r)=>_(s)?(d(),Q(no,{key:0,class:"VPNavBarExtra",label:"extra navigation"},{default:I(()=>[_(n).localeLinks?(d(),v("div",bf,[b("p",yf,ie(_(n).localeLinks.text),1),(d(!0),v(q,null,Ce(_(n).localeLinks.items,i=>(d(),Q(ss,{key:i.link,item:i},null,8,["item"]))),128))])):U("",!0),_(t).appearance?(d(),v("div",wf,[b("div",xf,[$f,b("div",Pf,[V(so)])])])):U("",!0),_(n).socialLinks?(d(),v("div",kf,[b("div",Cf,[V(oo,{class:"social-links-list",links:_(n).socialLinks},null,8,["links"])])])):U("",!0)]),_:1})):U("",!0)}});const Vf=O(Sf,[["__scopeId","data-v-e4361c82"]]),Tf=e=>(We("data-v-e5dd9c1c"),e=e(),qe(),e),Ef=["aria-expanded"],Lf=Tf(()=>b("span",{class:"container"},[b("span",{class:"top"}),b("span",{class:"middle"}),b("span",{class:"bottom"})],-1)),Mf=[Lf],If=B({__name:"VPNavBarHamburger",props:{active:{type:Boolean}},emits:["click"],setup(e){return(t,n)=>(d(),v("button",{type:"button",class:he(["VPNavBarHamburger",{active:e.active}]),"aria-label":"mobile navigation","aria-expanded":e.active,"aria-controls":"VPNavScreen",onClick:n[0]||(n[0]=s=>t.$emit("click"))},Mf,10,Ef))}});const Af=O(If,[["__scopeId","data-v-e5dd9c1c"]]),Nf={class:"container"},Of={class:"content"},Bf=B({__name:"VPNavBar",props:{isScreenOpen:{type:Boolean}},emits:["toggle-screen"],setup(e){const{hasSidebar:t}=et();return(n,s)=>(d(),v("div",{class:he(["VPNavBar",{"has-sidebar":_(t)}])},[b("div",Nf,[V(La,null,{"nav-bar-title-before":I(()=>[E(n.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":I(()=>[E(n.$slots,"nav-bar-title-after",{},void 0,!0)]),_:3}),b("div",Of,[E(n.$slots,"nav-bar-content-before",{},void 0,!0),V(Fa,{class:"search"}),V(Eu,{class:"menu"}),V(Du,{class:"translations"}),V(af,{class:"appearance"}),V(mf,{class:"social-links"}),V(Vf,{class:"extra"}),E(n.$slots,"nav-bar-content-after",{},void 0,!0),V(Af,{class:"hamburger",active:e.isScreenOpen,onClick:s[0]||(s[0]=o=>n.$emit("toggle-screen"))},null,8,["active"])])])],2))}});const Ff=O(Bf,[["__scopeId","data-v-6f1d18b5"]]);function Hf(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t1),Ht=[],Fn=!1,io=-1,nn=void 0,Ct=void 0,sn=void 0,gi=function(t){return Ht.some(function(n){return!!(n.options.allowTouchMove&&n.options.allowTouchMove(t))})},Hn=function(t){var n=t||window.event;return gi(n.target)||n.touches.length>1?!0:(n.preventDefault&&n.preventDefault(),!1)},Df=function(t){if(sn===void 0){var n=!!t&&t.reserveScrollBarGap===!0,s=window.innerWidth-document.documentElement.clientWidth;if(n&&s>0){var o=parseInt(window.getComputedStyle(document.body).getPropertyValue("padding-right"),10);sn=document.body.style.paddingRight,document.body.style.paddingRight=o+s+"px"}}nn===void 0&&(nn=document.body.style.overflow,document.body.style.overflow="hidden")},Rf=function(){sn!==void 0&&(document.body.style.paddingRight=sn,sn=void 0),nn!==void 0&&(document.body.style.overflow=nn,nn=void 0)},Uf=function(){return window.requestAnimationFrame(function(){if(Ct===void 0){Ct={position:document.body.style.position,top:document.body.style.top,left:document.body.style.left};var t=window,n=t.scrollY,s=t.scrollX,o=t.innerHeight;document.body.style.position="fixed",document.body.style.top=-n,document.body.style.left=-s,setTimeout(function(){return window.requestAnimationFrame(function(){var r=o-window.innerHeight;r&&n>=o&&(document.body.style.top=-(n+r))})},300)}})},jf=function(){if(Ct!==void 0){var t=-parseInt(document.body.style.top,10),n=-parseInt(document.body.style.left,10);document.body.style.position=Ct.position,document.body.style.top=Ct.top,document.body.style.left=Ct.left,window.scrollTo(n,t),Ct=void 0}},zf=function(t){return t?t.scrollHeight-t.scrollTop<=t.clientHeight:!1},Kf=function(t,n){var s=t.targetTouches[0].clientY-io;return gi(t.target)?!1:n&&n.scrollTop===0&&s>0||zf(n)&&s<0?Hn(t):(t.stopPropagation(),!0)},Wf=function(t,n){if(!t){console.error("disableBodyScroll unsuccessful - targetElement must be provided when calling disableBodyScroll on IOS devices.");return}if(!Ht.some(function(o){return o.targetElement===t})){var s={targetElement:t,options:n||{}};Ht=[].concat(Hf(Ht),[s]),Bn?Uf():Df(n),Bn&&(t.ontouchstart=function(o){o.targetTouches.length===1&&(io=o.targetTouches[0].clientY)},t.ontouchmove=function(o){o.targetTouches.length===1&&Kf(o,t)},Fn||(document.addEventListener("touchmove",Hn,ro?{passive:!1}:void 0),Fn=!0))}},qf=function(){Bn&&(Ht.forEach(function(t){t.targetElement.ontouchstart=null,t.targetElement.ontouchmove=null}),Fn&&(document.removeEventListener("touchmove",Hn,ro?{passive:!1}:void 0),Fn=!1),io=-1),Bn?jf():Rf(),Ht=[]};const Gf=B({__name:"VPNavScreenMenuLink",props:{text:null,link:null},setup(e){const t=Xe("close-screen");return(n,s)=>(d(),Q(Yt,{class:"VPNavScreenMenuLink",href:e.link,onClick:_(t)},{default:I(()=>[Oe(ie(e.text),1)]),_:1},8,["href","onClick"]))}});const Yf=O(Gf,[["__scopeId","data-v-b7098508"]]),Qf={},Jf={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Xf=b("path",{d:"M18.9,10.9h-6v-6c0-0.6-0.4-1-1-1s-1,0.4-1,1v6h-6c-0.6,0-1,0.4-1,1s0.4,1,1,1h6v6c0,0.6,0.4,1,1,1s1-0.4,1-1v-6h6c0.6,0,1-0.4,1-1S19.5,10.9,18.9,10.9z"},null,-1),Zf=[Xf];function ed(e,t){return d(),v("svg",Jf,Zf)}const td=O(Qf,[["render",ed]]),nd=B({__name:"VPNavScreenMenuGroupLink",props:{text:null,link:null},setup(e){const t=Xe("close-screen");return(n,s)=>(d(),Q(Yt,{class:"VPNavScreenMenuGroupLink",href:e.link,onClick:_(t)},{default:I(()=>[Oe(ie(e.text),1)]),_:1},8,["href","onClick"]))}});const bi=O(nd,[["__scopeId","data-v-7f173864"]]),sd={class:"VPNavScreenMenuGroupSection"},od={key:0,class:"title"},rd=B({__name:"VPNavScreenMenuGroupSection",props:{text:null,items:null},setup(e){return(t,n)=>(d(),v("div",sd,[e.text?(d(),v("p",od,ie(e.text),1)):U("",!0),(d(!0),v(q,null,Ce(e.items,s=>(d(),Q(bi,{key:s.text,text:s.text,link:s.link},null,8,["text","link"]))),128))]))}});const id=O(rd,[["__scopeId","data-v-7478538b"]]),ld=["aria-controls","aria-expanded"],cd={class:"button-text"},ad=["id"],ud={key:1,class:"group"},fd=B({__name:"VPNavScreenMenuGroup",props:{text:null,items:null},setup(e){const t=e,n=me(!1),s=re(()=>`NavScreenGroup-${t.text.replace(" ","-").toLowerCase()}`);function o(){n.value=!n.value}return(r,i)=>(d(),v("div",{class:he(["VPNavScreenMenuGroup",{open:n.value}])},[b("button",{class:"button","aria-controls":_(s),"aria-expanded":n.value,onClick:o},[b("span",cd,ie(e.text),1),V(td,{class:"button-icon"})],8,ld),b("div",{id:_(s),class:"items"},[(d(!0),v(q,null,Ce(e.items,l=>(d(),v(q,{key:l.text},["link"in l?(d(),v("div",{key:l.text,class:"item"},[V(bi,{text:l.text,link:l.link},null,8,["text","link"])])):(d(),v("div",ud,[V(id,{text:l.text,items:l.items},null,8,["text","items"])]))],64))),128))],8,ad)],2))}});const dd=O(fd,[["__scopeId","data-v-5bc84358"]]),hd={key:0,class:"VPNavScreenMenu"},_d=B({__name:"VPNavScreenMenu",setup(e){const{theme:t}=ae();return(n,s)=>_(t).nav?(d(),v("nav",hd,[(d(!0),v(q,null,Ce(_(t).nav,o=>(d(),v(q,{key:o.text},["link"in o?(d(),Q(Yf,{key:0,text:o.text,link:o.link},null,8,["text","link"])):(d(),Q(dd,{key:1,text:o.text||"",items:o.items},null,8,["text","items"]))],64))),128))])):U("",!0)}}),pd=e=>(We("data-v-7bc19822"),e=e(),qe(),e),vd={key:0,class:"VPNavScreenAppearance"},md=pd(()=>b("p",{class:"text"},"Appearance",-1)),gd=B({__name:"VPNavScreenAppearance",setup(e){const{site:t}=ae();return(n,s)=>_(t).appearance?(d(),v("div",vd,[md,V(so)])):U("",!0)}});const bd=O(gd,[["__scopeId","data-v-7bc19822"]]),yd={class:"list"},wd=["href"],xd=B({__name:"VPNavScreenTranslations",setup(e){const{theme:t}=ae(),n=me(!1);function s(){n.value=!n.value}return(o,r)=>_(t).localeLinks?(d(),v("div",{key:0,class:he(["VPNavScreenTranslations",{open:n.value}])},[b("button",{class:"title",onClick:s},[V(mi,{class:"icon lang"}),Oe(" "+ie(_(t).localeLinks.text)+" ",1),V(vi,{class:"icon chevron"})]),b("ul",yd,[(d(!0),v(q,null,Ce(_(t).localeLinks.items,i=>(d(),v("li",{key:i.link,class:"item"},[b("a",{class:"link",href:i.link},ie(i.text),9,wd)]))),128))])],2)):U("",!0)}});const $d=O(xd,[["__scopeId","data-v-6bfcad30"]]),Pd=B({__name:"VPNavScreenSocialLinks",setup(e){const{theme:t}=ae();return(n,s)=>_(t).socialLinks?(d(),Q(oo,{key:0,class:"VPNavScreenSocialLinks",links:_(t).socialLinks},null,8,["links"])):U("",!0)}}),kd={class:"container"},Cd=B({__name:"VPNavScreen",props:{open:{type:Boolean}},setup(e){const t=me(null);function n(){Wf(t.value,{reserveScrollBarGap:!0})}function s(){qf()}return(o,r)=>(d(),Q(ts,{name:"fade",onEnter:n,onAfterLeave:s},{default:I(()=>[e.open?(d(),v("div",{key:0,class:"VPNavScreen",ref_key:"screen",ref:t},[b("div",kd,[E(o.$slots,"nav-screen-content-before",{},void 0,!0),V(_d,{class:"menu"}),V($d,{class:"translations"}),V(bd,{class:"appearance"}),V(Pd,{class:"social-links"}),E(o.$slots,"nav-screen-content-after",{},void 0,!0)])],512)):U("",!0)]),_:3}))}});const Sd=O(Cd,[["__scopeId","data-v-3428b523"]]),Vd=B({__name:"VPNav",setup(e){const{isScreenOpen:t,closeScreen:n,toggleScreen:s}=ka(),{hasSidebar:o}=et();return Qn("close-screen",n),(r,i)=>(d(),v("header",{class:he(["VPNav",{"no-sidebar":!_(o)}])},[V(Ff,{"is-screen-open":_(t),onToggleScreen:_(s)},{"nav-bar-title-before":I(()=>[E(r.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":I(()=>[E(r.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":I(()=>[E(r.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":I(()=>[E(r.$slots,"nav-bar-content-after",{},void 0,!0)]),_:3},8,["is-screen-open","onToggleScreen"]),V(Sd,{open:_(t)},{"nav-screen-content-before":I(()=>[E(r.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":I(()=>[E(r.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3},8,["open"])],2))}});const Td=O(Vd,[["__scopeId","data-v-a71a30f1"]]),Ed={},Ld={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Md=b("path",{d:"M17,11H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,11,17,11z"},null,-1),Id=b("path",{d:"M21,7H3C2.4,7,2,6.6,2,6s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,7,21,7z"},null,-1),Ad=b("path",{d:"M21,15H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,15,21,15z"},null,-1),Nd=b("path",{d:"M17,19H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,19,17,19z"},null,-1),Od=[Md,Id,Ad,Nd];function Bd(e,t){return d(),v("svg",Ld,Od)}const Fd=O(Ed,[["render",Bd]]),Hd=e=>(We("data-v-aac27d5e"),e=e(),qe(),e),Dd={key:0,class:"VPLocalNav"},Rd=["aria-expanded"],Ud=Hd(()=>b("span",{class:"menu-text"},"Menu",-1)),jd=B({__name:"VPLocalNav",props:{open:{type:Boolean}},emits:["open-menu"],setup(e){const{hasSidebar:t}=et();function n(){window.scrollTo({top:0,left:0,behavior:"smooth"})}return(s,o)=>_(t)?(d(),v("div",Dd,[b("button",{class:"menu","aria-expanded":e.open,"aria-controls":"VPSidebarNav",onClick:o[0]||(o[0]=r=>s.$emit("open-menu"))},[V(Fd,{class:"menu-icon"}),Ud],8,Rd),b("a",{class:"top-link",href:"#",onClick:n}," Return to top ")])):U("",!0)}});const zd=O(jd,[["__scopeId","data-v-aac27d5e"]]),Kd={},Wd={version:"1.1",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},qd=b("path",{d:"M19,2H5C3.3,2,2,3.3,2,5v14c0,1.7,1.3,3,3,3h14c1.7,0,3-1.3,3-3V5C22,3.3,20.7,2,19,2z M20,19c0,0.6-0.4,1-1,1H5c-0.6,0-1-0.4-1-1V5c0-0.6,0.4-1,1-1h14c0.6,0,1,0.4,1,1V19z"},null,-1),Gd=b("path",{d:"M16,11h-3V8c0-0.6-0.4-1-1-1s-1,0.4-1,1v3H8c-0.6,0-1,0.4-1,1s0.4,1,1,1h3v3c0,0.6,0.4,1,1,1s1-0.4,1-1v-3h3c0.6,0,1-0.4,1-1S16.6,11,16,11z"},null,-1),Yd=[qd,Gd];function Qd(e,t){return d(),v("svg",Wd,Yd)}const Jd=O(Kd,[["render",Qd]]),Xd={},Zd={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 24 24"},eh=b("path",{d:"M19,2H5C3.3,2,2,3.3,2,5v14c0,1.7,1.3,3,3,3h14c1.7,0,3-1.3,3-3V5C22,3.3,20.7,2,19,2zM20,19c0,0.6-0.4,1-1,1H5c-0.6,0-1-0.4-1-1V5c0-0.6,0.4-1,1-1h14c0.6,0,1,0.4,1,1V19z"},null,-1),th=b("path",{d:"M16,11H8c-0.6,0-1,0.4-1,1s0.4,1,1,1h8c0.6,0,1-0.4,1-1S16.6,11,16,11z"},null,-1),nh=[eh,th];function sh(e,t){return d(),v("svg",Zd,nh)}const oh=O(Xd,[["render",sh]]),rh=B({__name:"VPSidebarLink",props:{item:null,depth:{default:1}},setup(e){const{page:t,frontmatter:n}=ae(),s=re(()=>n.value.sidebarDepth||1/0),o=Xe("close-sidebar");return(r,i)=>{const l=Tt("VPSidebarLink",!0);return d(),v(q,null,[V(Yt,{class:he(["link",{active:_(Gt)(_(t).relativePath,e.item.link)}]),style:Dn({paddingLeft:16*(e.depth-1)+"px"}),href:e.item.link,onClick:_(o)},{default:I(()=>[b("span",{class:he(["link-text",{light:e.depth>1}])},ie(e.item.text),3)]),_:1},8,["class","style","href","onClick"]),"items"in e.item&&e.depth<_(s)?(d(!0),v(q,{key:0},Ce(e.item.items,c=>(d(),Q(l,{key:c.link,item:c,depth:e.depth+1},null,8,["item","depth"]))),128)):U("",!0)],64)}}});const ih=O(rh,[["__scopeId","data-v-2cfe069a"]]),lh=["role"],ch={class:"title-text"},ah={class:"action"},uh={class:"items"},fh=B({__name:"VPSidebarGroup",props:{text:null,items:null,collapsible:{type:Boolean},collapsed:{type:Boolean}},setup(e){const t=e,n=me(!1);Ut(()=>{n.value=!!(t.collapsible&&t.collapsed)});const{page:s}=ae();Ut(()=>{t.items.some(r=>Gt(s.value.relativePath,r.link))&&(n.value=!1)});function o(){t.collapsible&&(n.value=!n.value)}return(r,i)=>(d(),v("section",{class:he(["VPSidebarGroup",{collapsible:e.collapsible,collapsed:n.value}])},[e.text?(d(),v("div",{key:0,class:"title",role:e.collapsible?"button":void 0,onClick:o},[b("h2",ch,ie(e.text),1),b("div",ah,[V(oh,{class:"icon minus"}),V(Jd,{class:"icon plus"})])],8,lh)):U("",!0),b("div",uh,[(d(!0),v(q,null,Ce(e.items,l=>(d(),Q(ih,{key:l.link,item:l},null,8,["item"]))),128))])],2))}});const dh=O(fh,[["__scopeId","data-v-35f99ef5"]]),hh=e=>(We("data-v-f332cb62"),e=e(),qe(),e),_h={class:"nav",id:"VPSidebarNav","aria-labelledby":"sidebar-aria-label",tabindex:"-1"},ph=hh(()=>b("span",{class:"visually-hidden",id:"sidebar-aria-label"}," Sidebar Navigation ",-1)),vh=B({__name:"VPSidebar",props:{open:{type:Boolean}},setup(e){const t=e,{sidebar:n,hasSidebar:s}=et();let o=me(null);return Or(async()=>{var r;t.open&&(await qn(),(r=o.value)==null||r.focus())}),(r,i)=>_(s)?(d(),v("aside",{key:0,class:he(["VPSidebar",{open:e.open}]),ref_key:"navEl",ref:o,onClick:i[0]||(i[0]=Kc(()=>{},["stop"]))},[b("nav",_h,[ph,(d(!0),v(q,null,Ce(_(n),l=>(d(),v("div",{key:l.text,class:"group"},[V(dh,{text:l.text,items:l.items,collapsible:l.collapsible,collapsed:l.collapsed},null,8,["text","items","collapsible","collapsed"])]))),128))])],2)):U("",!0)}});const mh=O(vh,[["__scopeId","data-v-f332cb62"]]),gh={},bh={class:"VPPage"};function yh(e,t){const n=Tt("Content");return d(),v("div",bh,[V(n)])}const wh=O(gh,[["render",yh]]),xh=B({__name:"VPButton",props:{tag:null,size:null,theme:null,text:null,href:null},setup(e){const t=e,n=re(()=>{var r,i;return[(r=t.size)!=null?r:"medium",(i=t.theme)!=null?i:"brand"]}),s=re(()=>t.href&&ns.test(t.href)),o=re(()=>t.tag?t.tag:t.href?"a":"button");return(r,i)=>(d(),Q(Ys(_(o)),{class:he(["VPButton",_(n)]),href:e.href?_(On)(e.href):void 0,target:_(s)?"_blank":void 0,rel:_(s)?"noreferrer":void 0},{default:I(()=>[Oe(ie(e.text),1)]),_:1},8,["class","href","target","rel"]))}});const $h=O(xh,[["__scopeId","data-v-53dbb8eb"]]),Ph=e=>(We("data-v-923ba72e"),e=e(),qe(),e),kh={class:"container"},Ch={class:"main"},Sh={key:0,class:"name"},Vh={class:"clip"},Th={key:1,class:"text"},Eh={key:2,class:"tagline"},Lh={key:3,class:"actions"},Mh={key:0,class:"image"},Ih={class:"image-container"},Ah=Ph(()=>b("div",{class:"image-bg"},null,-1)),Nh=B({__name:"VPHero",props:{name:null,text:null,tagline:null,image:null,actions:null},setup(e){return(t,n)=>(d(),v("div",{class:he(["VPHero",{"has-image":e.image}])},[b("div",kh,[b("div",Ch,[e.name?(d(),v("h1",Sh,[b("span",Vh,ie(e.name),1)])):U("",!0),e.text?(d(),v("p",Th,ie(e.text),1)):U("",!0),e.tagline?(d(),v("p",Eh,ie(e.tagline),1)):U("",!0),e.actions?(d(),v("div",Lh,[(d(!0),v(q,null,Ce(e.actions,s=>(d(),v("div",{key:s.link,class:"action"},[V($h,{tag:"a",size:"medium",theme:s.theme,text:s.text,href:s.link},null,8,["theme","text","href"])]))),128))])):U("",!0)]),e.image?(d(),v("div",Mh,[b("div",Ih,[Ah,V(hi,{class:"image-src",image:e.image},null,8,["image"])])])):U("",!0)])],2))}});const Oh=O(Nh,[["__scopeId","data-v-923ba72e"]]),Bh=B({__name:"VPHomeHero",setup(e){const{frontmatter:t}=ae();return(n,s)=>_(t).hero?(d(),Q(Oh,{key:0,class:"VPHomeHero",name:_(t).hero.name,text:_(t).hero.text,tagline:_(t).hero.tagline,image:_(t).hero.image,actions:_(t).hero.actions},null,8,["name","text","tagline","image","actions"])):U("",!0)}}),Fh={class:"VPFeature"},Hh={key:0,class:"icon"},Dh={class:"title"},Rh={class:"details"},Uh=B({__name:"VPFeature",props:{icon:null,title:null,details:null},setup(e){return(t,n)=>(d(),v("article",Fh,[e.icon?(d(),v("div",Hh,ie(e.icon),1)):U("",!0),b("h2",Dh,ie(e.title),1),b("p",Rh,ie(e.details),1)]))}});const jh=O(Uh,[["__scopeId","data-v-d99b2f77"]]),zh={key:0,class:"VPFeatures"},Kh={class:"container"},Wh={class:"items"},qh=B({__name:"VPFeatures",props:{features:null},setup(e){const t=e,n=re(()=>{const s=t.features.length;if(s){if(s===2)return"grid-2";if(s===3)return"grid-3";if(s%3===0)return"grid-6";if(s%2===0)return"grid-4"}else return});return(s,o)=>e.features?(d(),v("div",zh,[b("div",Kh,[b("div",Wh,[(d(!0),v(q,null,Ce(e.features,r=>(d(),v("div",{key:r.title,class:he(["item",[_(n)]])},[V(jh,{icon:r.icon,title:r.title,details:r.details},null,8,["icon","title","details"])],2))),128))])])])):U("",!0)}});const Gh=O(qh,[["__scopeId","data-v-6a6451ec"]]),Yh=B({__name:"VPHomeFeatures",setup(e){const{frontmatter:t}=ae();return(n,s)=>_(t).features?(d(),Q(Gh,{key:0,class:"VPHomeFeatures",features:_(t).features},null,8,["features"])):U("",!0)}}),Qh={class:"VPHome"},Jh=B({__name:"VPHome",setup(e){return(t,n)=>{const s=Tt("Content");return d(),v("div",Qh,[E(t.$slots,"home-hero-before",{},void 0,!0),V(Bh),E(t.$slots,"home-hero-after",{},void 0,!0),E(t.$slots,"home-features-before",{},void 0,!0),V(Yh),E(t.$slots,"home-features-after",{},void 0,!0),V(s)])}}});const Xh=O(Jh,[["__scopeId","data-v-1db23833"]]);var nr;const _n=typeof window<"u";_n&&((nr=window==null?void 0:window.navigator)==null?void 0:nr.userAgent)&&/iP(ad|hone|od)/.test(window.navigator.userAgent);function Zh(e){return e}function e_(e){return Fi()?(Hi(e),!0):!1}function t_(e){return typeof e=="function"?re(e):me(e)}function n_(e,t=!0){Zs()?De(e):t?e():qn(e)}const s_=_n?window:void 0;_n&&window.document;_n&&window.navigator;_n&&window.location;function o_(e,t=!1){const n=me(),s=()=>n.value=Boolean(e());return s(),n_(s,t),n}function sr(e,t={}){const{window:n=s_}=t,s=o_(()=>n&&"matchMedia"in n&&typeof n.matchMedia=="function");let o;const r=me(!1),i=()=>{!o||("removeEventListener"in o?o.removeEventListener("change",l):o.removeListener(l))},l=()=>{!s.value||(i(),o=n.matchMedia(t_(e).value),r.value=o.matches,"addEventListener"in o?o.addEventListener("change",l):o.addListener(l))};return Ut(l),e_(()=>i()),r}const Es=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},Ls="__vueuse_ssr_handlers__";Es[Ls]=Es[Ls]||{};Es[Ls];var or;(function(e){e.UP="UP",e.RIGHT="RIGHT",e.DOWN="DOWN",e.LEFT="LEFT",e.NONE="NONE"})(or||(or={}));var r_=Object.defineProperty,rr=Object.getOwnPropertySymbols,i_=Object.prototype.hasOwnProperty,l_=Object.prototype.propertyIsEnumerable,ir=(e,t,n)=>t in e?r_(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,c_=(e,t)=>{for(var n in t||(t={}))i_.call(t,n)&&ir(e,n,t[n]);if(rr)for(var n of rr(t))l_.call(t,n)&&ir(e,n,t[n]);return e};const a_={easeInSine:[.12,0,.39,0],easeOutSine:[.61,1,.88,1],easeInOutSine:[.37,0,.63,1],easeInQuad:[.11,0,.5,0],easeOutQuad:[.5,1,.89,1],easeInOutQuad:[.45,0,.55,1],easeInCubic:[.32,0,.67,0],easeOutCubic:[.33,1,.68,1],easeInOutCubic:[.65,0,.35,1],easeInQuart:[.5,0,.75,0],easeOutQuart:[.25,1,.5,1],easeInOutQuart:[.76,0,.24,1],easeInQuint:[.64,0,.78,0],easeOutQuint:[.22,1,.36,1],easeInOutQuint:[.83,0,.17,1],easeInExpo:[.7,0,.84,0],easeOutExpo:[.16,1,.3,1],easeInOutExpo:[.87,0,.13,1],easeInCirc:[.55,0,1,.45],easeOutCirc:[0,.55,.45,1],easeInOutCirc:[.85,0,.15,1],easeInBack:[.36,0,.66,-.56],easeOutBack:[.34,1.56,.64,1],easeInOutBack:[.68,-.6,.32,1.6]};c_({linear:Zh},a_);function u_(){const{hasSidebar:e}=et(),t=sr("(min-width: 960px)"),n=sr("(min-width: 1280px)");return{isAsideEnabled:re(()=>!n.value&&!t.value?!1:e.value?n.value:t.value)}}const f_=71;function d_(e){if(e===!1)return[];let t=[];return document.querySelectorAll("h2, h3, h4, h5, h6").forEach(n=>{n.textContent&&n.id&&t.push({level:Number(n.tagName[1]),title:n.innerText.replace(/\s+#\s*$/,""),link:`#${n.id}`})}),h_(t,e)}function h_(e,t=2){return __(e,typeof t=="number"?[t,t]:t==="deep"?[2,6]:t)}function __(e,t){const n=[];return e=e.map(s=>({...s})),e.forEach((s,o)=>{s.level>=t[0]&&s.level<=t[1]&&p_(o,e,t)&&n.push(s)}),n}function p_(e,t,n){if(e===0)return!0;const s=t[e];for(let o=e-1;o>=0;o--){const r=t[o];if(r.level=n[0]&&r.level<=n[1])return r.children==null&&(r.children=[]),r.children.push(s),!1}return!0}function v_(e,t){const{isAsideEnabled:n}=u_(),s=ma(r,100);let o=null;De(()=>{requestAnimationFrame(r),window.addEventListener("scroll",s)}),qs(()=>{i(location.hash)}),pt(()=>{window.removeEventListener("scroll",s)});function r(){if(!n.value)return;const l=[].slice.call(e.value.querySelectorAll(".outline-link")),c=[].slice.call(document.querySelectorAll(".content .header-anchor")).filter(C=>l.some(j=>j.hash===C.hash&&C.offsetParent!==null)),f=window.scrollY,h=window.innerHeight,m=document.body.offsetHeight,x=Math.abs(f+h-m)<1;if(c.length&&x){i(c[c.length-1].hash);return}for(let C=0;C{const s=Tt("VPDocAsideOutlineItem",!0);return d(),v("ul",{class:he(e.root?"root":"nested")},[(d(!0),v(q,null,Ce(e.headers,({children:o,link:r,title:i})=>(d(),v("li",null,[b("a",{class:"outline-link",href:r,onClick:n[0]||(n[0]=(...l)=>e.onClick&&e.onClick(...l))},ie(i),9,g_),o!=null&&o.length?(d(),Q(s,{key:0,headers:o,onClick:e.onClick},null,8,["headers","onClick"])):U("",!0)]))),256))],2)}}});const y_=O(b_,[["__scopeId","data-v-1188541a"]]),w_=e=>(We("data-v-2865c0b0"),e=e(),qe(),e),x_={class:"content"},$_={class:"outline-title"},P_={"aria-labelledby":"doc-outline-aria-label"},k_=w_(()=>b("span",{class:"visually-hidden",id:"doc-outline-aria-label"}," Table of Contents for current page ",-1)),C_=B({__name:"VPDocAsideOutline",setup(e){const{frontmatter:t,theme:n}=ae(),s=re(()=>{var h;return(h=t.value.outline)!=null?h:n.value.outline}),o=Xe("onContentUpdated");o.value=()=>{r.value=d_(s.value)};const r=me([]),i=re(()=>r.value.length>0),l=me(),c=me();v_(l,c);function f({target:h}){const m="#"+h.href.split("#")[1],x=document.querySelector(decodeURIComponent(m));x==null||x.focus()}return(h,m)=>(d(),v("div",{class:he(["VPDocAsideOutline",{"has-outline":_(i)}]),ref_key:"container",ref:l},[b("div",x_,[b("div",{class:"outline-marker",ref_key:"marker",ref:c},null,512),b("div",$_,ie(_(n).outlineTitle||"On this page"),1),b("nav",P_,[k_,V(y_,{headers:r.value,root:!0,onClick:f},null,8,["headers"])])])],2))}});const S_=O(C_,[["__scopeId","data-v-2865c0b0"]]),V_={class:"VPDocAsideCarbonAds"},T_=B({__name:"VPDocAsideCarbonAds",setup(e){const t=()=>null;return(n,s)=>(d(),v("div",V_,[V(_(t))]))}}),E_=e=>(We("data-v-afc4c1a1"),e=e(),qe(),e),L_={class:"VPDocAside"},M_=E_(()=>b("div",{class:"spacer"},null,-1)),I_=B({__name:"VPDocAside",setup(e){const{theme:t}=ae();return(n,s)=>(d(),v("div",L_,[E(n.$slots,"aside-top",{},void 0,!0),E(n.$slots,"aside-outline-before",{},void 0,!0),V(S_),E(n.$slots,"aside-outline-after",{},void 0,!0),M_,E(n.$slots,"aside-ads-before",{},void 0,!0),_(t).carbonAds?(d(),Q(T_,{key:0})):U("",!0),E(n.$slots,"aside-ads-after",{},void 0,!0),E(n.$slots,"aside-bottom",{},void 0,!0)]))}});const A_=O(I_,[["__scopeId","data-v-afc4c1a1"]]);function N_(){const{theme:e,page:t}=ae();return re(()=>{const{text:n="Edit this page",pattern:s}=e.value.editLink||{},{relativePath:o}=t.value;return{url:s.replace(/:path/g,o),text:n}})}function O_(){const{page:e,theme:t,frontmatter:n}=ae();return re(()=>{const s=di(t.value.sidebar,e.value.relativePath),o=ga(s),r=o.findIndex(i=>Gt(e.value.relativePath,i.link));return{prev:n.value.prev?{...o[r-1],text:n.value.prev}:o[r-1],next:n.value.next?{...o[r+1],text:n.value.next}:o[r+1]}})}const B_={},F_={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},H_=b("path",{d:"M18,23H4c-1.7,0-3-1.3-3-3V6c0-1.7,1.3-3,3-3h7c0.6,0,1,0.4,1,1s-0.4,1-1,1H4C3.4,5,3,5.4,3,6v14c0,0.6,0.4,1,1,1h14c0.6,0,1-0.4,1-1v-7c0-0.6,0.4-1,1-1s1,0.4,1,1v7C21,21.7,19.7,23,18,23z"},null,-1),D_=b("path",{d:"M8,17c-0.3,0-0.5-0.1-0.7-0.3C7,16.5,6.9,16.1,7,15.8l1-4c0-0.2,0.1-0.3,0.3-0.5l9.5-9.5c1.2-1.2,3.2-1.2,4.4,0c1.2,1.2,1.2,3.2,0,4.4l-9.5,9.5c-0.1,0.1-0.3,0.2-0.5,0.3l-4,1C8.2,17,8.1,17,8,17zM9.9,12.5l-0.5,2.1l2.1-0.5l9.3-9.3c0.4-0.4,0.4-1.1,0-1.6c-0.4-0.4-1.2-0.4-1.6,0l0,0L9.9,12.5z M18.5,2.5L18.5,2.5L18.5,2.5z"},null,-1),R_=[H_,D_];function U_(e,t){return d(),v("svg",F_,R_)}const j_=O(B_,[["render",U_]]),z_={class:"VPLastUpdated"},K_=["datatime"],W_=B({__name:"VPDocFooterLastUpdated",setup(e){const{theme:t,page:n}=ae(),s=re(()=>new Date(n.value.lastUpdated)),o=re(()=>s.value.toISOString()),r=me("");return De(()=>{Ut(()=>{r.value=s.value.toLocaleString(window.navigator.language)})}),(i,l)=>{var c;return d(),v("p",z_,[Oe(ie((c=_(t).lastUpdatedText)!=null?c:"Last updated")+": ",1),b("time",{datatime:_(o)},ie(r.value),9,K_)])}}});const q_=O(W_,[["__scopeId","data-v-f7d51a9c"]]),G_={key:0,class:"VPDocFooter"},Y_={key:0,class:"edit-info"},Q_={key:0,class:"edit-link"},J_={key:1,class:"last-updated"},X_={key:1,class:"prev-next"},Z_={class:"pager"},e1=["href"],t1={class:"desc"},n1={class:"title"},s1=["href"],o1={class:"desc"},r1={class:"title"},i1=B({__name:"VPDocFooter",setup(e){const{theme:t,page:n,frontmatter:s}=ae(),o=N_(),r=O_(),i=re(()=>t.value.editLink&&s.value.editLink!==!1),l=re(()=>n.value.lastUpdated&&s.value.lastUpdated!==!1),c=re(()=>i.value||l.value||r.value.prev||r.value.next);return(f,h)=>{var m,x,C,j;return _(c)?(d(),v("footer",G_,[_(i)||_(l)?(d(),v("div",Y_,[_(i)?(d(),v("div",Q_,[V(Yt,{class:"edit-link-button",href:_(o).url,"no-icon":!0},{default:I(()=>[V(j_,{class:"edit-link-icon"}),Oe(" "+ie(_(o).text),1)]),_:1},8,["href"])])):U("",!0),_(l)?(d(),v("div",J_,[V(q_)])):U("",!0)])):U("",!0),_(r).prev||_(r).next?(d(),v("div",X_,[b("div",Z_,[_(r).prev?(d(),v("a",{key:0,class:"pager-link prev",href:_(On)(_(r).prev.link)},[b("span",t1,ie((x=(m=_(t).docFooter)==null?void 0:m.prev)!=null?x:"Previous page"),1),b("span",n1,ie(_(r).prev.text),1)],8,e1)):U("",!0)]),b("div",{class:he(["pager",{"has-prev":_(r).prev}])},[_(r).next?(d(),v("a",{key:0,class:"pager-link next",href:_(On)(_(r).next.link)},[b("span",o1,ie((j=(C=_(t).docFooter)==null?void 0:C.next)!=null?j:"Next page"),1),b("span",r1,ie(_(r).next.text),1)],8,s1)):U("",!0)],2)])):U("",!0)])):U("",!0)}}});const l1=O(i1,[["__scopeId","data-v-a54a85bd"]]),c1=e=>(We("data-v-37ebe389"),e=e(),qe(),e),a1={class:"container"},u1={key:0,class:"aside"},f1=c1(()=>b("div",{class:"aside-curtain"},null,-1)),d1={class:"aside-container"},h1={class:"aside-content"},_1={class:"content"},p1={class:"content-container"},v1={class:"main"},m1=B({__name:"VPDoc",setup(e){const t=vt(),{hasSidebar:n,hasAside:s}=et(),o=re(()=>t.path.replace(/[./]+/g,"_").replace(/_html$/,"")),r=me();return Qn("onContentUpdated",r),(i,l)=>{const c=Tt("Content");return d(),v("div",{class:he(["VPDoc",{"has-sidebar":_(n),"has-aside":_(s)}])},[b("div",a1,[_(s)?(d(),v("div",u1,[f1,b("div",d1,[b("div",h1,[V(A_,null,{"aside-top":I(()=>[E(i.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":I(()=>[E(i.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":I(()=>[E(i.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":I(()=>[E(i.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":I(()=>[E(i.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":I(()=>[E(i.$slots,"aside-ads-after",{},void 0,!0)]),_:3})])])])):U("",!0),b("div",_1,[b("div",p1,[E(i.$slots,"doc-before",{},void 0,!0),b("main",v1,[V(c,{class:he(["vp-doc",_(o)]),onContentUpdated:r.value},null,8,["class","onContentUpdated"])]),E(i.$slots,"doc-footer-before",{},void 0,!0),V(l1),E(i.$slots,"doc-after",{},void 0,!0)])])])],2)}}});const g1=O(m1,[["__scopeId","data-v-37ebe389"]]),b1=B({__name:"VPContent",setup(e){const t=vt(),{frontmatter:n}=ae(),{hasSidebar:s}=et(),o=Xe("NotFound");return(r,i)=>(d(),v("div",{class:he(["VPContent",{"has-sidebar":_(s),"is-home":_(n).layout==="home"}]),id:"VPContent"},[_(t).component===_(o)?(d(),Q(_(o),{key:0})):_(n).layout==="page"?(d(),Q(wh,{key:1})):_(n).layout==="home"?(d(),Q(Xh,{key:2},{"home-hero-before":I(()=>[E(r.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-after":I(()=>[E(r.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":I(()=>[E(r.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":I(()=>[E(r.$slots,"home-features-after",{},void 0,!0)]),_:3})):(d(),Q(g1,{key:3},{"doc-footer-before":I(()=>[E(r.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":I(()=>[E(r.$slots,"doc-before",{},void 0,!0)]),"doc-after":I(()=>[E(r.$slots,"doc-after",{},void 0,!0)]),"aside-top":I(()=>[E(r.$slots,"aside-top",{},void 0,!0)]),"aside-outline-before":I(()=>[E(r.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":I(()=>[E(r.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":I(()=>[E(r.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":I(()=>[E(r.$slots,"aside-ads-after",{},void 0,!0)]),"aside-bottom":I(()=>[E(r.$slots,"aside-bottom",{},void 0,!0)]),_:3}))],2))}});const y1=O(b1,[["__scopeId","data-v-c95df128"]]),w1={class:"container"},x1=["innerHTML"],$1=["innerHTML"],P1=B({__name:"VPFooter",setup(e){const{theme:t}=ae(),{hasSidebar:n}=et();return(s,o)=>_(t).footer?(d(),v("footer",{key:0,class:he(["VPFooter",{"has-sidebar":_(n)}])},[b("div",w1,[_(t).footer.message?(d(),v("p",{key:0,class:"message",innerHTML:_(t).footer.message},null,8,x1)):U("",!0),_(t).footer.copyright?(d(),v("p",{key:1,class:"copyright",innerHTML:_(t).footer.copyright},null,8,$1)):U("",!0)])],2)):U("",!0)}});const k1=O(P1,[["__scopeId","data-v-9f24cc86"]]),C1={key:0,class:"Layout"},S1=B({__name:"Layout",setup(e){const{isOpen:t,open:n,close:s}=et(),o=vt();st(()=>o.path,s),ba(t,s),Qn("close-sidebar",s);const{frontmatter:r}=ae();return(i,l)=>{const c=Tt("Content");return _(r).layout!==!1?(d(),v("div",C1,[E(i.$slots,"layout-top",{},void 0,!0),V(wa),V(Pa,{class:"backdrop",show:_(t),onClick:_(s)},null,8,["show","onClick"]),V(Td,null,{"nav-bar-title-before":I(()=>[E(i.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":I(()=>[E(i.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":I(()=>[E(i.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":I(()=>[E(i.$slots,"nav-bar-content-after",{},void 0,!0)]),"nav-screen-content-before":I(()=>[E(i.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":I(()=>[E(i.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3}),V(zd,{open:_(t),onOpenMenu:_(n)},null,8,["open","onOpenMenu"]),V(mh,{open:_(t)},null,8,["open"]),V(y1,null,{"home-hero-before":I(()=>[E(i.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-after":I(()=>[E(i.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":I(()=>[E(i.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":I(()=>[E(i.$slots,"home-features-after",{},void 0,!0)]),"doc-footer-before":I(()=>[E(i.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":I(()=>[E(i.$slots,"doc-before",{},void 0,!0)]),"doc-after":I(()=>[E(i.$slots,"doc-after",{},void 0,!0)]),"aside-top":I(()=>[E(i.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":I(()=>[E(i.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":I(()=>[E(i.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":I(()=>[E(i.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":I(()=>[E(i.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":I(()=>[E(i.$slots,"aside-ads-after",{},void 0,!0)]),_:3}),V(k1),E(i.$slots,"layout-bottom",{},void 0,!0)])):(d(),Q(c,{key:1}))}}});const V1=O(S1,[["__scopeId","data-v-c6a644e1"]]),os=e=>(We("data-v-95656537"),e=e(),qe(),e),T1={class:"NotFound"},E1=os(()=>b("p",{class:"code"},"404",-1)),L1=os(()=>b("h1",{class:"title"},"PAGE NOT FOUND",-1)),M1=os(()=>b("div",{class:"divider"},null,-1)),I1=os(()=>b("blockquote",{class:"quote"}," But if you don't change your direction, and if you keep looking, you may end up where you are heading. ",-1)),A1={class:"action"},N1=["href"],O1=B({__name:"NotFound",setup(e){const{site:t}=ae();return(n,s)=>(d(),v("div",T1,[E1,L1,M1,I1,b("div",A1,[b("a",{class:"link",href:_(t).base,"aria-label":"go to home"}," Take me home ",8,N1)])]))}});const B1=O(O1,[["__scopeId","data-v-95656537"]]);const Dt={Layout:V1,NotFound:B1};function F1(e,t){let n=[],s=!0;const o=r=>{if(s){s=!1;return}n.forEach(i=>document.head.removeChild(i)),n=[],r.forEach(i=>{const l=H1(i);document.head.appendChild(l),n.push(l)})};Ut(()=>{const r=e.data,i=t.value,l=r&&r.description,c=r&&r.frontmatter.head||[];document.title=li(i,r),document.querySelector("meta[name=description]").setAttribute("content",l||i.description),o(ia(i.head,R1(c)))})}function H1([e,t,n]){const s=document.createElement(e);for(const o in t)s.setAttribute(o,t[o]);return n&&(s.innerHTML=n),s}function D1(e){return e[0]==="meta"&&e[1]&&e[1].name==="description"}function R1(e){return e.filter(t=>!D1(t))}const ps=new Set,yi=()=>document.createElement("link"),U1=e=>{const t=yi();t.rel="prefetch",t.href=e,document.head.appendChild(t)},j1=e=>{const t=new XMLHttpRequest;t.open("GET",e,t.withCredentials=!0),t.send()};let Pn;const z1=Ee&&(Pn=yi())&&Pn.relList&&Pn.relList.supports&&Pn.relList.supports("prefetch")?U1:j1;function K1(){if(!Ee||!window.IntersectionObserver)return;let e;if((e=navigator.connection)&&(e.saveData||/2g/.test(e.effectiveType)))return;const t=window.requestIdleCallback||setTimeout;let n=null;const s=()=>{n&&n.disconnect(),n=new IntersectionObserver(r=>{r.forEach(i=>{if(i.isIntersecting){const l=i.target;n.unobserve(l);const{pathname:c}=l;if(!ps.has(c)){ps.add(c);const f=ci(c);z1(f)}}})}),t(()=>{document.querySelectorAll("#app a").forEach(r=>{const{target:i,hostname:l,pathname:c}=r,f=c.match(/\.\w+$/);f&&f[0]!==".html"||i!=="_blank"&&l===location.hostname&&(c!==location.pathname?n.observe(r):ps.add(c))})})};De(s);const o=vt();st(()=>o.path,s),pt(()=>{n&&n.disconnect()})}const W1=B({setup(e,{slots:t}){const n=me(!1);return De(()=>{n.value=!0}),()=>n.value&&t.default?t.default():null}});function q1(){if(Ee){const e=new Map;window.addEventListener("click",t=>{var s;const n=t.target;if(n.matches('div[class*="language-"] > button.copy')){const o=n.parentElement,r=(s=n.nextElementSibling)==null?void 0:s.nextElementSibling;if(!o||!r)return;const i=/language-(shellscript|shell|bash|sh|zsh)/.test(o.classList.toString());let{innerText:l=""}=r;i&&(l=l.replace(/^ *(\$|>) /gm,"")),G1(l).then(()=>{n.classList.add("copied"),clearTimeout(e.get(n));const c=setTimeout(()=>{n.classList.remove("copied"),n.blur(),e.delete(n)},2e3);e.set(n,c)})}})}}async function G1(e){try{return navigator.clipboard.writeText(e)}catch{const t=document.createElement("textarea"),n=document.activeElement;t.value=e,t.setAttribute("readonly",""),t.style.contain="strict",t.style.position="absolute",t.style.left="-9999px",t.style.fontSize="12pt";const s=document.getSelection(),o=s?s.rangeCount>0&&s.getRangeAt(0):null;document.body.appendChild(t),t.select(),t.selectionStart=0,t.selectionEnd=e.length,document.execCommand("copy"),document.body.removeChild(t),o&&(s.removeAllRanges(),s.addRange(o)),n&&n.focus()}}const wi=Dt.NotFound||(()=>"404 Not Found"),Y1=B({name:"VitePressApp",setup(){const{site:e}=ae();return De(()=>{st(()=>e.value.lang,t=>{document.documentElement.lang=t},{immediate:!0})}),K1(),q1(),Dt.setup&&Dt.setup(),()=>Nn(Dt.Layout)}});function Q1(){const e=X1(),t=J1();t.provide(ui,e);const n=ca(e.route);return t.provide(ai,n),t.provide("NotFound",wi),t.component("Content",da),t.component("ClientOnly",W1),Object.defineProperty(t.config.globalProperties,"$frontmatter",{get(){return n.frontmatter.value}}),Dt.enhanceApp&&Dt.enhanceApp({app:t,router:e,siteData:zt}),{app:t,router:e,data:n}}function J1(){return Gc(Y1)}function X1(){let e=Ee,t;return ua(n=>{let s=ci(n);return e&&(t=s),(e||t===s)&&(s=s.replace(/\.js$/,".lean.js")),Ee&&(e=!1),Xc(()=>import(s),[])},wi)}if(Ee){const{app:e,router:t,data:n}=Q1();t.go().then(()=>{F1(t.route,n.site),e.mount("#app")})}export{O as _,lc as a,b,v as c,Q1 as createApp,Oe as d,d as o}; diff --git a/assets/guide-to-incrementals_index.md.da67c4dd.js b/assets/guide-to-incrementals_index.md.01643183.js similarity index 97% rename from assets/guide-to-incrementals_index.md.da67c4dd.js rename to assets/guide-to-incrementals_index.md.01643183.js index 475a2bdaf..95e88b26a 100644 --- a/assets/guide-to-incrementals_index.md.da67c4dd.js +++ b/assets/guide-to-incrementals_index.md.01643183.js @@ -1 +1 @@ -import{_ as e,c as t,o as a,a as n}from"./app.a576d425.js";const u=JSON.parse('{"title":"Introduction","description":"","frontmatter":{"title":"Introduction"},"headers":[{"level":2,"title":"Who am I?","slug":"who-am-i","link":"#who-am-i","children":[]}],"relativePath":"guide-to-incrementals/index.md","lastUpdated":null}'),o={name:"guide-to-incrementals/index.md"},i=n('

Introduction

This is a comprehensive guide to Incremental Games, a genre of video games. It will explore defining the genre, why it's appealing, and how to design and build your own incremental game. Along the way will be interactive examples, snippets from other creators, and relevant material to contextualize everything.

Note: This is an incomplete document. I want to keep adding opinions and opposing views from other incremental games developers, and add interactive examples to illustrate various points regarding game design and balancing. Consider this a living document - and see the changelog at the end.

Who am I?

That's a good question! What authority do I have to be making this site? I haven't made the best incremental games, nor the most incremental games, certainly not the most popular ones either. I do have some formal education in game development, know a lot of incremental game devs, as well as other game devs, and an interest in ludology, classifying genres, etc. I've also made a couple of incremental games myself.

If you have any additional questions about my credentials or anything on this site, feel free to contact me: I'm "The Paper Pilot" on most social media. You'll probably get a response fastest via my discord server, or if you just want to suggest changes to the website you can click the "Edit this page" link present on every single page.

',6),r=[i];function s(l,d,c,h,m,p){return a(),t("div",null,r)}const _=e(o,[["render",s]]);export{u as __pageData,_ as default}; +import{_ as e,c as t,o as a,a as n}from"./app.9bfeb8de.js";const u=JSON.parse('{"title":"Introduction","description":"","frontmatter":{"title":"Introduction"},"headers":[{"level":2,"title":"Who am I?","slug":"who-am-i","link":"#who-am-i","children":[]}],"relativePath":"guide-to-incrementals/index.md","lastUpdated":null}'),o={name:"guide-to-incrementals/index.md"},i=n('

Introduction

This is a comprehensive guide to Incremental Games, a genre of video games. It will explore defining the genre, why it's appealing, and how to design and build your own incremental game. Along the way will be interactive examples, snippets from other creators, and relevant material to contextualize everything.

Note: This is an incomplete document. I want to keep adding opinions and opposing views from other incremental games developers, and add interactive examples to illustrate various points regarding game design and balancing. Consider this a living document - and see the changelog at the end.

Who am I?

That's a good question! What authority do I have to be making this site? I haven't made the best incremental games, nor the most incremental games, certainly not the most popular ones either. I do have some formal education in game development, know a lot of incremental game devs, as well as other game devs, and an interest in ludology, classifying genres, etc. I've also made a couple of incremental games myself.

If you have any additional questions about my credentials or anything on this site, feel free to contact me: I'm "The Paper Pilot" on most social media. You'll probably get a response fastest via my discord server, or if you just want to suggest changes to the website you can click the "Edit this page" link present on every single page.

',6),r=[i];function s(l,d,c,h,m,p){return a(),t("div",null,r)}const _=e(o,[["render",s]]);export{u as __pageData,_ as default}; diff --git a/assets/guide-to-incrementals_index.md.da67c4dd.lean.js b/assets/guide-to-incrementals_index.md.01643183.lean.js similarity index 87% rename from assets/guide-to-incrementals_index.md.da67c4dd.lean.js rename to assets/guide-to-incrementals_index.md.01643183.lean.js index 62466d559..e59972fd6 100644 --- a/assets/guide-to-incrementals_index.md.da67c4dd.lean.js +++ b/assets/guide-to-incrementals_index.md.01643183.lean.js @@ -1 +1 @@ -import{_ as e,c as t,o as a,a as n}from"./app.a576d425.js";const u=JSON.parse('{"title":"Introduction","description":"","frontmatter":{"title":"Introduction"},"headers":[{"level":2,"title":"Who am I?","slug":"who-am-i","link":"#who-am-i","children":[]}],"relativePath":"guide-to-incrementals/index.md","lastUpdated":null}'),o={name:"guide-to-incrementals/index.md"},i=n("",6),r=[i];function s(l,d,c,h,m,p){return a(),t("div",null,r)}const _=e(o,[["render",s]]);export{u as __pageData,_ as default}; +import{_ as e,c as t,o as a,a as n}from"./app.9bfeb8de.js";const u=JSON.parse('{"title":"Introduction","description":"","frontmatter":{"title":"Introduction"},"headers":[{"level":2,"title":"Who am I?","slug":"who-am-i","link":"#who-am-i","children":[]}],"relativePath":"guide-to-incrementals/index.md","lastUpdated":null}'),o={name:"guide-to-incrementals/index.md"},i=n("",6),r=[i];function s(l,d,c,h,m,p){return a(),t("div",null,r)}const _=e(o,[["render",s]]);export{u as __pageData,_ as default}; diff --git a/assets/guide-to-incrementals_ludology_appeal-developers.md.005a3b47.lean.js b/assets/guide-to-incrementals_ludology_appeal-developers.md.2e6312d0.js similarity index 83% rename from assets/guide-to-incrementals_ludology_appeal-developers.md.005a3b47.lean.js rename to assets/guide-to-incrementals_ludology_appeal-developers.md.2e6312d0.js index e6ecb0e60..d2d363439 100644 --- a/assets/guide-to-incrementals_ludology_appeal-developers.md.005a3b47.lean.js +++ b/assets/guide-to-incrementals_ludology_appeal-developers.md.2e6312d0.js @@ -1 +1 @@ -import{_ as e,c as t,o as a}from"./app.a576d425.js";const _=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide-to-incrementals/ludology/appeal-developers.md","lastUpdated":null}'),o={name:"guide-to-incrementals/ludology/appeal-developers.md"};function r(s,l,p,n,c,d){return a(),t("div")}const m=e(o,[["render",r]]);export{_ as __pageData,m as default}; +import{_ as e,c as t,o as a}from"./app.9bfeb8de.js";const _=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide-to-incrementals/ludology/appeal-developers.md","lastUpdated":null}'),o={name:"guide-to-incrementals/ludology/appeal-developers.md"};function r(s,l,p,n,c,d){return a(),t("div")}const m=e(o,[["render",r]]);export{_ as __pageData,m as default}; diff --git a/assets/guide-to-incrementals_ludology_appeal-developers.md.005a3b47.js b/assets/guide-to-incrementals_ludology_appeal-developers.md.2e6312d0.lean.js similarity index 83% rename from assets/guide-to-incrementals_ludology_appeal-developers.md.005a3b47.js rename to assets/guide-to-incrementals_ludology_appeal-developers.md.2e6312d0.lean.js index e6ecb0e60..d2d363439 100644 --- a/assets/guide-to-incrementals_ludology_appeal-developers.md.005a3b47.js +++ b/assets/guide-to-incrementals_ludology_appeal-developers.md.2e6312d0.lean.js @@ -1 +1 @@ -import{_ as e,c as t,o as a}from"./app.a576d425.js";const _=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide-to-incrementals/ludology/appeal-developers.md","lastUpdated":null}'),o={name:"guide-to-incrementals/ludology/appeal-developers.md"};function r(s,l,p,n,c,d){return a(),t("div")}const m=e(o,[["render",r]]);export{_ as __pageData,m as default}; +import{_ as e,c as t,o as a}from"./app.9bfeb8de.js";const _=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide-to-incrementals/ludology/appeal-developers.md","lastUpdated":null}'),o={name:"guide-to-incrementals/ludology/appeal-developers.md"};function r(s,l,p,n,c,d){return a(),t("div")}const m=e(o,[["render",r]]);export{_ as __pageData,m as default}; diff --git a/assets/guide-to-incrementals_ludology_appeal-gamers.md.1941e23d.js b/assets/guide-to-incrementals_ludology_appeal-gamers.md.c0319ea4.js similarity index 83% rename from assets/guide-to-incrementals_ludology_appeal-gamers.md.1941e23d.js rename to assets/guide-to-incrementals_ludology_appeal-gamers.md.c0319ea4.js index 9dde3c4aa..4a18ae918 100644 --- a/assets/guide-to-incrementals_ludology_appeal-gamers.md.1941e23d.js +++ b/assets/guide-to-incrementals_ludology_appeal-gamers.md.c0319ea4.js @@ -1 +1 @@ -import{_ as e,c as a,o as t}from"./app.a576d425.js";const m=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide-to-incrementals/ludology/appeal-gamers.md","lastUpdated":null}'),o={name:"guide-to-incrementals/ludology/appeal-gamers.md"};function r(s,n,l,p,c,d){return t(),a("div")}const _=e(o,[["render",r]]);export{m as __pageData,_ as default}; +import{_ as e,c as a,o as t}from"./app.9bfeb8de.js";const m=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide-to-incrementals/ludology/appeal-gamers.md","lastUpdated":null}'),o={name:"guide-to-incrementals/ludology/appeal-gamers.md"};function r(s,n,l,p,c,d){return t(),a("div")}const _=e(o,[["render",r]]);export{m as __pageData,_ as default}; diff --git a/assets/guide-to-incrementals_ludology_appeal-gamers.md.1941e23d.lean.js b/assets/guide-to-incrementals_ludology_appeal-gamers.md.c0319ea4.lean.js similarity index 83% rename from assets/guide-to-incrementals_ludology_appeal-gamers.md.1941e23d.lean.js rename to assets/guide-to-incrementals_ludology_appeal-gamers.md.c0319ea4.lean.js index 9dde3c4aa..4a18ae918 100644 --- a/assets/guide-to-incrementals_ludology_appeal-gamers.md.1941e23d.lean.js +++ b/assets/guide-to-incrementals_ludology_appeal-gamers.md.c0319ea4.lean.js @@ -1 +1 @@ -import{_ as e,c as a,o as t}from"./app.a576d425.js";const m=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide-to-incrementals/ludology/appeal-gamers.md","lastUpdated":null}'),o={name:"guide-to-incrementals/ludology/appeal-gamers.md"};function r(s,n,l,p,c,d){return t(),a("div")}const _=e(o,[["render",r]]);export{m as __pageData,_ as default}; +import{_ as e,c as a,o as t}from"./app.9bfeb8de.js";const m=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide-to-incrementals/ludology/appeal-gamers.md","lastUpdated":null}'),o={name:"guide-to-incrementals/ludology/appeal-gamers.md"};function r(s,n,l,p,c,d){return t(),a("div")}const _=e(o,[["render",r]]);export{m as __pageData,_ as default}; diff --git a/assets/guide-to-incrementals_ludology_content.md.4c4f3543.js b/assets/guide-to-incrementals_ludology_content.md.d8a8c68c.js similarity index 82% rename from assets/guide-to-incrementals_ludology_content.md.4c4f3543.js rename to assets/guide-to-incrementals_ludology_content.md.d8a8c68c.js index ac1263f7f..e67720ee4 100644 --- a/assets/guide-to-incrementals_ludology_content.md.4c4f3543.js +++ b/assets/guide-to-incrementals_ludology_content.md.d8a8c68c.js @@ -1 +1 @@ -import{_ as t,c as e,o as n}from"./app.a576d425.js";const _=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide-to-incrementals/ludology/content.md","lastUpdated":null}'),o={name:"guide-to-incrementals/ludology/content.md"};function a(c,r,s,d,l,i){return n(),e("div")}const m=t(o,[["render",a]]);export{_ as __pageData,m as default}; +import{_ as t,c as e,o as n}from"./app.9bfeb8de.js";const _=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide-to-incrementals/ludology/content.md","lastUpdated":null}'),o={name:"guide-to-incrementals/ludology/content.md"};function a(c,r,s,d,l,i){return n(),e("div")}const m=t(o,[["render",a]]);export{_ as __pageData,m as default}; diff --git a/assets/guide-to-incrementals_ludology_content.md.4c4f3543.lean.js b/assets/guide-to-incrementals_ludology_content.md.d8a8c68c.lean.js similarity index 82% rename from assets/guide-to-incrementals_ludology_content.md.4c4f3543.lean.js rename to assets/guide-to-incrementals_ludology_content.md.d8a8c68c.lean.js index ac1263f7f..e67720ee4 100644 --- a/assets/guide-to-incrementals_ludology_content.md.4c4f3543.lean.js +++ b/assets/guide-to-incrementals_ludology_content.md.d8a8c68c.lean.js @@ -1 +1 @@ -import{_ as t,c as e,o as n}from"./app.a576d425.js";const _=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide-to-incrementals/ludology/content.md","lastUpdated":null}'),o={name:"guide-to-incrementals/ludology/content.md"};function a(c,r,s,d,l,i){return n(),e("div")}const m=t(o,[["render",a]]);export{_ as __pageData,m as default}; +import{_ as t,c as e,o as n}from"./app.9bfeb8de.js";const _=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"guide-to-incrementals/ludology/content.md","lastUpdated":null}'),o={name:"guide-to-incrementals/ludology/content.md"};function a(c,r,s,d,l,i){return n(),e("div")}const m=t(o,[["render",a]]);export{_ as __pageData,m as default}; diff --git a/assets/guide-to-incrementals_ludology_definition.md.cdcec89a.js b/assets/guide-to-incrementals_ludology_definition.md.effc1cd4.js similarity index 99% rename from assets/guide-to-incrementals_ludology_definition.md.cdcec89a.js rename to assets/guide-to-incrementals_ludology_definition.md.effc1cd4.js index 69e48e031..fae6b0666 100644 --- a/assets/guide-to-incrementals_ludology_definition.md.cdcec89a.js +++ b/assets/guide-to-incrementals_ludology_definition.md.effc1cd4.js @@ -1 +1 @@ -import{_ as e,c as t,o as a,a as r}from"./app.a576d425.js";const p=JSON.parse('{"title":"Defining the Genre","description":"","frontmatter":{"title":"Defining the Genre"},"headers":[{"level":2,"title":"Incrementals vs Idlers vs Clickers","slug":"incrementals-vs-idlers-vs-clickers","link":"#incrementals-vs-idlers-vs-clickers","children":[]},{"level":2,"title":"Incrementals as Parodies","slug":"incrementals-as-parodies","link":"#incrementals-as-parodies","children":[]},{"level":2,"title":"Incrementals as NGU","slug":"incrementals-as-ngu","link":"#incrementals-as-ngu","children":[]},{"level":2,"title":"Incrementals as Strategies","slug":"incrementals-as-strategies","link":"#incrementals-as-strategies","children":[]},{"level":2,"title":"Roguelites as Incrementals?","slug":"roguelites-as-incrementals","link":"#roguelites-as-incrementals","children":[{"level":3,"title":"The Berlin Interpretation","slug":"the-berlin-interpretation","link":"#the-berlin-interpretation","children":[]},{"level":3,"title":"The Incremental Games Canon","slug":"the-incremental-games-canon","link":"#the-incremental-games-canon","children":[]},{"level":3,"title":"The Paradigm Shift","slug":"the-paradigm-shift","link":"#the-paradigm-shift","children":[]},{"level":3,"title":"High-Value Factors","slug":"high-value-factors","link":"#high-value-factors","children":[]},{"level":3,"title":"Low-Value Factors","slug":"low-value-factors","link":"#low-value-factors","children":[]},{"level":3,"title":"Are Roguelites Incrementals?","slug":"are-roguelites-incrementals","link":"#are-roguelites-incrementals","children":[]}]},{"level":2,"title":"Sub-Genres","slug":"sub-genres","link":"#sub-genres","children":[]},{"level":2,"title":"Other Related Genres","slug":"other-related-genres","link":"#other-related-genres","children":[]}],"relativePath":"guide-to-incrementals/ludology/definition.md","lastUpdated":null}'),n={name:"guide-to-incrementals/ludology/definition.md"},i=r('

Defining the Genre

Video games are placed into genres for a variety of reasons. They can give a mental shorthand to set the player's expectations up, they can help a game market itself by its similarities to other, already popular games, and honestly, people just love categorization for its own sake. For this guide, it's important to define the genre so it is clear what games it's even talking about.

This poses a problem. "Incremental" is a horribly vague way to define games. Most games have numbers going up in some form or another. We need a more specific definition - similar to how "strategy" can't just mean any game with any amount of strategy because that would be most games. What specifically differentiates incremental games from the rest?

"Incremental" implies it's a genre defined by a game mechanic, but all those game mechanics it could imply exist in many other games. Having a skill tree or upgrades doesn't make you incremental, and if a reset mechanic is all it takes then every roguelite would be an incremental as well. So clearly there's more to it than that - what makes an incremental an incremental?

I'd like to go over a couple of popular suggestions I've seen on defining the genre here. I have my personal preferences and will state them here, but I don't think there's a truly perfect answer here.

Disclaimer: I mostly play incremental games on my computer, and my definitions will be heavily biased towards the games I'm familiar with.

Incrementals vs Idlers vs Clickers

Oftentimes people refer to this genre as idle games and/or clicker games. You'll even find a trend of oxymoronic game titles that contain both terms. "Incremental games" is the umbrella term both those terms fall under. However, I'd like to argue that not only is it better to just use the term "incremental games", but calling them "idle games" or "clicker games" is wrong. Almost universally, these terms are used interchangeably to refer to the same kind of game, where you start the game click spamming and eventually automate the process. Frankly, that kind of game deserves neither title, and the incremental games genre has trended away from ever requiring click spamming, as it's a bad mechanic, anyways.

While these games do span a spectrum of how active it requires you to be, and sorting games by that metric can be useful for those looking for a particular experience, the borders of when an incremental game counts as an "idler" is too blurry for the term to be useful. "Incremental games" may not be a great descriptive term for the genre (hence this many thousands of words long page on defining what the genre even is), but it's strictly better than calling them "idler" or "clicker" games. This guide will always use the term "incremental games" unless quoting someone else, as it is the term you typically see on all modern games in the genre.

Incrementals as Parodies

Let's start with one of the most interesting definitions of incremental games. Incremental games appear to be distilled versions of games or genres, "revealing" the naked game design at the core of these games or genres not unlike how parodies comment upon their source material.

To understand what that means, think of how a casino uses skinner boxes to emotionally manipulate its customers to keep playing, but "dressing" up the skinner box with tons of stimuli to hide that ultimately the goal is to manipulate you to keep coming back. The idea that incremental games are parodies means taking the stance that at some level all games are similarly manipulating you, giving dopamine rewards in a way that manipulates you to keep playing while not necessarily giving you any value or fulfillment. Incremental games, then, are any games that plainly display the skinner box, and the manipulative core of the game, at the forefront of the experience.

This "undressing" tends to go hand in hand with a reduced focus on aesthetics, often just printing the game state directly to the screen as text. This makes incremental games much easier to develop, particularly for those with programming skills but not art skills, but that's a tangent for why Incremental Games appeal to Developers.

Before I continue, I'd like to make my stance clear that I love games and incremental games, and do not think they should be considered inherently bad or manipulative with the above logic. Skinner boxes are just a way of manipulating behavior via rewards. The games are still fun - that's the reward! I'd believe the real criticism here is that it is "empty fun", or "empty dopamine", that doesn't offer any additional value or sense of fulfillment. I don't think that's inherently bad in moderation, although it can become a problem if the game is manipulating you for profit-seeking, or if you play the game to the detriment of the other parts of your life. While incremental games can be fun and even healthy in certain contexts, they can exacerbate video game addiction moreso than other genres. If you feel like playing incremental games is taking priority over other things in your life, or manipulating your sleep schedule, it may be prudent to seek help. See r/StopGaming for resources.

Another interpretation of incremental games as parodies comes from several mainstream incremental games that are also parodies of capitalism, such as cookie clicker and adventure capitalist. It's a very common framework for incremental games to portray the ever-increasing numbers as an insatiable hunger for resources, like the ones observed within capitalism. Therefore, these games are used as evidence that the genre as a whole is about parody and commentary.

Popular videos on incremental games that portray the genre as parodies are Why Idle games make good satire, and how it was ruined. and Bad Game Design - Clicker Games. You may also be interested in this response to the latter video from a fan of incremental games: BadGood Game Design - Clicker Games.

I think that this definition ultimately ascribes a motive to the genre as a whole that only happens to apply to some of the more mainstream titles. There certainly are incremental games commenting on different things, including the genre itself as in the case of The Prestige Tree Classic, The Ascension Tree, or Omega Layers, but certainly not all. And of course, not all games that comment on something or parody something are incremental games! Additionally, a very large majority of incremental games are mobile games using these manipulative strategies to get players to spend as much money as possible - hell, Adventure Capitalist is ostensibly a critique on capitalism but features microtransactions and gameplay that manipulates you into buying them! These profit-seeking incremental games certainly belong within the genre but are hardly parodies when they too use manipulation to serve their interests. Also, from my own anecdotal experience, those who use this definition seem to do so from a fairly surface-level familiarity with the genre, and often in the context of criticizing the genre or the fans thereof.

Incrementals as NGU

Another broad definition often used is that incremental games are games where the focus of the game is "numbers going up". This definition proposes that other genres simply use increasing numbers as a means to an end, but incremental games uniquely only care about the numbers themselves going up. Put another way, it implies there should be no narrative justification for the numbers going up other than "why shouldn't they be going up?"

While this definition is common because it feels easy to understand, it is difficult to formally define. Often phrases are used to describe games using this framework, such as having an "exaggerated sense of progression" or "big" numbers. These terms are vague and don't demonstrate an actual threshold between non-incrementals and incrementals. Most games have a sense of progression, so when is it "exaggerated"? How big are "big" numbers? Most notably, RPGs that are typically not considered incrementals will often pass this definition.

Additionally, a lot of incrementals tend to have some theme guiding the gameplay, or at least the names of mechanics. This makes the line blurred between when numbers are going up for their own sake versus for a contextual reason. I believe this point is best illustrated that, while most RPGs are not considered incremental games, there is a sub-genre of "incremental RPGs" that typically relates to RPGs that perform combat automatically. This definition of incremental games does not support RPGs and "incremental RPGs" being on distinct sides of the line if the only difference between them is manual vs automatic combat.

Incrementals as Strategies

This is a rarer interpretation, but there are similarities between incremental games and strategy games, implying incrementals might just be a sub-genre of strategy games. By this approach, incremental games would be defined by their relation to strategy games, and how they involve player strategy. Incremental games are often large optimization problems - above all else, the actual gameplay the player is performing is deciding what to do next. The consequences of wrong decisions are typically more lenient in incremental games - such as just not making optimal progress - but they certainly get complex.

So if we accept the premise that incrementals could fall under strategy, we still need to define what makes a strategy game an incremental versus some other strategy sub-genre. This is a bit tricky due to one particular sub-genre of strategy games: Factory Builders.

Factory builders, such as Factorio or Satisfactory, are games about gaining ever increasing resources, optimizing production, and expanding more and more. That... sounds pretty similar, doesn't it? In fact, there's been some debate on whether factory builders would fall under the "incremental" umbrella. I think it's safe to say the two are certainly related, and probably have quite a bit of overlap in playerbase.

Roguelites as Incrementals?

Earlier on, I mentioned reset mechanics shouldn't be used in the definition because that could make all roguelites incrementals... But what if it does? A lot of incrementals can be described as games with a strong sense of progression, often with layers of meta-progression. Roguelites fit that bill to a T. What would make roguelites not incremental? I honestly don't think there's a good explanation here, but many fans of incremental games will state they do believe the two genres to be unrelated, even if there's a significant overlap between their player bases due to having similar appealing traits.

At this point, it'd be appropriate to consider what part of the definition of roguelites precludes them from also being incrementals, but that reveals a new problem: What are roguelites? They're usually defined as rogue_likes with meta-progression, but that just pushes the problem back a step: Incrementals aren't the only genre to have difficulties defining themselves, it seems! Roguelikes are another genre where the community argues over the formal definition of their genre, although that means we can borrow from their process of coming to a consensus, and maybe come across a viable definition for incremental games.

The Berlin Interpretation

By far the most popular way of defining roguelikes is the "Berlin Interpretation", which acknowledged the diversity of games within the genre and argued the definition should not be based on any ideals about what the genre ought to be, but rather defined by "its canon". They argued there are a handful of games that can be used to define the canon for roguelikes, and from those games, a list of factors can be derived to determine a game's "roguelikeness". The more factors a game has, the more of a roguelike it is. This strategy is very lenient, allowing a game to not present any specific factor so long as it shows enough, and accounts for the blurriness of any genre definition by not explicitly stating how many factors a game must have to qualify as a definite roguelike.

I believe this strategy for defining genres can be applied to other genres as well. A handful of games can be argued to be the incremental games canon, and a list of factors derived from them can be used to judge any game based on its "incrementalness". I'll propose such a canon and list of factors here, but by no means should it be considered the end-all-be-all.

Note: The "Temple of the roguelike", an authority within the genre, has since replaced the Berlin Interpretation with a new set of factors here: https://blog.roguetemple.com/what-is-a-traditional-roguelike/

The Incremental Games Canon

Alright, time to get controversial. Up til now, I've been trying my best to stay objective and analytical, but now it's time to start making some opinionated decisions. Here is a list of games I think could justifiably make up an Incremental Games Canon:

I chose a variety of games here, biasing towards newer games, purposefully to avoid making a narrow or "traditional" definition. The genre is growing and shouldn't be constrained by the traits of the early popular titles. A lot of these could easily be replaced with other games that are mechanically congruent, so ultimately I'm sure if you asked 10 people for their canon list you'd just get 10 different answers, but I think this should sufficiently allow us to determine what factors make a game have higher "incrementalness".

The Paradigm Shift

The Paradigm Shift is probably the highest possible value factor for an incremental. It's so common that for a while people referred to incrementals that exhibit this trait as "unfolding" games, to the point of trying to replace the term incremental due to their popularity. Paradigm shifts refer to when the gameplay significantly changes. There are too many examples to list here, but notably, every single reset mechanic is typically going to be a paradigm shift. Examples of games with paradigm shifts that aren't tied to reset mechanics include Universal Paperclips and A Dark Room.

There are many reasons for the appeal of paradigm shifts. Oftentimes each mechanic builds on top of the existing mechanics, increasing the complexity of the game in steps so the player can follow along. They provide a sense of mystery, with the player anticipating what will happen next. They shake up the gameplay before it gets too stale - allowing the game to entertain for longer before the illusion of content dissipates. Of the canon games selected above, I would argue every single one contains a paradigm shift (although I could see someone disagreeing with that statement wrt Increlution).

I should take a moment to say that while I'm hyping up this specific factor, we cannot just reduce the genre definition to "does it have paradigm shifts". Many games have paradigm shifts that are not incremental, so it's just an indicator of incrementalness. Additionally, it can become quite hard to determine how large of a shift is a "paradigm" shift. Take, for example, any game with a skill tree. In some games, each skill node might have a large impact on how you play with the game, and qualify as a paradigm shift for some players. In other games, each skill node might just be a small percentage modifier on some stat that doesn't really impact much more than a slight bias towards an already established mechanic that's newly buffed. Every single canon game may show that it's common amongst incremental games, but could just as easily indicate that they're common in games in general.

High-Value Factors

I won't take as long to discuss the high and low-value factors, as you've already seen most of them brought up earlier on this page. As a reminder, a game does NOT need all of these to be an incremental game, but these are factors that each indicate a strong possibility the game is an incremental, so having several of these means they probably are. These factors apply to most of the canon incremental games.

"Pure UI" Display. Incrementals typically have a textual presentation of the game state - there isn't a visual representation of the entities within the game. The interface is closer to what would be just the UI of a game in another genre or the control panel of a plane. If there is a visual representation, the player is often still interacting with non-diegetic game elements.

Reduced Consequences. Incrementals tend to have reduced repurcussions for misplaying. They very rarely have fail states, where often the largest consequence is simply not progressing - never losing progress.

Optimization Problems. The predominant gameplay of incrementals is typically solving optimization problems, from deciding which purchase to save up for to reasoning and deciding between different mutually exclusive options the game presents.

Resource Management. Incrementals tend to have a lot of resources within the game to keep track of.

Low-Value Factors

These are low-value factors, meaning they aren't as strongly correlated with incremental games. Incremental games may have none of these, and non-incrementals may have several of these - if a game only has low-value factors, they're probably not an incremental.

Fast Numeric Growth. Numbers in incremental games tend to grow faster than in other genres. There are more instances of superlinear growth. The larger the numbers get, the stronger of a signal this factor is.

Automation. As an incremental game progresses, the player often no longer has to deal with earlier mechanics, by having them either happen automatically or otherwise be replaced with an alternative that requires less player interaction.

Goal-Oriented. Incrementals are often heavily reliant on extrinsic motivation to guide the player. Typically this is through some sort of in-game goal to work towards, such as a certain amount of a resource being required to unlock or purchase something new.

Waiting is a Mechanic. In incremental games, the player may come across times where there is no action they can take, and the game will progress automatically instead. The player must wait for some amount of this automatic progress to occur before they can resume interaction with the game.

Are Roguelites Incrementals?

Having made our variation of the Berlin Interpretation for incremental games, we can compare it to the Berlin Interpretation to determine if there's enough overlap that any game that "passes" the Berlin Interpretation would also pass the incremental variant. That is to say, whether any roguelite would also be considered an incremental game.

The meta-progression of an incremental game could arguably be considered a paradigm shift, and certainly adds some resource management. Goal-oriented would probably also apply. I think anything other than those would be a stretch, and in my opinion that just isn't enough to qualify. To be totally honest, I was never expecting to conclude otherwise though \u{1F609}

Sub-Genres

There are some trends in incremental games that go beyond just being a commonly used mechanic, such that they deeply affect the rest of the game design. These trends can be used to determine sub-genres within the incremental games umbrella:

  • Cultivation RPGs are a genre of games, books, and anime popular in China that center around being in a fantasy world with characters getting stronger over time. While few of them get translated into English, a fan of incremental games may find the available games interesting.
',60),o=[i];function s(l,h,m,c,g,d){return a(),t("div",null,o)}const f=e(n,[["render",s]]);export{p as __pageData,f as default}; +import{_ as e,c as t,o as a,a as r}from"./app.9bfeb8de.js";const p=JSON.parse('{"title":"Defining the Genre","description":"","frontmatter":{"title":"Defining the Genre"},"headers":[{"level":2,"title":"Incrementals vs Idlers vs Clickers","slug":"incrementals-vs-idlers-vs-clickers","link":"#incrementals-vs-idlers-vs-clickers","children":[]},{"level":2,"title":"Incrementals as Parodies","slug":"incrementals-as-parodies","link":"#incrementals-as-parodies","children":[]},{"level":2,"title":"Incrementals as NGU","slug":"incrementals-as-ngu","link":"#incrementals-as-ngu","children":[]},{"level":2,"title":"Incrementals as Strategies","slug":"incrementals-as-strategies","link":"#incrementals-as-strategies","children":[]},{"level":2,"title":"Roguelites as Incrementals?","slug":"roguelites-as-incrementals","link":"#roguelites-as-incrementals","children":[{"level":3,"title":"The Berlin Interpretation","slug":"the-berlin-interpretation","link":"#the-berlin-interpretation","children":[]},{"level":3,"title":"The Incremental Games Canon","slug":"the-incremental-games-canon","link":"#the-incremental-games-canon","children":[]},{"level":3,"title":"The Paradigm Shift","slug":"the-paradigm-shift","link":"#the-paradigm-shift","children":[]},{"level":3,"title":"High-Value Factors","slug":"high-value-factors","link":"#high-value-factors","children":[]},{"level":3,"title":"Low-Value Factors","slug":"low-value-factors","link":"#low-value-factors","children":[]},{"level":3,"title":"Are Roguelites Incrementals?","slug":"are-roguelites-incrementals","link":"#are-roguelites-incrementals","children":[]}]},{"level":2,"title":"Sub-Genres","slug":"sub-genres","link":"#sub-genres","children":[]},{"level":2,"title":"Other Related Genres","slug":"other-related-genres","link":"#other-related-genres","children":[]}],"relativePath":"guide-to-incrementals/ludology/definition.md","lastUpdated":null}'),n={name:"guide-to-incrementals/ludology/definition.md"},i=r('

Defining the Genre

Video games are placed into genres for a variety of reasons. They can give a mental shorthand to set the player's expectations up, they can help a game market itself by its similarities to other, already popular games, and honestly, people just love categorization for its own sake. For this guide, it's important to define the genre so it is clear what games it's even talking about.

This poses a problem. "Incremental" is a horribly vague way to define games. Most games have numbers going up in some form or another. We need a more specific definition - similar to how "strategy" can't just mean any game with any amount of strategy because that would be most games. What specifically differentiates incremental games from the rest?

"Incremental" implies it's a genre defined by a game mechanic, but all those game mechanics it could imply exist in many other games. Having a skill tree or upgrades doesn't make you incremental, and if a reset mechanic is all it takes then every roguelite would be an incremental as well. So clearly there's more to it than that - what makes an incremental an incremental?

I'd like to go over a couple of popular suggestions I've seen on defining the genre here. I have my personal preferences and will state them here, but I don't think there's a truly perfect answer here.

Disclaimer: I mostly play incremental games on my computer, and my definitions will be heavily biased towards the games I'm familiar with.

Incrementals vs Idlers vs Clickers

Oftentimes people refer to this genre as idle games and/or clicker games. You'll even find a trend of oxymoronic game titles that contain both terms. "Incremental games" is the umbrella term both those terms fall under. However, I'd like to argue that not only is it better to just use the term "incremental games", but calling them "idle games" or "clicker games" is wrong. Almost universally, these terms are used interchangeably to refer to the same kind of game, where you start the game click spamming and eventually automate the process. Frankly, that kind of game deserves neither title, and the incremental games genre has trended away from ever requiring click spamming, as it's a bad mechanic, anyways.

While these games do span a spectrum of how active it requires you to be, and sorting games by that metric can be useful for those looking for a particular experience, the borders of when an incremental game counts as an "idler" is too blurry for the term to be useful. "Incremental games" may not be a great descriptive term for the genre (hence this many thousands of words long page on defining what the genre even is), but it's strictly better than calling them "idler" or "clicker" games. This guide will always use the term "incremental games" unless quoting someone else, as it is the term you typically see on all modern games in the genre.

Incrementals as Parodies

Let's start with one of the most interesting definitions of incremental games. Incremental games appear to be distilled versions of games or genres, "revealing" the naked game design at the core of these games or genres not unlike how parodies comment upon their source material.

To understand what that means, think of how a casino uses skinner boxes to emotionally manipulate its customers to keep playing, but "dressing" up the skinner box with tons of stimuli to hide that ultimately the goal is to manipulate you to keep coming back. The idea that incremental games are parodies means taking the stance that at some level all games are similarly manipulating you, giving dopamine rewards in a way that manipulates you to keep playing while not necessarily giving you any value or fulfillment. Incremental games, then, are any games that plainly display the skinner box, and the manipulative core of the game, at the forefront of the experience.

This "undressing" tends to go hand in hand with a reduced focus on aesthetics, often just printing the game state directly to the screen as text. This makes incremental games much easier to develop, particularly for those with programming skills but not art skills, but that's a tangent for why Incremental Games appeal to Developers.

Before I continue, I'd like to make my stance clear that I love games and incremental games, and do not think they should be considered inherently bad or manipulative with the above logic. Skinner boxes are just a way of manipulating behavior via rewards. The games are still fun - that's the reward! I'd believe the real criticism here is that it is "empty fun", or "empty dopamine", that doesn't offer any additional value or sense of fulfillment. I don't think that's inherently bad in moderation, although it can become a problem if the game is manipulating you for profit-seeking, or if you play the game to the detriment of the other parts of your life. While incremental games can be fun and even healthy in certain contexts, they can exacerbate video game addiction moreso than other genres. If you feel like playing incremental games is taking priority over other things in your life, or manipulating your sleep schedule, it may be prudent to seek help. See r/StopGaming for resources.

Another interpretation of incremental games as parodies comes from several mainstream incremental games that are also parodies of capitalism, such as cookie clicker and adventure capitalist. It's a very common framework for incremental games to portray the ever-increasing numbers as an insatiable hunger for resources, like the ones observed within capitalism. Therefore, these games are used as evidence that the genre as a whole is about parody and commentary.

Popular videos on incremental games that portray the genre as parodies are Why Idle games make good satire, and how it was ruined. and Bad Game Design - Clicker Games. You may also be interested in this response to the latter video from a fan of incremental games: BadGood Game Design - Clicker Games.

I think that this definition ultimately ascribes a motive to the genre as a whole that only happens to apply to some of the more mainstream titles. There certainly are incremental games commenting on different things, including the genre itself as in the case of The Prestige Tree Classic, The Ascension Tree, or Omega Layers, but certainly not all. And of course, not all games that comment on something or parody something are incremental games! Additionally, a very large majority of incremental games are mobile games using these manipulative strategies to get players to spend as much money as possible - hell, Adventure Capitalist is ostensibly a critique on capitalism but features microtransactions and gameplay that manipulates you into buying them! These profit-seeking incremental games certainly belong within the genre but are hardly parodies when they too use manipulation to serve their interests. Also, from my own anecdotal experience, those who use this definition seem to do so from a fairly surface-level familiarity with the genre, and often in the context of criticizing the genre or the fans thereof.

Incrementals as NGU

Another broad definition often used is that incremental games are games where the focus of the game is "numbers going up". This definition proposes that other genres simply use increasing numbers as a means to an end, but incremental games uniquely only care about the numbers themselves going up. Put another way, it implies there should be no narrative justification for the numbers going up other than "why shouldn't they be going up?"

While this definition is common because it feels easy to understand, it is difficult to formally define. Often phrases are used to describe games using this framework, such as having an "exaggerated sense of progression" or "big" numbers. These terms are vague and don't demonstrate an actual threshold between non-incrementals and incrementals. Most games have a sense of progression, so when is it "exaggerated"? How big are "big" numbers? Most notably, RPGs that are typically not considered incrementals will often pass this definition.

Additionally, a lot of incrementals tend to have some theme guiding the gameplay, or at least the names of mechanics. This makes the line blurred between when numbers are going up for their own sake versus for a contextual reason. I believe this point is best illustrated that, while most RPGs are not considered incremental games, there is a sub-genre of "incremental RPGs" that typically relates to RPGs that perform combat automatically. This definition of incremental games does not support RPGs and "incremental RPGs" being on distinct sides of the line if the only difference between them is manual vs automatic combat.

Incrementals as Strategies

This is a rarer interpretation, but there are similarities between incremental games and strategy games, implying incrementals might just be a sub-genre of strategy games. By this approach, incremental games would be defined by their relation to strategy games, and how they involve player strategy. Incremental games are often large optimization problems - above all else, the actual gameplay the player is performing is deciding what to do next. The consequences of wrong decisions are typically more lenient in incremental games - such as just not making optimal progress - but they certainly get complex.

So if we accept the premise that incrementals could fall under strategy, we still need to define what makes a strategy game an incremental versus some other strategy sub-genre. This is a bit tricky due to one particular sub-genre of strategy games: Factory Builders.

Factory builders, such as Factorio or Satisfactory, are games about gaining ever increasing resources, optimizing production, and expanding more and more. That... sounds pretty similar, doesn't it? In fact, there's been some debate on whether factory builders would fall under the "incremental" umbrella. I think it's safe to say the two are certainly related, and probably have quite a bit of overlap in playerbase.

Roguelites as Incrementals?

Earlier on, I mentioned reset mechanics shouldn't be used in the definition because that could make all roguelites incrementals... But what if it does? A lot of incrementals can be described as games with a strong sense of progression, often with layers of meta-progression. Roguelites fit that bill to a T. What would make roguelites not incremental? I honestly don't think there's a good explanation here, but many fans of incremental games will state they do believe the two genres to be unrelated, even if there's a significant overlap between their player bases due to having similar appealing traits.

At this point, it'd be appropriate to consider what part of the definition of roguelites precludes them from also being incrementals, but that reveals a new problem: What are roguelites? They're usually defined as rogue_likes with meta-progression, but that just pushes the problem back a step: Incrementals aren't the only genre to have difficulties defining themselves, it seems! Roguelikes are another genre where the community argues over the formal definition of their genre, although that means we can borrow from their process of coming to a consensus, and maybe come across a viable definition for incremental games.

The Berlin Interpretation

By far the most popular way of defining roguelikes is the "Berlin Interpretation", which acknowledged the diversity of games within the genre and argued the definition should not be based on any ideals about what the genre ought to be, but rather defined by "its canon". They argued there are a handful of games that can be used to define the canon for roguelikes, and from those games, a list of factors can be derived to determine a game's "roguelikeness". The more factors a game has, the more of a roguelike it is. This strategy is very lenient, allowing a game to not present any specific factor so long as it shows enough, and accounts for the blurriness of any genre definition by not explicitly stating how many factors a game must have to qualify as a definite roguelike.

I believe this strategy for defining genres can be applied to other genres as well. A handful of games can be argued to be the incremental games canon, and a list of factors derived from them can be used to judge any game based on its "incrementalness". I'll propose such a canon and list of factors here, but by no means should it be considered the end-all-be-all.

Note: The "Temple of the roguelike", an authority within the genre, has since replaced the Berlin Interpretation with a new set of factors here: https://blog.roguetemple.com/what-is-a-traditional-roguelike/

The Incremental Games Canon

Alright, time to get controversial. Up til now, I've been trying my best to stay objective and analytical, but now it's time to start making some opinionated decisions. Here is a list of games I think could justifiably make up an Incremental Games Canon:

I chose a variety of games here, biasing towards newer games, purposefully to avoid making a narrow or "traditional" definition. The genre is growing and shouldn't be constrained by the traits of the early popular titles. A lot of these could easily be replaced with other games that are mechanically congruent, so ultimately I'm sure if you asked 10 people for their canon list you'd just get 10 different answers, but I think this should sufficiently allow us to determine what factors make a game have higher "incrementalness".

The Paradigm Shift

The Paradigm Shift is probably the highest possible value factor for an incremental. It's so common that for a while people referred to incrementals that exhibit this trait as "unfolding" games, to the point of trying to replace the term incremental due to their popularity. Paradigm shifts refer to when the gameplay significantly changes. There are too many examples to list here, but notably, every single reset mechanic is typically going to be a paradigm shift. Examples of games with paradigm shifts that aren't tied to reset mechanics include Universal Paperclips and A Dark Room.

There are many reasons for the appeal of paradigm shifts. Oftentimes each mechanic builds on top of the existing mechanics, increasing the complexity of the game in steps so the player can follow along. They provide a sense of mystery, with the player anticipating what will happen next. They shake up the gameplay before it gets too stale - allowing the game to entertain for longer before the illusion of content dissipates. Of the canon games selected above, I would argue every single one contains a paradigm shift (although I could see someone disagreeing with that statement wrt Increlution).

I should take a moment to say that while I'm hyping up this specific factor, we cannot just reduce the genre definition to "does it have paradigm shifts". Many games have paradigm shifts that are not incremental, so it's just an indicator of incrementalness. Additionally, it can become quite hard to determine how large of a shift is a "paradigm" shift. Take, for example, any game with a skill tree. In some games, each skill node might have a large impact on how you play with the game, and qualify as a paradigm shift for some players. In other games, each skill node might just be a small percentage modifier on some stat that doesn't really impact much more than a slight bias towards an already established mechanic that's newly buffed. Every single canon game may show that it's common amongst incremental games, but could just as easily indicate that they're common in games in general.

High-Value Factors

I won't take as long to discuss the high and low-value factors, as you've already seen most of them brought up earlier on this page. As a reminder, a game does NOT need all of these to be an incremental game, but these are factors that each indicate a strong possibility the game is an incremental, so having several of these means they probably are. These factors apply to most of the canon incremental games.

"Pure UI" Display. Incrementals typically have a textual presentation of the game state - there isn't a visual representation of the entities within the game. The interface is closer to what would be just the UI of a game in another genre or the control panel of a plane. If there is a visual representation, the player is often still interacting with non-diegetic game elements.

Reduced Consequences. Incrementals tend to have reduced repurcussions for misplaying. They very rarely have fail states, where often the largest consequence is simply not progressing - never losing progress.

Optimization Problems. The predominant gameplay of incrementals is typically solving optimization problems, from deciding which purchase to save up for to reasoning and deciding between different mutually exclusive options the game presents.

Resource Management. Incrementals tend to have a lot of resources within the game to keep track of.

Low-Value Factors

These are low-value factors, meaning they aren't as strongly correlated with incremental games. Incremental games may have none of these, and non-incrementals may have several of these - if a game only has low-value factors, they're probably not an incremental.

Fast Numeric Growth. Numbers in incremental games tend to grow faster than in other genres. There are more instances of superlinear growth. The larger the numbers get, the stronger of a signal this factor is.

Automation. As an incremental game progresses, the player often no longer has to deal with earlier mechanics, by having them either happen automatically or otherwise be replaced with an alternative that requires less player interaction.

Goal-Oriented. Incrementals are often heavily reliant on extrinsic motivation to guide the player. Typically this is through some sort of in-game goal to work towards, such as a certain amount of a resource being required to unlock or purchase something new.

Waiting is a Mechanic. In incremental games, the player may come across times where there is no action they can take, and the game will progress automatically instead. The player must wait for some amount of this automatic progress to occur before they can resume interaction with the game.

Are Roguelites Incrementals?

Having made our variation of the Berlin Interpretation for incremental games, we can compare it to the Berlin Interpretation to determine if there's enough overlap that any game that "passes" the Berlin Interpretation would also pass the incremental variant. That is to say, whether any roguelite would also be considered an incremental game.

The meta-progression of an incremental game could arguably be considered a paradigm shift, and certainly adds some resource management. Goal-oriented would probably also apply. I think anything other than those would be a stretch, and in my opinion that just isn't enough to qualify. To be totally honest, I was never expecting to conclude otherwise though \u{1F609}

Sub-Genres

There are some trends in incremental games that go beyond just being a commonly used mechanic, such that they deeply affect the rest of the game design. These trends can be used to determine sub-genres within the incremental games umbrella:

  • Cultivation RPGs are a genre of games, books, and anime popular in China that center around being in a fantasy world with characters getting stronger over time. While few of them get translated into English, a fan of incremental games may find the available games interesting.
',60),o=[i];function s(l,h,m,c,g,d){return a(),t("div",null,o)}const f=e(n,[["render",s]]);export{p as __pageData,f as default}; diff --git a/assets/guide-to-incrementals_ludology_definition.md.cdcec89a.lean.js b/assets/guide-to-incrementals_ludology_definition.md.effc1cd4.lean.js similarity index 96% rename from assets/guide-to-incrementals_ludology_definition.md.cdcec89a.lean.js rename to assets/guide-to-incrementals_ludology_definition.md.effc1cd4.lean.js index 1becad212..af3384f89 100644 --- a/assets/guide-to-incrementals_ludology_definition.md.cdcec89a.lean.js +++ b/assets/guide-to-incrementals_ludology_definition.md.effc1cd4.lean.js @@ -1 +1 @@ -import{_ as e,c as t,o as a,a as r}from"./app.a576d425.js";const p=JSON.parse('{"title":"Defining the Genre","description":"","frontmatter":{"title":"Defining the Genre"},"headers":[{"level":2,"title":"Incrementals vs Idlers vs Clickers","slug":"incrementals-vs-idlers-vs-clickers","link":"#incrementals-vs-idlers-vs-clickers","children":[]},{"level":2,"title":"Incrementals as Parodies","slug":"incrementals-as-parodies","link":"#incrementals-as-parodies","children":[]},{"level":2,"title":"Incrementals as NGU","slug":"incrementals-as-ngu","link":"#incrementals-as-ngu","children":[]},{"level":2,"title":"Incrementals as Strategies","slug":"incrementals-as-strategies","link":"#incrementals-as-strategies","children":[]},{"level":2,"title":"Roguelites as Incrementals?","slug":"roguelites-as-incrementals","link":"#roguelites-as-incrementals","children":[{"level":3,"title":"The Berlin Interpretation","slug":"the-berlin-interpretation","link":"#the-berlin-interpretation","children":[]},{"level":3,"title":"The Incremental Games Canon","slug":"the-incremental-games-canon","link":"#the-incremental-games-canon","children":[]},{"level":3,"title":"The Paradigm Shift","slug":"the-paradigm-shift","link":"#the-paradigm-shift","children":[]},{"level":3,"title":"High-Value Factors","slug":"high-value-factors","link":"#high-value-factors","children":[]},{"level":3,"title":"Low-Value Factors","slug":"low-value-factors","link":"#low-value-factors","children":[]},{"level":3,"title":"Are Roguelites Incrementals?","slug":"are-roguelites-incrementals","link":"#are-roguelites-incrementals","children":[]}]},{"level":2,"title":"Sub-Genres","slug":"sub-genres","link":"#sub-genres","children":[]},{"level":2,"title":"Other Related Genres","slug":"other-related-genres","link":"#other-related-genres","children":[]}],"relativePath":"guide-to-incrementals/ludology/definition.md","lastUpdated":null}'),n={name:"guide-to-incrementals/ludology/definition.md"},i=r("",60),o=[i];function s(l,h,m,c,g,d){return a(),t("div",null,o)}const f=e(n,[["render",s]]);export{p as __pageData,f as default}; +import{_ as e,c as t,o as a,a as r}from"./app.9bfeb8de.js";const p=JSON.parse('{"title":"Defining the Genre","description":"","frontmatter":{"title":"Defining the Genre"},"headers":[{"level":2,"title":"Incrementals vs Idlers vs Clickers","slug":"incrementals-vs-idlers-vs-clickers","link":"#incrementals-vs-idlers-vs-clickers","children":[]},{"level":2,"title":"Incrementals as Parodies","slug":"incrementals-as-parodies","link":"#incrementals-as-parodies","children":[]},{"level":2,"title":"Incrementals as NGU","slug":"incrementals-as-ngu","link":"#incrementals-as-ngu","children":[]},{"level":2,"title":"Incrementals as Strategies","slug":"incrementals-as-strategies","link":"#incrementals-as-strategies","children":[]},{"level":2,"title":"Roguelites as Incrementals?","slug":"roguelites-as-incrementals","link":"#roguelites-as-incrementals","children":[{"level":3,"title":"The Berlin Interpretation","slug":"the-berlin-interpretation","link":"#the-berlin-interpretation","children":[]},{"level":3,"title":"The Incremental Games Canon","slug":"the-incremental-games-canon","link":"#the-incremental-games-canon","children":[]},{"level":3,"title":"The Paradigm Shift","slug":"the-paradigm-shift","link":"#the-paradigm-shift","children":[]},{"level":3,"title":"High-Value Factors","slug":"high-value-factors","link":"#high-value-factors","children":[]},{"level":3,"title":"Low-Value Factors","slug":"low-value-factors","link":"#low-value-factors","children":[]},{"level":3,"title":"Are Roguelites Incrementals?","slug":"are-roguelites-incrementals","link":"#are-roguelites-incrementals","children":[]}]},{"level":2,"title":"Sub-Genres","slug":"sub-genres","link":"#sub-genres","children":[]},{"level":2,"title":"Other Related Genres","slug":"other-related-genres","link":"#other-related-genres","children":[]}],"relativePath":"guide-to-incrementals/ludology/definition.md","lastUpdated":null}'),n={name:"guide-to-incrementals/ludology/definition.md"},i=r("",60),o=[i];function s(l,h,m,c,g,d){return a(),t("div",null,o)}const f=e(n,[["render",s]]);export{p as __pageData,f as default}; diff --git a/assets/index.md.fdd76977.js b/assets/index.md.c05fb4a0.js similarity index 76% rename from assets/index.md.fdd76977.js rename to assets/index.md.c05fb4a0.js index e08029479..577ea8c6b 100644 --- a/assets/index.md.fdd76977.js +++ b/assets/index.md.c05fb4a0.js @@ -1 +1 @@ -import{_ as e,c as t,o as a}from"./app.a576d425.js";const m=JSON.parse(`{"title":"The Paper Pilot","description":"","frontmatter":{"title":"The Paper Pilot","layout":"home","hero":{"name":"The Paper Pilot","tagline":"I'm Anthony, or The Paper Pilot, and I make fun games and tools!","actions":[{"theme":"brand","text":"My Projects","link":"/projects/"}]}},"headers":[],"relativePath":"index.md","lastUpdated":1664944072000}`),o={name:"index.md"};function n(r,s,i,c,d,p){return a(),t("div")}const h=e(o,[["render",n]]);export{m as __pageData,h as default}; +import{_ as e,c as t,o as a}from"./app.9bfeb8de.js";const m=JSON.parse(`{"title":"The Paper Pilot","description":"","frontmatter":{"title":"The Paper Pilot","layout":"home","hero":{"name":"The Paper Pilot","tagline":"I'm Anthony, or The Paper Pilot, and I make fun games and tools!","actions":[{"theme":"brand","text":"My Projects","link":"/projects/"}]}},"headers":[],"relativePath":"index.md","lastUpdated":1664944600000}`),o={name:"index.md"};function n(r,s,i,c,d,p){return a(),t("div")}const h=e(o,[["render",n]]);export{m as __pageData,h as default}; diff --git a/assets/index.md.fdd76977.lean.js b/assets/index.md.c05fb4a0.lean.js similarity index 76% rename from assets/index.md.fdd76977.lean.js rename to assets/index.md.c05fb4a0.lean.js index e08029479..577ea8c6b 100644 --- a/assets/index.md.fdd76977.lean.js +++ b/assets/index.md.c05fb4a0.lean.js @@ -1 +1 @@ -import{_ as e,c as t,o as a}from"./app.a576d425.js";const m=JSON.parse(`{"title":"The Paper Pilot","description":"","frontmatter":{"title":"The Paper Pilot","layout":"home","hero":{"name":"The Paper Pilot","tagline":"I'm Anthony, or The Paper Pilot, and I make fun games and tools!","actions":[{"theme":"brand","text":"My Projects","link":"/projects/"}]}},"headers":[],"relativePath":"index.md","lastUpdated":1664944072000}`),o={name:"index.md"};function n(r,s,i,c,d,p){return a(),t("div")}const h=e(o,[["render",n]]);export{m as __pageData,h as default}; +import{_ as e,c as t,o as a}from"./app.9bfeb8de.js";const m=JSON.parse(`{"title":"The Paper Pilot","description":"","frontmatter":{"title":"The Paper Pilot","layout":"home","hero":{"name":"The Paper Pilot","tagline":"I'm Anthony, or The Paper Pilot, and I make fun games and tools!","actions":[{"theme":"brand","text":"My Projects","link":"/projects/"}]}},"headers":[],"relativePath":"index.md","lastUpdated":1664944600000}`),o={name:"index.md"};function n(r,s,i,c,d,p){return a(),t("div")}const h=e(o,[["render",n]]);export{m as __pageData,h as default}; diff --git a/assets/projects_babble_index.md.75ea61ee.js b/assets/projects_babble_index.md.db4edec9.js similarity index 96% rename from assets/projects_babble_index.md.75ea61ee.js rename to assets/projects_babble_index.md.db4edec9.js index 7ad27d770..6250d061f 100644 --- a/assets/projects_babble_index.md.75ea61ee.js +++ b/assets/projects_babble_index.md.db4edec9.js @@ -1 +1 @@ -import{_ as e,c as a,o as t,a as r}from"./app.a576d425.js";const s="/assets/screenshot.3bf794a2.png",o="/assets/babblemmscreenshot.7646b6c2.png",g=JSON.parse('{"title":"Babble Buds","description":"","frontmatter":{"title":"Babble Buds"},"headers":[{"level":2,"title":"Engine","slug":"engine","link":"#engine","children":[]},{"level":2,"title":"Babble Movie Maker","slug":"babble-movie-maker","link":"#babble-movie-maker","children":[]}],"relativePath":"projects/babble/index.md","lastUpdated":1664944072000}'),n={name:"projects/babble/index.md"},i=r('

Babble Buds

Babble Buds Homepage

Source Code:

Babble buds is a free, open-source virtual puppet show software. It is heavily based on the non-public software called "Puppet Pals", used in URealms Live. The software is written in javascript using React, a rendering library called PIXI.js, and electron.

Users can create puppets with different faces for different emotions, and then use the puppet on a stage where you and other users can each make your respective puppets move, change emotions, and "babble" at each other. The stage has a green screen feature and can be popped out, which gives the users tons of possibilities in terms of using the program for a role-playing live stream, faux video chatting with friends, game development, or whatever else you want!

Users can connect to the public server and create private rooms so that they and their friends can see each other's puppets and use the software however they please. For the security conscious, you can also use the server's source code to self-host your private server.

Babble Buds Screenshot

Engine

The engine originally made to make the Babble Buds program was separated into a separate engine called babble.js, so that projects created in Babble Buds can be used in other projects. For example, a game can create puppets in Babble Buds and then use them for cutscenes or player agency inside of the game. Additionally, it has been ported to C# (called babble.cs) for use with Unity, for the same kinds of purposes. You can check out Tower Offense for a pixi.js game using Babble Buds puppets for the cutscenes, or Dice Armor for a unity game using Babble Buds puppets for the cutscenes.

Babble Movie Maker

Babble Movie Maker is a cutscene editor for Babble Buds puppets. You open a babble buds project in it, and you can add actors to a stage and have them move and change expressions, etc., on a timeline. You can then use the cutscene in a game using babble.js or babble.cs, or export the cutscene into a video file. There is even support for defining custom commands with custom fields, so that if you've expanded upon the default actions provided in babble.js or babble.cs, you can still use Movie Maker to create your cutscenes.

Babble MM Screenshot

',13),b=[i];function c(l,p,d,h,u,f){return t(),a("div",null,b)}const v=e(n,[["render",c]]);export{g as __pageData,v as default}; +import{_ as e,c as a,o as t,a as r}from"./app.9bfeb8de.js";const s="/assets/screenshot.3bf794a2.png",o="/assets/babblemmscreenshot.7646b6c2.png",g=JSON.parse('{"title":"Babble Buds","description":"","frontmatter":{"title":"Babble Buds"},"headers":[{"level":2,"title":"Engine","slug":"engine","link":"#engine","children":[]},{"level":2,"title":"Babble Movie Maker","slug":"babble-movie-maker","link":"#babble-movie-maker","children":[]}],"relativePath":"projects/babble/index.md","lastUpdated":1664944600000}'),n={name:"projects/babble/index.md"},i=r('

Babble Buds

Babble Buds Homepage

Source Code:

Babble buds is a free, open-source virtual puppet show software. It is heavily based on the non-public software called "Puppet Pals", used in URealms Live. The software is written in javascript using React, a rendering library called PIXI.js, and electron.

Users can create puppets with different faces for different emotions, and then use the puppet on a stage where you and other users can each make your respective puppets move, change emotions, and "babble" at each other. The stage has a green screen feature and can be popped out, which gives the users tons of possibilities in terms of using the program for a role-playing live stream, faux video chatting with friends, game development, or whatever else you want!

Users can connect to the public server and create private rooms so that they and their friends can see each other's puppets and use the software however they please. For the security conscious, you can also use the server's source code to self-host your private server.

Babble Buds Screenshot

Engine

The engine originally made to make the Babble Buds program was separated into a separate engine called babble.js, so that projects created in Babble Buds can be used in other projects. For example, a game can create puppets in Babble Buds and then use them for cutscenes or player agency inside of the game. Additionally, it has been ported to C# (called babble.cs) for use with Unity, for the same kinds of purposes. You can check out Tower Offense for a pixi.js game using Babble Buds puppets for the cutscenes, or Dice Armor for a unity game using Babble Buds puppets for the cutscenes.

Babble Movie Maker

Babble Movie Maker is a cutscene editor for Babble Buds puppets. You open a babble buds project in it, and you can add actors to a stage and have them move and change expressions, etc., on a timeline. You can then use the cutscene in a game using babble.js or babble.cs, or export the cutscene into a video file. There is even support for defining custom commands with custom fields, so that if you've expanded upon the default actions provided in babble.js or babble.cs, you can still use Movie Maker to create your cutscenes.

Babble MM Screenshot

',13),b=[i];function c(l,p,d,h,u,f){return t(),a("div",null,b)}const v=e(n,[["render",c]]);export{g as __pageData,v as default}; diff --git a/assets/projects_babble_index.md.75ea61ee.lean.js b/assets/projects_babble_index.md.db4edec9.lean.js similarity index 81% rename from assets/projects_babble_index.md.75ea61ee.lean.js rename to assets/projects_babble_index.md.db4edec9.lean.js index cd0e9c0e0..da066b6f2 100644 --- a/assets/projects_babble_index.md.75ea61ee.lean.js +++ b/assets/projects_babble_index.md.db4edec9.lean.js @@ -1 +1 @@ -import{_ as e,c as a,o as t,a as r}from"./app.a576d425.js";const s="/assets/screenshot.3bf794a2.png",o="/assets/babblemmscreenshot.7646b6c2.png",g=JSON.parse('{"title":"Babble Buds","description":"","frontmatter":{"title":"Babble Buds"},"headers":[{"level":2,"title":"Engine","slug":"engine","link":"#engine","children":[]},{"level":2,"title":"Babble Movie Maker","slug":"babble-movie-maker","link":"#babble-movie-maker","children":[]}],"relativePath":"projects/babble/index.md","lastUpdated":1664944072000}'),n={name:"projects/babble/index.md"},i=r("",13),b=[i];function c(l,p,d,h,u,f){return t(),a("div",null,b)}const v=e(n,[["render",c]]);export{g as __pageData,v as default}; +import{_ as e,c as a,o as t,a as r}from"./app.9bfeb8de.js";const s="/assets/screenshot.3bf794a2.png",o="/assets/babblemmscreenshot.7646b6c2.png",g=JSON.parse('{"title":"Babble Buds","description":"","frontmatter":{"title":"Babble Buds"},"headers":[{"level":2,"title":"Engine","slug":"engine","link":"#engine","children":[]},{"level":2,"title":"Babble Movie Maker","slug":"babble-movie-maker","link":"#babble-movie-maker","children":[]}],"relativePath":"projects/babble/index.md","lastUpdated":1664944600000}'),n={name:"projects/babble/index.md"},i=r("",13),b=[i];function c(l,p,d,h,u,f){return t(),a("div",null,b)}const v=e(n,[["render",c]]);export{g as __pageData,v as default}; diff --git a/assets/projects_citadel_index.md.aa08898c.js b/assets/projects_citadel_index.md.ce7d0618.js similarity index 87% rename from assets/projects_citadel_index.md.aa08898c.js rename to assets/projects_citadel_index.md.ce7d0618.js index c79bed183..67cd1ff4b 100644 --- a/assets/projects_citadel_index.md.aa08898c.js +++ b/assets/projects_citadel_index.md.ce7d0618.js @@ -1 +1 @@ -import{_ as a,c as r,o as s,b as e,d as t}from"./app.a576d425.js";const n="/assets/screenshot.f2631300.png",C=JSON.parse('{"title":"Capture the Citadel","description":"","frontmatter":{"title":"Capture the Citadel"},"headers":[],"relativePath":"projects/citadel/index.md","lastUpdated":1664944072000}'),o={name:"projects/citadel/index.md"},i=e("h1",{id:"capture-the-citadel",tabindex:"-1"},[t("Capture the Citadel "),e("a",{class:"header-anchor",href:"#capture-the-citadel","aria-hidden":"true"},"#")],-1),c=e("p",null,"A 3D VR re-envisioning of a Slay the Spire-style game by Anthony Lawn and Grant Barbee for their VR class in college's final project.",-1),d=e("p",null,[t("For more details, visit "),e("a",{href:"https://grantcbarbee.github.io/conquer-the-citadel.html",target:"_blank",rel:"noreferrer"},"Grant's page on the game"),t(".")],-1),l=e("p",null,[e("img",{src:n,alt:"Screenshot"})],-1),h=[i,c,d,l];function p(_,u,f,m,g,b){return s(),r("div",null,h)}const v=a(o,[["render",p]]);export{C as __pageData,v as default}; +import{_ as a,c as r,o as s,b as e,d as t}from"./app.9bfeb8de.js";const n="/assets/screenshot.f2631300.png",C=JSON.parse('{"title":"Capture the Citadel","description":"","frontmatter":{"title":"Capture the Citadel"},"headers":[],"relativePath":"projects/citadel/index.md","lastUpdated":1664944600000}'),o={name:"projects/citadel/index.md"},i=e("h1",{id:"capture-the-citadel",tabindex:"-1"},[t("Capture the Citadel "),e("a",{class:"header-anchor",href:"#capture-the-citadel","aria-hidden":"true"},"#")],-1),c=e("p",null,"A 3D VR re-envisioning of a Slay the Spire-style game by Anthony Lawn and Grant Barbee for their VR class in college's final project.",-1),d=e("p",null,[t("For more details, visit "),e("a",{href:"https://grantcbarbee.github.io/conquer-the-citadel.html",target:"_blank",rel:"noreferrer"},"Grant's page on the game"),t(".")],-1),l=e("p",null,[e("img",{src:n,alt:"Screenshot"})],-1),h=[i,c,d,l];function p(_,u,f,m,g,b){return s(),r("div",null,h)}const v=a(o,[["render",p]]);export{C as __pageData,v as default}; diff --git a/assets/projects_citadel_index.md.aa08898c.lean.js b/assets/projects_citadel_index.md.ce7d0618.lean.js similarity index 87% rename from assets/projects_citadel_index.md.aa08898c.lean.js rename to assets/projects_citadel_index.md.ce7d0618.lean.js index c79bed183..67cd1ff4b 100644 --- a/assets/projects_citadel_index.md.aa08898c.lean.js +++ b/assets/projects_citadel_index.md.ce7d0618.lean.js @@ -1 +1 @@ -import{_ as a,c as r,o as s,b as e,d as t}from"./app.a576d425.js";const n="/assets/screenshot.f2631300.png",C=JSON.parse('{"title":"Capture the Citadel","description":"","frontmatter":{"title":"Capture the Citadel"},"headers":[],"relativePath":"projects/citadel/index.md","lastUpdated":1664944072000}'),o={name:"projects/citadel/index.md"},i=e("h1",{id:"capture-the-citadel",tabindex:"-1"},[t("Capture the Citadel "),e("a",{class:"header-anchor",href:"#capture-the-citadel","aria-hidden":"true"},"#")],-1),c=e("p",null,"A 3D VR re-envisioning of a Slay the Spire-style game by Anthony Lawn and Grant Barbee for their VR class in college's final project.",-1),d=e("p",null,[t("For more details, visit "),e("a",{href:"https://grantcbarbee.github.io/conquer-the-citadel.html",target:"_blank",rel:"noreferrer"},"Grant's page on the game"),t(".")],-1),l=e("p",null,[e("img",{src:n,alt:"Screenshot"})],-1),h=[i,c,d,l];function p(_,u,f,m,g,b){return s(),r("div",null,h)}const v=a(o,[["render",p]]);export{C as __pageData,v as default}; +import{_ as a,c as r,o as s,b as e,d as t}from"./app.9bfeb8de.js";const n="/assets/screenshot.f2631300.png",C=JSON.parse('{"title":"Capture the Citadel","description":"","frontmatter":{"title":"Capture the Citadel"},"headers":[],"relativePath":"projects/citadel/index.md","lastUpdated":1664944600000}'),o={name:"projects/citadel/index.md"},i=e("h1",{id:"capture-the-citadel",tabindex:"-1"},[t("Capture the Citadel "),e("a",{class:"header-anchor",href:"#capture-the-citadel","aria-hidden":"true"},"#")],-1),c=e("p",null,"A 3D VR re-envisioning of a Slay the Spire-style game by Anthony Lawn and Grant Barbee for their VR class in college's final project.",-1),d=e("p",null,[t("For more details, visit "),e("a",{href:"https://grantcbarbee.github.io/conquer-the-citadel.html",target:"_blank",rel:"noreferrer"},"Grant's page on the game"),t(".")],-1),l=e("p",null,[e("img",{src:n,alt:"Screenshot"})],-1),h=[i,c,d,l];function p(_,u,f,m,g,b){return s(),r("div",null,h)}const v=a(o,[["render",p]]);export{C as __pageData,v as default}; diff --git a/assets/projects_dice_index.md.5311cd9a.js b/assets/projects_dice_index.md.c23997d0.js similarity index 98% rename from assets/projects_dice_index.md.5311cd9a.js rename to assets/projects_dice_index.md.c23997d0.js index 793bf2bab..6c57fa620 100644 --- a/assets/projects_dice_index.md.5311cd9a.js +++ b/assets/projects_dice_index.md.c23997d0.js @@ -1 +1 @@ -import{_ as e,c as t,o as a,a as i}from"./app.a576d425.js";const o="/assets/da2.57c7af0b.png",s="/assets/editors.c2eaa93b.png",n="/assets/simulator.7ede7b83.jpg",r="/assets/da1.ae7a2bb1.png",h="/assets/da6.5b5d63de.png",d="/assets/da7.b7b33663.png",l="/assets/da8.d623c64f.png",c="/assets/da3.e16fb4de.png",p="/assets/da9.35a2db61.png",I=JSON.parse('{"title":"Dice Armor","description":"","frontmatter":{"title":"Dice Armor"},"headers":[],"relativePath":"projects/dice/index.md","lastUpdated":1664944072000}'),g={name:"projects/dice/index.md"},m=i('

Dice Armor

Download Here

Dice Armor is a game that started development as a semester-long project by a team of nine: a producer, a creative director, a narrative writer, an artist, two programmers, and 3 game designers. The information here is about my contributions as the lead programmer over the semester because I can show off stuff like the editor scripts I wrote. I was doing everything from interface coding, editor scripts, integrating Babble Buds, and of course, everything related to the gameplay itself. To date I'm still the lead programmer for the game; for more up-to-date information on the current state of the game please visit the official site.

The build available here was created for showing off at the end of the semester, and as such has some buttons present to make the game easier to skip parts of the game to see all the content: You start with all the dice in the game already in the shop, there's a button to give yourself free money to buy these dice with, and in the duel, there are buttons to force a win or a loss, which can be used to skip the tutorial (not recommended for first-time players).

Tutorial

Dice Armor is a dice dueling game. Players can use abilities, flip dice, and attack each other to win in a dice game that puts chance into the hands of the players. This is what the dueling scene looks like, with a tutorial cutscene happening on top to guide the player through the basics. Also, all the dice are constructed dynamically, using quaternion math to figure out the placement of each component relative to the face it is going on. The die in the middle has one of the player' and opponents' portraits on each of its sides.

Editors

For many of the objects I've created, I've made scriptable objects so that game designers can add and modify them easily. Additionally, I would create custom inspectors for the objects to help make them as easy to understand and edit as possible. The opponent's artificial intelligence is made up of many strategies, in a prioritized list. When it is the opponents' turn they go through each strategy and check if they can be run, and if so then the opponent performs the strategy and starts back over at the top of the list of strategies. The + sign under the list of strategies opens an organized dropdown of all the various strategies.

Simulator

In addition to custom inspector code, I've created new tools for the editor for our game designers to use. This is a duel simulator that will take two opponents and simulate an arbitrary number of duels between them, and output the results and summarize them for you, much much quicker than manually going through the duels, even with an absurdly high timeScale. This will become incredibly useful in making balance changes and testing new dice against existing sets. This is a screenshot of it in edit mode, but in play mode it removes the "Dueling Managers" field and will use whatever the current duel balance settings are, allowing for the GDs to test freely in play mode without worrying about undoing all their changes afterward.

Cutscene

I created the Babble Buds puppet editor and ported the rendering library I wrote for it to C# so it could be used in Unity. Dice Armor has a full campaign using cutscenes made using the Babble Buds cutscene editor, taking advantage of its support for custom commands and fields to control things like talking, giving the player dice and money, starting duels, and controlling player progression through the story.

Action Wheel

When a cutscene ends, its final command is to either start a duel or set the next cutscene in the story. In the latter case, there is an additional field for what to call the next cutscene, and what location it takes place. The cutscene is then added to the player's save file, and when they visit the city locations are greyed out until they have at least one action to do there. Each location has a dynamically populated action wheel with a custom range of acceptable angles.

Shop

The dice shop is dynamically populated by a list of dice available to the player, which can be changed during cutscenes, and is checked against the dice owned by the player to generate sold-out indicators. On the left, the player can choose to filter the options down to a single dice effect, which also updates the "Buy All" button to buy only all the dice in the current filter.

Inventory

The inventory works most the same as the shop, but for equipping dice. It also allows you to drag individual dice or entire sets to the equipped dice glyph. While dragging it will highlight all the slots the new dice will be equipped into.

Dice Rolling

The dice rolling uses the physics engine and detects once the dice have stopped moving, then determines which side is face up based on which of the normals is closest to straight up. It flags the die as cocked if that smallest angle is above a threshold. The dice sink into the table when not rolling to not interfere with any dice that are rolling.

Missile Storm

During certain events like winning the game or having the face of a die broken, the players' portraits will flash an emotion for a second. After winning, a random living die from the winning player is chosen to play their "finisher move", a flashy and dramatic effect to end the game. Shown is the arcane mechana's finisher, "Missile Storm".

',22),u=[m];function f(y,b,w,_,v,k){return a(),t("div",null,u)}const q=e(g,[["render",f]]);export{I as __pageData,q as default}; +import{_ as e,c as t,o as a,a as i}from"./app.9bfeb8de.js";const o="/assets/da2.57c7af0b.png",s="/assets/editors.c2eaa93b.png",n="/assets/simulator.7ede7b83.jpg",r="/assets/da1.ae7a2bb1.png",h="/assets/da6.5b5d63de.png",d="/assets/da7.b7b33663.png",l="/assets/da8.d623c64f.png",c="/assets/da3.e16fb4de.png",p="/assets/da9.35a2db61.png",I=JSON.parse('{"title":"Dice Armor","description":"","frontmatter":{"title":"Dice Armor"},"headers":[],"relativePath":"projects/dice/index.md","lastUpdated":1664944600000}'),g={name:"projects/dice/index.md"},m=i('

Dice Armor

Download Here

Dice Armor is a game that started development as a semester-long project by a team of nine: a producer, a creative director, a narrative writer, an artist, two programmers, and 3 game designers. The information here is about my contributions as the lead programmer over the semester because I can show off stuff like the editor scripts I wrote. I was doing everything from interface coding, editor scripts, integrating Babble Buds, and of course, everything related to the gameplay itself. To date I'm still the lead programmer for the game; for more up-to-date information on the current state of the game please visit the official site.

The build available here was created for showing off at the end of the semester, and as such has some buttons present to make the game easier to skip parts of the game to see all the content: You start with all the dice in the game already in the shop, there's a button to give yourself free money to buy these dice with, and in the duel, there are buttons to force a win or a loss, which can be used to skip the tutorial (not recommended for first-time players).

Tutorial

Dice Armor is a dice dueling game. Players can use abilities, flip dice, and attack each other to win in a dice game that puts chance into the hands of the players. This is what the dueling scene looks like, with a tutorial cutscene happening on top to guide the player through the basics. Also, all the dice are constructed dynamically, using quaternion math to figure out the placement of each component relative to the face it is going on. The die in the middle has one of the player' and opponents' portraits on each of its sides.

Editors

For many of the objects I've created, I've made scriptable objects so that game designers can add and modify them easily. Additionally, I would create custom inspectors for the objects to help make them as easy to understand and edit as possible. The opponent's artificial intelligence is made up of many strategies, in a prioritized list. When it is the opponents' turn they go through each strategy and check if they can be run, and if so then the opponent performs the strategy and starts back over at the top of the list of strategies. The + sign under the list of strategies opens an organized dropdown of all the various strategies.

Simulator

In addition to custom inspector code, I've created new tools for the editor for our game designers to use. This is a duel simulator that will take two opponents and simulate an arbitrary number of duels between them, and output the results and summarize them for you, much much quicker than manually going through the duels, even with an absurdly high timeScale. This will become incredibly useful in making balance changes and testing new dice against existing sets. This is a screenshot of it in edit mode, but in play mode it removes the "Dueling Managers" field and will use whatever the current duel balance settings are, allowing for the GDs to test freely in play mode without worrying about undoing all their changes afterward.

Cutscene

I created the Babble Buds puppet editor and ported the rendering library I wrote for it to C# so it could be used in Unity. Dice Armor has a full campaign using cutscenes made using the Babble Buds cutscene editor, taking advantage of its support for custom commands and fields to control things like talking, giving the player dice and money, starting duels, and controlling player progression through the story.

Action Wheel

When a cutscene ends, its final command is to either start a duel or set the next cutscene in the story. In the latter case, there is an additional field for what to call the next cutscene, and what location it takes place. The cutscene is then added to the player's save file, and when they visit the city locations are greyed out until they have at least one action to do there. Each location has a dynamically populated action wheel with a custom range of acceptable angles.

Shop

The dice shop is dynamically populated by a list of dice available to the player, which can be changed during cutscenes, and is checked against the dice owned by the player to generate sold-out indicators. On the left, the player can choose to filter the options down to a single dice effect, which also updates the "Buy All" button to buy only all the dice in the current filter.

Inventory

The inventory works most the same as the shop, but for equipping dice. It also allows you to drag individual dice or entire sets to the equipped dice glyph. While dragging it will highlight all the slots the new dice will be equipped into.

Dice Rolling

The dice rolling uses the physics engine and detects once the dice have stopped moving, then determines which side is face up based on which of the normals is closest to straight up. It flags the die as cocked if that smallest angle is above a threshold. The dice sink into the table when not rolling to not interfere with any dice that are rolling.

Missile Storm

During certain events like winning the game or having the face of a die broken, the players' portraits will flash an emotion for a second. After winning, a random living die from the winning player is chosen to play their "finisher move", a flashy and dramatic effect to end the game. Shown is the arcane mechana's finisher, "Missile Storm".

',22),u=[m];function f(y,b,w,_,v,k){return a(),t("div",null,u)}const q=e(g,[["render",f]]);export{I as __pageData,q as default}; diff --git a/assets/projects_dice_index.md.5311cd9a.lean.js b/assets/projects_dice_index.md.c23997d0.lean.js similarity index 81% rename from assets/projects_dice_index.md.5311cd9a.lean.js rename to assets/projects_dice_index.md.c23997d0.lean.js index 1ce8ae1fd..5d8bcff1e 100644 --- a/assets/projects_dice_index.md.5311cd9a.lean.js +++ b/assets/projects_dice_index.md.c23997d0.lean.js @@ -1 +1 @@ -import{_ as e,c as t,o as a,a as i}from"./app.a576d425.js";const o="/assets/da2.57c7af0b.png",s="/assets/editors.c2eaa93b.png",n="/assets/simulator.7ede7b83.jpg",r="/assets/da1.ae7a2bb1.png",h="/assets/da6.5b5d63de.png",d="/assets/da7.b7b33663.png",l="/assets/da8.d623c64f.png",c="/assets/da3.e16fb4de.png",p="/assets/da9.35a2db61.png",I=JSON.parse('{"title":"Dice Armor","description":"","frontmatter":{"title":"Dice Armor"},"headers":[],"relativePath":"projects/dice/index.md","lastUpdated":1664944072000}'),g={name:"projects/dice/index.md"},m=i("",22),u=[m];function f(y,b,w,_,v,k){return a(),t("div",null,u)}const q=e(g,[["render",f]]);export{I as __pageData,q as default}; +import{_ as e,c as t,o as a,a as i}from"./app.9bfeb8de.js";const o="/assets/da2.57c7af0b.png",s="/assets/editors.c2eaa93b.png",n="/assets/simulator.7ede7b83.jpg",r="/assets/da1.ae7a2bb1.png",h="/assets/da6.5b5d63de.png",d="/assets/da7.b7b33663.png",l="/assets/da8.d623c64f.png",c="/assets/da3.e16fb4de.png",p="/assets/da9.35a2db61.png",I=JSON.parse('{"title":"Dice Armor","description":"","frontmatter":{"title":"Dice Armor"},"headers":[],"relativePath":"projects/dice/index.md","lastUpdated":1664944600000}'),g={name:"projects/dice/index.md"},m=i("",22),u=[m];function f(y,b,w,_,v,k){return a(),t("div",null,u)}const q=e(g,[["render",f]]);export{I as __pageData,q as default}; diff --git a/assets/projects_index.md.c8d3f066.js b/assets/projects_index.md.6cef1a12.js similarity index 95% rename from assets/projects_index.md.c8d3f066.js rename to assets/projects_index.md.6cef1a12.js index 43fa4c64a..1375dd36e 100644 --- a/assets/projects_index.md.c8d3f066.js +++ b/assets/projects_index.md.6cef1a12.js @@ -1 +1 @@ -import{_ as e,c as a,o as t,a as r}from"./app.a576d425.js";const f=JSON.parse('{"title":"Projects","description":"","frontmatter":{"title":"Projects","lastUpdated":false},"headers":[],"relativePath":"projects/index.md","lastUpdated":1664944072000}'),n={name:"projects/index.md"},s=r('

Games!

I make games regularly! Check them out in the sidebar or on my itch.io page.

Profectus!

I contributed to a modding framework called The Modding Tree and then made Profectus as an alternative that gives developers more control. Profectus is a game engine for the web that uses TS and Vue.

V-ecs!

V-ecs (pronounced "Vex") is a Vulkan-based engine I made for making highly moddable games and tools in Lua centered around the ECS design pattern and a work-stealing job system.

OptiSpeech!

I led a team updating a legacy Unity project for research on speech therapy to use a modern version with a focus on extensibility to facilitate future maintenance and features.

Babble Buds!

Babble Buds is a free, open-source virtual puppet show engine I made for various platforms including HTLM5 and Unity, as well as an accompanying electron-based puppet editor and multiplayer stage.

Dice Armor

I was the lead programmer on a team of nine creating this game in a semester-long college course. I programmed all the gameplay systems as well as incorporated Babble Buds for the cutscenes and tutorial.

Capture the Citadel

A 3D VR re-envisioning of a Slay the Spire-style game by Anthony Lawn and Grant Barbee.

',14),i=[s];function o(d,h,c,l,p,u){return t(),a("div",null,i)}const b=e(n,[["render",o]]);export{f as __pageData,b as default}; +import{_ as e,c as a,o as t,a as r}from"./app.9bfeb8de.js";const f=JSON.parse('{"title":"Projects","description":"","frontmatter":{"title":"Projects","lastUpdated":false},"headers":[],"relativePath":"projects/index.md","lastUpdated":1664944600000}'),n={name:"projects/index.md"},s=r('

Games!

I make games regularly! Check them out in the sidebar or on my itch.io page.

Profectus!

I contributed to a modding framework called The Modding Tree and then made Profectus as an alternative that gives developers more control. Profectus is a game engine for the web that uses TS and Vue.

V-ecs!

V-ecs (pronounced "Vex") is a Vulkan-based engine I made for making highly moddable games and tools in Lua centered around the ECS design pattern and a work-stealing job system.

OptiSpeech!

I led a team updating a legacy Unity project for research on speech therapy to use a modern version with a focus on extensibility to facilitate future maintenance and features.

Babble Buds!

Babble Buds is a free, open-source virtual puppet show engine I made for various platforms including HTLM5 and Unity, as well as an accompanying electron-based puppet editor and multiplayer stage.

Dice Armor

I was the lead programmer on a team of nine creating this game in a semester-long college course. I programmed all the gameplay systems as well as incorporated Babble Buds for the cutscenes and tutorial.

Capture the Citadel

A 3D VR re-envisioning of a Slay the Spire-style game by Anthony Lawn and Grant Barbee.

',14),i=[s];function o(d,h,c,l,p,u){return t(),a("div",null,i)}const b=e(n,[["render",o]]);export{f as __pageData,b as default}; diff --git a/assets/projects_index.md.c8d3f066.lean.js b/assets/projects_index.md.6cef1a12.lean.js similarity index 69% rename from assets/projects_index.md.c8d3f066.lean.js rename to assets/projects_index.md.6cef1a12.lean.js index 0d190acc9..a8f5f28a1 100644 --- a/assets/projects_index.md.c8d3f066.lean.js +++ b/assets/projects_index.md.6cef1a12.lean.js @@ -1 +1 @@ -import{_ as e,c as a,o as t,a as r}from"./app.a576d425.js";const f=JSON.parse('{"title":"Projects","description":"","frontmatter":{"title":"Projects","lastUpdated":false},"headers":[],"relativePath":"projects/index.md","lastUpdated":1664944072000}'),n={name:"projects/index.md"},s=r("",14),i=[s];function o(d,h,c,l,p,u){return t(),a("div",null,i)}const b=e(n,[["render",o]]);export{f as __pageData,b as default}; +import{_ as e,c as a,o as t,a as r}from"./app.9bfeb8de.js";const f=JSON.parse('{"title":"Projects","description":"","frontmatter":{"title":"Projects","lastUpdated":false},"headers":[],"relativePath":"projects/index.md","lastUpdated":1664944600000}'),n={name:"projects/index.md"},s=r("",14),i=[s];function o(d,h,c,l,p,u){return t(),a("div",null,i)}const b=e(n,[["render",o]]);export{f as __pageData,b as default}; diff --git a/assets/projects_optispeech_index.md.8f367a68.js b/assets/projects_optispeech_index.md.45da3222.js similarity index 95% rename from assets/projects_optispeech_index.md.8f367a68.js rename to assets/projects_optispeech_index.md.45da3222.js index a0b49a870..70db0f425 100644 --- a/assets/projects_optispeech_index.md.8f367a68.js +++ b/assets/projects_optispeech_index.md.45da3222.js @@ -1 +1 @@ -import{_ as t,c as s,o as a,b as e,d as o}from"./app.a576d425.js";const n="/assets/system-architecture-600.254c8a7e.jpg",r="/assets/new-interface.99f03ba7.png",i="/assets/documentation.4e9ae6e0.png",c="/assets/unittests.e8833eb5.png",U=JSON.parse('{"title":"OptiSpeech","description":"","frontmatter":{"title":"OptiSpeech"},"headers":[],"relativePath":"projects/optispeech/index.md","lastUpdated":1664944072000}'),l={name:"projects/optispeech/index.md"},d=e("h1",{id:"optispeech",tabindex:"-1"},[o("OptiSpeech "),e("a",{class:"header-anchor",href:"#optispeech","aria-hidden":"true"},"#")],-1),p=e("p",null,"The Optispeech project involves designing and testing a real-time tongue model that can be viewed in a transparent head while a subject talks \u2014 for the purposes of treating speech errors and teaching foreign language sounds. This work has been conducted in partnership with Vulintus and with support from the National Institutes of Health (NIH). The UT Dallas Speech Production Lab is currently updating the program to use updated versions of Unity and adding support for more features and hardware.",-1),h=e("p",null,[e("img",{src:n,alt:"System Architecture"})],-1),u=e("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/9uHqIRs7ZjM",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:"",style:{display:"block",margin:"auto"}},null,-1),m=e("p",null,"This video shows a talker with WAVE sensors placed on the tongue hitting a virtual target sphere located at the alveolar ridge. When an alveolar consonant is hit (e.g., /s/, /n/, /d/) the sphere changes color from red to green.",-1),g=e("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/Oz42mKvlzqI",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:"",style:{display:"block",margin:"auto"}},null,-1),_=e("p",null,"This video shows an American talker learning a novel sound not found in English. When the post-alveolar consonant is hit, the target sphere changes color from red to green. Here, the NDI WAVE system serves as input.",-1),f=e("p",null,"The program is being updated by a team in the UT Dallas Speech Production Lab led by Anthony Lawn, so the program uses a more modern version of Unity, has an easier-to-use interface, can more easily support new features, and can connect to additional EMA systems, namely the Carstens AG501.",-1),w=e("p",null,[e("img",{src:r,alt:"New Interface"})],-1),y=e("p",null,"In addition, the program now includes documentation and unit tests to improve program stability and maintainability going forward.",-1),b=e("p",null,[e("img",{src:i,alt:"Documentation"})],-1),v=e("p",null,[e("img",{src:c,alt:"Unit Tests"})],-1),T=[d,p,h,u,m,g,_,f,w,y,b,v];function k(x,A,I,N,S,j){return a(),s("div",null,T)}const D=t(l,[["render",k]]);export{U as __pageData,D as default}; +import{_ as t,c as s,o as a,b as e,d as o}from"./app.9bfeb8de.js";const n="/assets/system-architecture-600.254c8a7e.jpg",r="/assets/new-interface.99f03ba7.png",i="/assets/documentation.4e9ae6e0.png",c="/assets/unittests.e8833eb5.png",U=JSON.parse('{"title":"OptiSpeech","description":"","frontmatter":{"title":"OptiSpeech"},"headers":[],"relativePath":"projects/optispeech/index.md","lastUpdated":1664944600000}'),l={name:"projects/optispeech/index.md"},d=e("h1",{id:"optispeech",tabindex:"-1"},[o("OptiSpeech "),e("a",{class:"header-anchor",href:"#optispeech","aria-hidden":"true"},"#")],-1),p=e("p",null,"The Optispeech project involves designing and testing a real-time tongue model that can be viewed in a transparent head while a subject talks \u2014 for the purposes of treating speech errors and teaching foreign language sounds. This work has been conducted in partnership with Vulintus and with support from the National Institutes of Health (NIH). The UT Dallas Speech Production Lab is currently updating the program to use updated versions of Unity and adding support for more features and hardware.",-1),h=e("p",null,[e("img",{src:n,alt:"System Architecture"})],-1),u=e("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/9uHqIRs7ZjM",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:"",style:{display:"block",margin:"auto"}},null,-1),m=e("p",null,"This video shows a talker with WAVE sensors placed on the tongue hitting a virtual target sphere located at the alveolar ridge. When an alveolar consonant is hit (e.g., /s/, /n/, /d/) the sphere changes color from red to green.",-1),g=e("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/Oz42mKvlzqI",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:"",style:{display:"block",margin:"auto"}},null,-1),_=e("p",null,"This video shows an American talker learning a novel sound not found in English. When the post-alveolar consonant is hit, the target sphere changes color from red to green. Here, the NDI WAVE system serves as input.",-1),f=e("p",null,"The program is being updated by a team in the UT Dallas Speech Production Lab led by Anthony Lawn, so the program uses a more modern version of Unity, has an easier-to-use interface, can more easily support new features, and can connect to additional EMA systems, namely the Carstens AG501.",-1),w=e("p",null,[e("img",{src:r,alt:"New Interface"})],-1),y=e("p",null,"In addition, the program now includes documentation and unit tests to improve program stability and maintainability going forward.",-1),b=e("p",null,[e("img",{src:i,alt:"Documentation"})],-1),v=e("p",null,[e("img",{src:c,alt:"Unit Tests"})],-1),T=[d,p,h,u,m,g,_,f,w,y,b,v];function k(x,A,I,N,S,j){return a(),s("div",null,T)}const D=t(l,[["render",k]]);export{U as __pageData,D as default}; diff --git a/assets/projects_optispeech_index.md.8f367a68.lean.js b/assets/projects_optispeech_index.md.45da3222.lean.js similarity index 95% rename from assets/projects_optispeech_index.md.8f367a68.lean.js rename to assets/projects_optispeech_index.md.45da3222.lean.js index a0b49a870..70db0f425 100644 --- a/assets/projects_optispeech_index.md.8f367a68.lean.js +++ b/assets/projects_optispeech_index.md.45da3222.lean.js @@ -1 +1 @@ -import{_ as t,c as s,o as a,b as e,d as o}from"./app.a576d425.js";const n="/assets/system-architecture-600.254c8a7e.jpg",r="/assets/new-interface.99f03ba7.png",i="/assets/documentation.4e9ae6e0.png",c="/assets/unittests.e8833eb5.png",U=JSON.parse('{"title":"OptiSpeech","description":"","frontmatter":{"title":"OptiSpeech"},"headers":[],"relativePath":"projects/optispeech/index.md","lastUpdated":1664944072000}'),l={name:"projects/optispeech/index.md"},d=e("h1",{id:"optispeech",tabindex:"-1"},[o("OptiSpeech "),e("a",{class:"header-anchor",href:"#optispeech","aria-hidden":"true"},"#")],-1),p=e("p",null,"The Optispeech project involves designing and testing a real-time tongue model that can be viewed in a transparent head while a subject talks \u2014 for the purposes of treating speech errors and teaching foreign language sounds. This work has been conducted in partnership with Vulintus and with support from the National Institutes of Health (NIH). The UT Dallas Speech Production Lab is currently updating the program to use updated versions of Unity and adding support for more features and hardware.",-1),h=e("p",null,[e("img",{src:n,alt:"System Architecture"})],-1),u=e("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/9uHqIRs7ZjM",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:"",style:{display:"block",margin:"auto"}},null,-1),m=e("p",null,"This video shows a talker with WAVE sensors placed on the tongue hitting a virtual target sphere located at the alveolar ridge. When an alveolar consonant is hit (e.g., /s/, /n/, /d/) the sphere changes color from red to green.",-1),g=e("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/Oz42mKvlzqI",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:"",style:{display:"block",margin:"auto"}},null,-1),_=e("p",null,"This video shows an American talker learning a novel sound not found in English. When the post-alveolar consonant is hit, the target sphere changes color from red to green. Here, the NDI WAVE system serves as input.",-1),f=e("p",null,"The program is being updated by a team in the UT Dallas Speech Production Lab led by Anthony Lawn, so the program uses a more modern version of Unity, has an easier-to-use interface, can more easily support new features, and can connect to additional EMA systems, namely the Carstens AG501.",-1),w=e("p",null,[e("img",{src:r,alt:"New Interface"})],-1),y=e("p",null,"In addition, the program now includes documentation and unit tests to improve program stability and maintainability going forward.",-1),b=e("p",null,[e("img",{src:i,alt:"Documentation"})],-1),v=e("p",null,[e("img",{src:c,alt:"Unit Tests"})],-1),T=[d,p,h,u,m,g,_,f,w,y,b,v];function k(x,A,I,N,S,j){return a(),s("div",null,T)}const D=t(l,[["render",k]]);export{U as __pageData,D as default}; +import{_ as t,c as s,o as a,b as e,d as o}from"./app.9bfeb8de.js";const n="/assets/system-architecture-600.254c8a7e.jpg",r="/assets/new-interface.99f03ba7.png",i="/assets/documentation.4e9ae6e0.png",c="/assets/unittests.e8833eb5.png",U=JSON.parse('{"title":"OptiSpeech","description":"","frontmatter":{"title":"OptiSpeech"},"headers":[],"relativePath":"projects/optispeech/index.md","lastUpdated":1664944600000}'),l={name:"projects/optispeech/index.md"},d=e("h1",{id:"optispeech",tabindex:"-1"},[o("OptiSpeech "),e("a",{class:"header-anchor",href:"#optispeech","aria-hidden":"true"},"#")],-1),p=e("p",null,"The Optispeech project involves designing and testing a real-time tongue model that can be viewed in a transparent head while a subject talks \u2014 for the purposes of treating speech errors and teaching foreign language sounds. This work has been conducted in partnership with Vulintus and with support from the National Institutes of Health (NIH). The UT Dallas Speech Production Lab is currently updating the program to use updated versions of Unity and adding support for more features and hardware.",-1),h=e("p",null,[e("img",{src:n,alt:"System Architecture"})],-1),u=e("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/9uHqIRs7ZjM",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:"",style:{display:"block",margin:"auto"}},null,-1),m=e("p",null,"This video shows a talker with WAVE sensors placed on the tongue hitting a virtual target sphere located at the alveolar ridge. When an alveolar consonant is hit (e.g., /s/, /n/, /d/) the sphere changes color from red to green.",-1),g=e("iframe",{width:"560",height:"315",src:"https://www.youtube.com/embed/Oz42mKvlzqI",frameborder:"0",allow:"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:"",style:{display:"block",margin:"auto"}},null,-1),_=e("p",null,"This video shows an American talker learning a novel sound not found in English. When the post-alveolar consonant is hit, the target sphere changes color from red to green. Here, the NDI WAVE system serves as input.",-1),f=e("p",null,"The program is being updated by a team in the UT Dallas Speech Production Lab led by Anthony Lawn, so the program uses a more modern version of Unity, has an easier-to-use interface, can more easily support new features, and can connect to additional EMA systems, namely the Carstens AG501.",-1),w=e("p",null,[e("img",{src:r,alt:"New Interface"})],-1),y=e("p",null,"In addition, the program now includes documentation and unit tests to improve program stability and maintainability going forward.",-1),b=e("p",null,[e("img",{src:i,alt:"Documentation"})],-1),v=e("p",null,[e("img",{src:c,alt:"Unit Tests"})],-1),T=[d,p,h,u,m,g,_,f,w,y,b,v];function k(x,A,I,N,S,j){return a(),s("div",null,T)}const D=t(l,[["render",k]]);export{U as __pageData,D as default}; diff --git a/assets/projects_vecs_index.md.d11dedb4.js b/assets/projects_vecs_index.md.40b7a9dc.js similarity index 89% rename from assets/projects_vecs_index.md.d11dedb4.js rename to assets/projects_vecs_index.md.40b7a9dc.js index c287ff18e..1cc97caeb 100644 --- a/assets/projects_vecs_index.md.d11dedb4.js +++ b/assets/projects_vecs_index.md.40b7a9dc.js @@ -1 +1 @@ -import{_ as e,c as t,o as s,a}from"./app.a576d425.js";const o="/assets/screenshot.78830a30.png",n="/assets/debug.0a8c47b7.png",r="/assets/sandsoftime.ba63f865.png",w=JSON.parse('{"title":"V-ecs","description":"","frontmatter":{"title":"V-ecs"},"headers":[],"relativePath":"projects/vecs/index.md","lastUpdated":1664944072000}'),i={name:"projects/vecs/index.md"},d=a('

V-ecs

V-ecs Screenshot

V-ecs (pronounced "Vex") is a Vulkan-based engine I made for making highly moddable games and tools in Lua centered around the ECS design pattern and a work-stealing job system.

The engine works with "worlds", which are collections of systems and renderers. The engine comes with several worlds using systems and renderers I made, including a voxel world, an incremental game, and some test scenes. All of these include systems to render the fps as well as show a debug console by typing the grave key (`). The default world is a title screen that detects any worlds in the "worlds" folder and displays a button for each of them.

Debug Menu

The original plans were to eventually put it on the steam workshop so people could more easily share their creations amongst each other, but I never became happy enough with the performance of the engine - the parallelization of the lua code involved a lot of overhead that severely limited performance.

Instead, I made a couple of worlds by myself - an infinite procedurally generated voxel world, a simple incremental game, and a more complex incremental game I call "Sands of Time".

Sands of Time

',8),l=[d];function c(p,h,m,u,_,g){return s(),t("div",null,l)}const y=e(i,[["render",c]]);export{w as __pageData,y as default}; +import{_ as e,c as t,o as s,a}from"./app.9bfeb8de.js";const o="/assets/screenshot.78830a30.png",n="/assets/debug.0a8c47b7.png",r="/assets/sandsoftime.ba63f865.png",w=JSON.parse('{"title":"V-ecs","description":"","frontmatter":{"title":"V-ecs"},"headers":[],"relativePath":"projects/vecs/index.md","lastUpdated":1664944600000}'),i={name:"projects/vecs/index.md"},d=a('

V-ecs

V-ecs Screenshot

V-ecs (pronounced "Vex") is a Vulkan-based engine I made for making highly moddable games and tools in Lua centered around the ECS design pattern and a work-stealing job system.

The engine works with "worlds", which are collections of systems and renderers. The engine comes with several worlds using systems and renderers I made, including a voxel world, an incremental game, and some test scenes. All of these include systems to render the fps as well as show a debug console by typing the grave key (`). The default world is a title screen that detects any worlds in the "worlds" folder and displays a button for each of them.

Debug Menu

The original plans were to eventually put it on the steam workshop so people could more easily share their creations amongst each other, but I never became happy enough with the performance of the engine - the parallelization of the lua code involved a lot of overhead that severely limited performance.

Instead, I made a couple of worlds by myself - an infinite procedurally generated voxel world, a simple incremental game, and a more complex incremental game I call "Sands of Time".

Sands of Time

',8),l=[d];function c(p,h,m,u,_,g){return s(),t("div",null,l)}const y=e(i,[["render",c]]);export{w as __pageData,y as default}; diff --git a/assets/projects_vecs_index.md.d11dedb4.lean.js b/assets/projects_vecs_index.md.40b7a9dc.lean.js similarity index 61% rename from assets/projects_vecs_index.md.d11dedb4.lean.js rename to assets/projects_vecs_index.md.40b7a9dc.lean.js index bcbebf212..414dffe76 100644 --- a/assets/projects_vecs_index.md.d11dedb4.lean.js +++ b/assets/projects_vecs_index.md.40b7a9dc.lean.js @@ -1 +1 @@ -import{_ as e,c as t,o as s,a}from"./app.a576d425.js";const o="/assets/screenshot.78830a30.png",n="/assets/debug.0a8c47b7.png",r="/assets/sandsoftime.ba63f865.png",w=JSON.parse('{"title":"V-ecs","description":"","frontmatter":{"title":"V-ecs"},"headers":[],"relativePath":"projects/vecs/index.md","lastUpdated":1664944072000}'),i={name:"projects/vecs/index.md"},d=a("",8),l=[d];function c(p,h,m,u,_,g){return s(),t("div",null,l)}const y=e(i,[["render",c]]);export{w as __pageData,y as default}; +import{_ as e,c as t,o as s,a}from"./app.9bfeb8de.js";const o="/assets/screenshot.78830a30.png",n="/assets/debug.0a8c47b7.png",r="/assets/sandsoftime.ba63f865.png",w=JSON.parse('{"title":"V-ecs","description":"","frontmatter":{"title":"V-ecs"},"headers":[],"relativePath":"projects/vecs/index.md","lastUpdated":1664944600000}'),i={name:"projects/vecs/index.md"},d=a("",8),l=[d];function c(p,h,m,u,_,g){return s(),t("div",null,l)}const y=e(i,[["render",c]]);export{w as __pageData,y as default}; diff --git a/assets/public_gamedevtree_2.0-format-changes.md.447c1832.js b/assets/public_gamedevtree_2.0-format-changes.md.7cfcce8b.js similarity index 96% rename from assets/public_gamedevtree_2.0-format-changes.md.447c1832.js rename to assets/public_gamedevtree_2.0-format-changes.md.7cfcce8b.js index 065a8b871..bdef2fb57 100644 --- a/assets/public_gamedevtree_2.0-format-changes.md.447c1832.js +++ b/assets/public_gamedevtree_2.0-format-changes.md.7cfcce8b.js @@ -1 +1 @@ -import{_ as e,c as a,o as t,a as i}from"./app.a576d425.js";const m=JSON.parse('{"title":"2.0 format changes","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/2.0-format-changes.md","lastUpdated":null}'),n={name:"public/gamedevtree/2.0-format-changes.md"},l=i('

2.0 format changes

  • Temp format is changed from temp.something[layer] to temp[layer].something, for consistency
  • Challenges are now saved as an object with the amount of completions in each spot. (This will break saves.)
  • effectDisplay in Challenges and Upgrades no longer takes an argument, and neither does effect for Buyables
  • Buyable cost can take an argument for amount of buyables, but it needs to function if no argument is supplied (it should do the cost for the next purchase).
  • Generation of Points now happens in the main game loop (not in a layer update function), enabled by canGenPoints in game.js.
  • Changed fullLayerReset to layerDataReset, which takes an array of names of values to keep

In addition, many names were changed, mostly expanding abbreviations:

All instances of:

  • chall -> challenge
  • unl -> unlocked
  • upg -> upgrade (besides CSS)
  • amt -> amount
  • desc -> description
  • resCeil -> roundUpCost
  • order -> unlockOrder
  • incr_order -> increaseUnlockOrder

Challenges:

  • desc -> challengeDescription
  • reward -> rewardDescription
  • effect -> rewardEffect
  • effectDisplay -> rewardDisplay
  • active -> challengeActive
',7),o=[l];function s(r,c,d,g,h,p){return t(),a("div",null,o)}const u=e(n,[["render",s]]);export{m as __pageData,u as default}; +import{_ as e,c as a,o as t,a as i}from"./app.9bfeb8de.js";const m=JSON.parse('{"title":"2.0 format changes","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/2.0-format-changes.md","lastUpdated":null}'),n={name:"public/gamedevtree/2.0-format-changes.md"},l=i('

2.0 format changes

  • Temp format is changed from temp.something[layer] to temp[layer].something, for consistency
  • Challenges are now saved as an object with the amount of completions in each spot. (This will break saves.)
  • effectDisplay in Challenges and Upgrades no longer takes an argument, and neither does effect for Buyables
  • Buyable cost can take an argument for amount of buyables, but it needs to function if no argument is supplied (it should do the cost for the next purchase).
  • Generation of Points now happens in the main game loop (not in a layer update function), enabled by canGenPoints in game.js.
  • Changed fullLayerReset to layerDataReset, which takes an array of names of values to keep

In addition, many names were changed, mostly expanding abbreviations:

All instances of:

  • chall -> challenge
  • unl -> unlocked
  • upg -> upgrade (besides CSS)
  • amt -> amount
  • desc -> description
  • resCeil -> roundUpCost
  • order -> unlockOrder
  • incr_order -> increaseUnlockOrder

Challenges:

  • desc -> challengeDescription
  • reward -> rewardDescription
  • effect -> rewardEffect
  • effectDisplay -> rewardDisplay
  • active -> challengeActive
',7),o=[l];function s(r,c,d,g,h,p){return t(),a("div",null,o)}const u=e(n,[["render",s]]);export{m as __pageData,u as default}; diff --git a/assets/public_gamedevtree_2.0-format-changes.md.447c1832.lean.js b/assets/public_gamedevtree_2.0-format-changes.md.7cfcce8b.lean.js similarity index 84% rename from assets/public_gamedevtree_2.0-format-changes.md.447c1832.lean.js rename to assets/public_gamedevtree_2.0-format-changes.md.7cfcce8b.lean.js index 121fdfffd..a8ddbbf8c 100644 --- a/assets/public_gamedevtree_2.0-format-changes.md.447c1832.lean.js +++ b/assets/public_gamedevtree_2.0-format-changes.md.7cfcce8b.lean.js @@ -1 +1 @@ -import{_ as e,c as a,o as t,a as i}from"./app.a576d425.js";const m=JSON.parse('{"title":"2.0 format changes","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/2.0-format-changes.md","lastUpdated":null}'),n={name:"public/gamedevtree/2.0-format-changes.md"},l=i("",7),o=[l];function s(r,c,d,g,h,p){return t(),a("div",null,o)}const u=e(n,[["render",s]]);export{m as __pageData,u as default}; +import{_ as e,c as a,o as t,a as i}from"./app.9bfeb8de.js";const m=JSON.parse('{"title":"2.0 format changes","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/2.0-format-changes.md","lastUpdated":null}'),n={name:"public/gamedevtree/2.0-format-changes.md"},l=i("",7),o=[l];function s(r,c,d,g,h,p){return t(),a("div",null,o)}const u=e(n,[["render",s]]);export{m as __pageData,u as default}; diff --git a/assets/public_gamedevtree_README.md.a20d0a16.js b/assets/public_gamedevtree_README.md.49de9ca0.js similarity index 94% rename from assets/public_gamedevtree_README.md.a20d0a16.js rename to assets/public_gamedevtree_README.md.49de9ca0.js index fcde80b18..4b25e775c 100644 --- a/assets/public_gamedevtree_README.md.a20d0a16.js +++ b/assets/public_gamedevtree_README.md.49de9ca0.js @@ -1 +1 @@ -import{_ as o,c as a,o as r,b as e,d as t}from"./app.a576d425.js";const T=JSON.parse('{"title":"The-Modding-Tree","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/README.md","lastUpdated":null}'),n={name:"public/gamedevtree/README.md"},s=e("h1",{id:"the-modding-tree",tabindex:"-1"},[t("The-Modding-Tree "),e("a",{class:"header-anchor",href:"#the-modding-tree","aria-hidden":"true"},"#")],-1),i=e("p",null,"A modified version of The Prestige Tree that is much easier to mod. It still requires programming knowledge, but it's mostly pretty easy things and copy/pasting.",-1),d=e("p",null,[e("a",{href:"./docs/getting-started"},"Look here for a tutorial on getting started with modding with TMT")],-1),l=e("p",null,[t("You can look in the "),e("a",{href:"./docs/!general-info"},"documentation"),t(" for more information on how it all works, or look at the code in layers.js to see what it all looks like.")],-1),c=[s,i,d,l];function h(m,p,_,g,u,f){return r(),a("div",null,c)}const E=o(n,[["render",h]]);export{T as __pageData,E as default}; +import{_ as o,c as a,o as r,b as e,d as t}from"./app.9bfeb8de.js";const T=JSON.parse('{"title":"The-Modding-Tree","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/README.md","lastUpdated":null}'),n={name:"public/gamedevtree/README.md"},s=e("h1",{id:"the-modding-tree",tabindex:"-1"},[t("The-Modding-Tree "),e("a",{class:"header-anchor",href:"#the-modding-tree","aria-hidden":"true"},"#")],-1),i=e("p",null,"A modified version of The Prestige Tree that is much easier to mod. It still requires programming knowledge, but it's mostly pretty easy things and copy/pasting.",-1),d=e("p",null,[e("a",{href:"./docs/getting-started"},"Look here for a tutorial on getting started with modding with TMT")],-1),l=e("p",null,[t("You can look in the "),e("a",{href:"./docs/!general-info"},"documentation"),t(" for more information on how it all works, or look at the code in layers.js to see what it all looks like.")],-1),c=[s,i,d,l];function h(m,p,_,g,u,f){return r(),a("div",null,c)}const E=o(n,[["render",h]]);export{T as __pageData,E as default}; diff --git a/assets/public_gamedevtree_README.md.a20d0a16.lean.js b/assets/public_gamedevtree_README.md.49de9ca0.lean.js similarity index 94% rename from assets/public_gamedevtree_README.md.a20d0a16.lean.js rename to assets/public_gamedevtree_README.md.49de9ca0.lean.js index fcde80b18..4b25e775c 100644 --- a/assets/public_gamedevtree_README.md.a20d0a16.lean.js +++ b/assets/public_gamedevtree_README.md.49de9ca0.lean.js @@ -1 +1 @@ -import{_ as o,c as a,o as r,b as e,d as t}from"./app.a576d425.js";const T=JSON.parse('{"title":"The-Modding-Tree","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/README.md","lastUpdated":null}'),n={name:"public/gamedevtree/README.md"},s=e("h1",{id:"the-modding-tree",tabindex:"-1"},[t("The-Modding-Tree "),e("a",{class:"header-anchor",href:"#the-modding-tree","aria-hidden":"true"},"#")],-1),i=e("p",null,"A modified version of The Prestige Tree that is much easier to mod. It still requires programming knowledge, but it's mostly pretty easy things and copy/pasting.",-1),d=e("p",null,[e("a",{href:"./docs/getting-started"},"Look here for a tutorial on getting started with modding with TMT")],-1),l=e("p",null,[t("You can look in the "),e("a",{href:"./docs/!general-info"},"documentation"),t(" for more information on how it all works, or look at the code in layers.js to see what it all looks like.")],-1),c=[s,i,d,l];function h(m,p,_,g,u,f){return r(),a("div",null,c)}const E=o(n,[["render",h]]);export{T as __pageData,E as default}; +import{_ as o,c as a,o as r,b as e,d as t}from"./app.9bfeb8de.js";const T=JSON.parse('{"title":"The-Modding-Tree","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/README.md","lastUpdated":null}'),n={name:"public/gamedevtree/README.md"},s=e("h1",{id:"the-modding-tree",tabindex:"-1"},[t("The-Modding-Tree "),e("a",{class:"header-anchor",href:"#the-modding-tree","aria-hidden":"true"},"#")],-1),i=e("p",null,"A modified version of The Prestige Tree that is much easier to mod. It still requires programming knowledge, but it's mostly pretty easy things and copy/pasting.",-1),d=e("p",null,[e("a",{href:"./docs/getting-started"},"Look here for a tutorial on getting started with modding with TMT")],-1),l=e("p",null,[t("You can look in the "),e("a",{href:"./docs/!general-info"},"documentation"),t(" for more information on how it all works, or look at the code in layers.js to see what it all looks like.")],-1),c=[s,i,d,l];function h(m,p,_,g,u,f){return r(),a("div",null,c)}const E=o(n,[["render",h]]);export{T as __pageData,E as default}; diff --git a/assets/public_gamedevtree_changelog.md.77d8af60.js b/assets/public_gamedevtree_changelog.md.7503a901.js similarity index 98% rename from assets/public_gamedevtree_changelog.md.77d8af60.js rename to assets/public_gamedevtree_changelog.md.7503a901.js index f3d9ac4ff..f820acc16 100644 --- a/assets/public_gamedevtree_changelog.md.77d8af60.js +++ b/assets/public_gamedevtree_changelog.md.7503a901.js @@ -1 +1 @@ -import{_ as e,c as i,o as l,a}from"./app.a576d425.js";const g=JSON.parse('{"title":"The Game Dev Tree changelog:","description":"","frontmatter":{},"headers":[{"level":3,"title":"v1.0.4 Version Bump [rebalanced,debuggedx3] - 2020-11-09","slug":"v1-0-4-version-bump-rebalanced-debuggedx3-2020-11-09","link":"#v1-0-4-version-bump-rebalanced-debuggedx3-2020-11-09","children":[]},{"level":3,"title":"v1.0.3 Version Bump [rebalanced,debuggedx2] - 2020-11-08","slug":"v1-0-3-version-bump-rebalanced-debuggedx2-2020-11-08","link":"#v1-0-3-version-bump-rebalanced-debuggedx2-2020-11-08","children":[]},{"level":3,"title":"v1.0.2 Version Bump [rebalanced,debugged] - 2020-11-08","slug":"v1-0-2-version-bump-rebalanced-debugged-2020-11-08","link":"#v1-0-2-version-bump-rebalanced-debugged-2020-11-08","children":[]},{"level":3,"title":"v1.0.1 Version Bump [rebalanced] - 2020-11-08","slug":"v1-0-1-version-bump-rebalanced-2020-11-08","link":"#v1-0-1-version-bump-rebalanced-2020-11-08","children":[]},{"level":3,"title":"v1.0 Version Bump - 2020-11-08","slug":"v1-0-version-bump-2020-11-08","link":"#v1-0-version-bump-2020-11-08","children":[]},{"level":3,"title":"v0.2.3 Stylish - 2020-10-30","slug":"v0-2-3-stylish-2020-10-30","link":"#v0-2-3-stylish-2020-10-30","children":[]},{"level":3,"title":"v0.2.2 Row 3 - 2020-10-22","slug":"v0-2-2-row-3-2020-10-22","link":"#v0-2-2-row-3-2020-10-22","children":[]},{"level":3,"title":"v0.2.1 Row 3 - 2020-10-21","slug":"v0-2-1-row-3-2020-10-21","link":"#v0-2-1-row-3-2020-10-21","children":[]},{"level":3,"title":"v0.2 Row 3 - 2020-10-21","slug":"v0-2-row-3-2020-10-21","link":"#v0-2-row-3-2020-10-21","children":[]},{"level":3,"title":"v0.1.1 Cash Influx [rebalanced] - 2020-10-19","slug":"v0-1-1-cash-influx-rebalanced-2020-10-19","link":"#v0-1-1-cash-influx-rebalanced-2020-10-19","children":[]},{"level":3,"title":"v0.1 Cash Influx - 2020-10-19","slug":"v0-1-cash-influx-2020-10-19","link":"#v0-1-cash-influx-2020-10-19","children":[]},{"level":3,"title":"v0.0 Initial Commit - 2020-10-18","slug":"v0-0-initial-commit-2020-10-18","link":"#v0-0-initial-commit-2020-10-18","children":[]}],"relativePath":"public/gamedevtree/changelog.md","lastUpdated":null}'),r={name:"public/gamedevtree/changelog.md"},n=a('

The Game Dev Tree changelog:

v1.0.4 Version Bump [rebalanced,debuggedx3] - 2020-11-09

  • Fixed refactorings 2, 3, and 4 not actually affecting productivity

v1.0.3 Version Bump [rebalanced,debuggedx2] - 2020-11-08

  • Fixed API milestone 4 not working

v1.0.2 Version Bump [rebalanced,debugged] - 2020-11-08

  • Fixed tree lines being hidden after hitting "keepGoing" in the victory screen

v1.0.1 Version Bump [rebalanced] - 2020-11-08

  • Buffed several TAs

v1.0 Version Bump - 2020-11-08

  • Finished row 4
  • Added colored text to lore
  • Fixed some visual bugs with milestones
  • Probably other stuff lol its been a week

v0.2.3 Stylish - 2020-10-30

  • Re-styled basically everything
  • Added favicon
  • Added header bar
  • Added changelog

v0.2.2 Row 3 - 2020-10-22

  • Removed debug statement
  • Moved milestones in F layer beneath the buyables

v0.2.1 Row 3 - 2020-10-21

  • Fixed layers hiding
  • Fixed typos/minor issues
  • Fixed S layer being highlighted before you can unlock the layer

v0.2 Row 3 - 2020-10-21

  • Implemented row 3

v0.1.1 Cash Influx [rebalanced] - 2020-10-19

  • Fixed notification issue
  • Rebalanced to make early game faster and late game slower
  • Fixed other minor issues

v0.1 Cash Influx - 2020-10-19

  • Implemented row 2

v0.0 Initial Commit - 2020-10-18

  • Implemented row 1
',25),d=[n];function t(s,h,o,u,c,v){return l(),i("div",null,d)}const m=e(r,[["render",t]]);export{g as __pageData,m as default}; +import{_ as e,c as i,o as l,a}from"./app.9bfeb8de.js";const g=JSON.parse('{"title":"The Game Dev Tree changelog:","description":"","frontmatter":{},"headers":[{"level":3,"title":"v1.0.4 Version Bump [rebalanced,debuggedx3] - 2020-11-09","slug":"v1-0-4-version-bump-rebalanced-debuggedx3-2020-11-09","link":"#v1-0-4-version-bump-rebalanced-debuggedx3-2020-11-09","children":[]},{"level":3,"title":"v1.0.3 Version Bump [rebalanced,debuggedx2] - 2020-11-08","slug":"v1-0-3-version-bump-rebalanced-debuggedx2-2020-11-08","link":"#v1-0-3-version-bump-rebalanced-debuggedx2-2020-11-08","children":[]},{"level":3,"title":"v1.0.2 Version Bump [rebalanced,debugged] - 2020-11-08","slug":"v1-0-2-version-bump-rebalanced-debugged-2020-11-08","link":"#v1-0-2-version-bump-rebalanced-debugged-2020-11-08","children":[]},{"level":3,"title":"v1.0.1 Version Bump [rebalanced] - 2020-11-08","slug":"v1-0-1-version-bump-rebalanced-2020-11-08","link":"#v1-0-1-version-bump-rebalanced-2020-11-08","children":[]},{"level":3,"title":"v1.0 Version Bump - 2020-11-08","slug":"v1-0-version-bump-2020-11-08","link":"#v1-0-version-bump-2020-11-08","children":[]},{"level":3,"title":"v0.2.3 Stylish - 2020-10-30","slug":"v0-2-3-stylish-2020-10-30","link":"#v0-2-3-stylish-2020-10-30","children":[]},{"level":3,"title":"v0.2.2 Row 3 - 2020-10-22","slug":"v0-2-2-row-3-2020-10-22","link":"#v0-2-2-row-3-2020-10-22","children":[]},{"level":3,"title":"v0.2.1 Row 3 - 2020-10-21","slug":"v0-2-1-row-3-2020-10-21","link":"#v0-2-1-row-3-2020-10-21","children":[]},{"level":3,"title":"v0.2 Row 3 - 2020-10-21","slug":"v0-2-row-3-2020-10-21","link":"#v0-2-row-3-2020-10-21","children":[]},{"level":3,"title":"v0.1.1 Cash Influx [rebalanced] - 2020-10-19","slug":"v0-1-1-cash-influx-rebalanced-2020-10-19","link":"#v0-1-1-cash-influx-rebalanced-2020-10-19","children":[]},{"level":3,"title":"v0.1 Cash Influx - 2020-10-19","slug":"v0-1-cash-influx-2020-10-19","link":"#v0-1-cash-influx-2020-10-19","children":[]},{"level":3,"title":"v0.0 Initial Commit - 2020-10-18","slug":"v0-0-initial-commit-2020-10-18","link":"#v0-0-initial-commit-2020-10-18","children":[]}],"relativePath":"public/gamedevtree/changelog.md","lastUpdated":null}'),r={name:"public/gamedevtree/changelog.md"},n=a('

The Game Dev Tree changelog:

v1.0.4 Version Bump [rebalanced,debuggedx3] - 2020-11-09

  • Fixed refactorings 2, 3, and 4 not actually affecting productivity

v1.0.3 Version Bump [rebalanced,debuggedx2] - 2020-11-08

  • Fixed API milestone 4 not working

v1.0.2 Version Bump [rebalanced,debugged] - 2020-11-08

  • Fixed tree lines being hidden after hitting "keepGoing" in the victory screen

v1.0.1 Version Bump [rebalanced] - 2020-11-08

  • Buffed several TAs

v1.0 Version Bump - 2020-11-08

  • Finished row 4
  • Added colored text to lore
  • Fixed some visual bugs with milestones
  • Probably other stuff lol its been a week

v0.2.3 Stylish - 2020-10-30

  • Re-styled basically everything
  • Added favicon
  • Added header bar
  • Added changelog

v0.2.2 Row 3 - 2020-10-22

  • Removed debug statement
  • Moved milestones in F layer beneath the buyables

v0.2.1 Row 3 - 2020-10-21

  • Fixed layers hiding
  • Fixed typos/minor issues
  • Fixed S layer being highlighted before you can unlock the layer

v0.2 Row 3 - 2020-10-21

  • Implemented row 3

v0.1.1 Cash Influx [rebalanced] - 2020-10-19

  • Fixed notification issue
  • Rebalanced to make early game faster and late game slower
  • Fixed other minor issues

v0.1 Cash Influx - 2020-10-19

  • Implemented row 2

v0.0 Initial Commit - 2020-10-18

  • Implemented row 1
',25),d=[n];function t(s,h,o,u,c,v){return l(),i("div",null,d)}const m=e(r,[["render",t]]);export{g as __pageData,m as default}; diff --git a/assets/public_gamedevtree_changelog.md.77d8af60.lean.js b/assets/public_gamedevtree_changelog.md.7503a901.lean.js similarity index 97% rename from assets/public_gamedevtree_changelog.md.77d8af60.lean.js rename to assets/public_gamedevtree_changelog.md.7503a901.lean.js index 6e3a22672..779001994 100644 --- a/assets/public_gamedevtree_changelog.md.77d8af60.lean.js +++ b/assets/public_gamedevtree_changelog.md.7503a901.lean.js @@ -1 +1 @@ -import{_ as e,c as i,o as l,a}from"./app.a576d425.js";const g=JSON.parse('{"title":"The Game Dev Tree changelog:","description":"","frontmatter":{},"headers":[{"level":3,"title":"v1.0.4 Version Bump [rebalanced,debuggedx3] - 2020-11-09","slug":"v1-0-4-version-bump-rebalanced-debuggedx3-2020-11-09","link":"#v1-0-4-version-bump-rebalanced-debuggedx3-2020-11-09","children":[]},{"level":3,"title":"v1.0.3 Version Bump [rebalanced,debuggedx2] - 2020-11-08","slug":"v1-0-3-version-bump-rebalanced-debuggedx2-2020-11-08","link":"#v1-0-3-version-bump-rebalanced-debuggedx2-2020-11-08","children":[]},{"level":3,"title":"v1.0.2 Version Bump [rebalanced,debugged] - 2020-11-08","slug":"v1-0-2-version-bump-rebalanced-debugged-2020-11-08","link":"#v1-0-2-version-bump-rebalanced-debugged-2020-11-08","children":[]},{"level":3,"title":"v1.0.1 Version Bump [rebalanced] - 2020-11-08","slug":"v1-0-1-version-bump-rebalanced-2020-11-08","link":"#v1-0-1-version-bump-rebalanced-2020-11-08","children":[]},{"level":3,"title":"v1.0 Version Bump - 2020-11-08","slug":"v1-0-version-bump-2020-11-08","link":"#v1-0-version-bump-2020-11-08","children":[]},{"level":3,"title":"v0.2.3 Stylish - 2020-10-30","slug":"v0-2-3-stylish-2020-10-30","link":"#v0-2-3-stylish-2020-10-30","children":[]},{"level":3,"title":"v0.2.2 Row 3 - 2020-10-22","slug":"v0-2-2-row-3-2020-10-22","link":"#v0-2-2-row-3-2020-10-22","children":[]},{"level":3,"title":"v0.2.1 Row 3 - 2020-10-21","slug":"v0-2-1-row-3-2020-10-21","link":"#v0-2-1-row-3-2020-10-21","children":[]},{"level":3,"title":"v0.2 Row 3 - 2020-10-21","slug":"v0-2-row-3-2020-10-21","link":"#v0-2-row-3-2020-10-21","children":[]},{"level":3,"title":"v0.1.1 Cash Influx [rebalanced] - 2020-10-19","slug":"v0-1-1-cash-influx-rebalanced-2020-10-19","link":"#v0-1-1-cash-influx-rebalanced-2020-10-19","children":[]},{"level":3,"title":"v0.1 Cash Influx - 2020-10-19","slug":"v0-1-cash-influx-2020-10-19","link":"#v0-1-cash-influx-2020-10-19","children":[]},{"level":3,"title":"v0.0 Initial Commit - 2020-10-18","slug":"v0-0-initial-commit-2020-10-18","link":"#v0-0-initial-commit-2020-10-18","children":[]}],"relativePath":"public/gamedevtree/changelog.md","lastUpdated":null}'),r={name:"public/gamedevtree/changelog.md"},n=a("",25),d=[n];function t(s,h,o,u,c,v){return l(),i("div",null,d)}const m=e(r,[["render",t]]);export{g as __pageData,m as default}; +import{_ as e,c as i,o as l,a}from"./app.9bfeb8de.js";const g=JSON.parse('{"title":"The Game Dev Tree changelog:","description":"","frontmatter":{},"headers":[{"level":3,"title":"v1.0.4 Version Bump [rebalanced,debuggedx3] - 2020-11-09","slug":"v1-0-4-version-bump-rebalanced-debuggedx3-2020-11-09","link":"#v1-0-4-version-bump-rebalanced-debuggedx3-2020-11-09","children":[]},{"level":3,"title":"v1.0.3 Version Bump [rebalanced,debuggedx2] - 2020-11-08","slug":"v1-0-3-version-bump-rebalanced-debuggedx2-2020-11-08","link":"#v1-0-3-version-bump-rebalanced-debuggedx2-2020-11-08","children":[]},{"level":3,"title":"v1.0.2 Version Bump [rebalanced,debugged] - 2020-11-08","slug":"v1-0-2-version-bump-rebalanced-debugged-2020-11-08","link":"#v1-0-2-version-bump-rebalanced-debugged-2020-11-08","children":[]},{"level":3,"title":"v1.0.1 Version Bump [rebalanced] - 2020-11-08","slug":"v1-0-1-version-bump-rebalanced-2020-11-08","link":"#v1-0-1-version-bump-rebalanced-2020-11-08","children":[]},{"level":3,"title":"v1.0 Version Bump - 2020-11-08","slug":"v1-0-version-bump-2020-11-08","link":"#v1-0-version-bump-2020-11-08","children":[]},{"level":3,"title":"v0.2.3 Stylish - 2020-10-30","slug":"v0-2-3-stylish-2020-10-30","link":"#v0-2-3-stylish-2020-10-30","children":[]},{"level":3,"title":"v0.2.2 Row 3 - 2020-10-22","slug":"v0-2-2-row-3-2020-10-22","link":"#v0-2-2-row-3-2020-10-22","children":[]},{"level":3,"title":"v0.2.1 Row 3 - 2020-10-21","slug":"v0-2-1-row-3-2020-10-21","link":"#v0-2-1-row-3-2020-10-21","children":[]},{"level":3,"title":"v0.2 Row 3 - 2020-10-21","slug":"v0-2-row-3-2020-10-21","link":"#v0-2-row-3-2020-10-21","children":[]},{"level":3,"title":"v0.1.1 Cash Influx [rebalanced] - 2020-10-19","slug":"v0-1-1-cash-influx-rebalanced-2020-10-19","link":"#v0-1-1-cash-influx-rebalanced-2020-10-19","children":[]},{"level":3,"title":"v0.1 Cash Influx - 2020-10-19","slug":"v0-1-cash-influx-2020-10-19","link":"#v0-1-cash-influx-2020-10-19","children":[]},{"level":3,"title":"v0.0 Initial Commit - 2020-10-18","slug":"v0-0-initial-commit-2020-10-18","link":"#v0-0-initial-commit-2020-10-18","children":[]}],"relativePath":"public/gamedevtree/changelog.md","lastUpdated":null}'),r={name:"public/gamedevtree/changelog.md"},n=a("",25),d=[n];function t(s,h,o,u,c,v){return l(),i("div",null,d)}const m=e(r,[["render",t]]);export{g as __pageData,m as default}; diff --git a/assets/public_gamedevtree_docs_!general-info.md.a23875ce.js b/assets/public_gamedevtree_docs_!general-info.md.9545d5e0.js similarity index 98% rename from assets/public_gamedevtree_docs_!general-info.md.a23875ce.js rename to assets/public_gamedevtree_docs_!general-info.md.9545d5e0.js index 36795f6e3..97b4817d9 100644 --- a/assets/public_gamedevtree_docs_!general-info.md.a23875ce.js +++ b/assets/public_gamedevtree_docs_!general-info.md.9545d5e0.js @@ -1 +1 @@ -import{_ as e,c as a,o as t,a as o}from"./app.a576d425.js";const p=JSON.parse('{"title":"The-Modding-Tree","description":"","frontmatter":{},"headers":[{"level":2,"title":"General:","slug":"general","link":"#general","children":[]},{"level":2,"title":"Common components","slug":"common-components","link":"#common-components","children":[]},{"level":2,"title":"Other components","slug":"other-components","link":"#other-components","children":[]}],"relativePath":"public/gamedevtree/docs/!general-info.md","lastUpdated":null}'),n={name:"public/gamedevtree/docs/!general-info.md"},r=o('

The-Modding-Tree

The main way to add content is through creating layers. You can either add a layer directly in the layers object in layersSupportjs, or declare it in another file and then do "addLayer(layername, layerdata)" (good for breaking things up into smaller files). The existing layers are just examples and can be freely deleted. You can also use them as references and a base for your own layers.

The first thing you need to do is to edit the modInfo at the top of game.js to set your modID (a string). A unique modId will prevent your mod's saves from conflicting with other mods.

Most of the time, you won't need to dive deep into the code to create things, but you still can if you really want to.

The Modding Tree uses break_eternity.js to store large values. This means that many numbers are Decimal objects, and must be treated differently. For example, you have to use new Decimal(x) to create a Decimal value instead of a plain number, and perform operations on them by calling functions. e.g, instead of x = x + y, use x = x.add(y).

Almost all values can be either a constant value, or a dynamic value. Dynamic values are defined by putting a function that returns what the value should be at any given time.

All display text can be basic HTML instead (But you can't use most Vue features there).

Table of Contents:

General:

  • Getting Started: Getting your own copy of the code set up with Github Desktop.
  • Main mod info: How to set up general things for your mod in mod.js.
  • Basic layer breakdown: Breaking down the components of a layer with minimal features.
  • Layer features: Explanations of all of the different properties that you can give a layer.
  • Custom Tab Layouts: An optional way to give your tabs a different layout. You can even create entirely new components to use.
  • Updating TMT: Using Github Desktop to update your mod's version of TMT.

Common components

  • Upgrades: How to create upgrades for a layer.
  • Milestones: How to create milestones for a layer.
  • Buyables: Create rebuyable upgrades for your layer (with the option to make them respec-able). Can be used to make Enhancers or Space Buildings.
  • Clickables: A more generalized variant of buyables, for any kind of thing that is sometimes clickable. Between these and Buyables, you can do just about anything.

Other components

  • Challenges: How to create challenges for a layer.
  • Bars: Display some information as a progress bar, gague, or similar. They are highly customizable, and can be horizontal and vertical as well.
  • Subtabs and Microtabs: Create subtabs for your tabs, as well as "microtab" components that you can put inside the tabs.
  • Achievements: How to create achievements for a layer (or for the whole game).
  • Infoboxes: Boxes containing text that can be shown or hidden.
',14),i=[r];function s(l,d,c,h,u,m){return t(),a("div",null,i)}const y=e(n,[["render",s]]);export{p as __pageData,y as default}; +import{_ as e,c as a,o as t,a as o}from"./app.9bfeb8de.js";const p=JSON.parse('{"title":"The-Modding-Tree","description":"","frontmatter":{},"headers":[{"level":2,"title":"General:","slug":"general","link":"#general","children":[]},{"level":2,"title":"Common components","slug":"common-components","link":"#common-components","children":[]},{"level":2,"title":"Other components","slug":"other-components","link":"#other-components","children":[]}],"relativePath":"public/gamedevtree/docs/!general-info.md","lastUpdated":null}'),n={name:"public/gamedevtree/docs/!general-info.md"},r=o('

The-Modding-Tree

The main way to add content is through creating layers. You can either add a layer directly in the layers object in layersSupportjs, or declare it in another file and then do "addLayer(layername, layerdata)" (good for breaking things up into smaller files). The existing layers are just examples and can be freely deleted. You can also use them as references and a base for your own layers.

The first thing you need to do is to edit the modInfo at the top of game.js to set your modID (a string). A unique modId will prevent your mod's saves from conflicting with other mods.

Most of the time, you won't need to dive deep into the code to create things, but you still can if you really want to.

The Modding Tree uses break_eternity.js to store large values. This means that many numbers are Decimal objects, and must be treated differently. For example, you have to use new Decimal(x) to create a Decimal value instead of a plain number, and perform operations on them by calling functions. e.g, instead of x = x + y, use x = x.add(y).

Almost all values can be either a constant value, or a dynamic value. Dynamic values are defined by putting a function that returns what the value should be at any given time.

All display text can be basic HTML instead (But you can't use most Vue features there).

Table of Contents:

General:

  • Getting Started: Getting your own copy of the code set up with Github Desktop.
  • Main mod info: How to set up general things for your mod in mod.js.
  • Basic layer breakdown: Breaking down the components of a layer with minimal features.
  • Layer features: Explanations of all of the different properties that you can give a layer.
  • Custom Tab Layouts: An optional way to give your tabs a different layout. You can even create entirely new components to use.
  • Updating TMT: Using Github Desktop to update your mod's version of TMT.

Common components

  • Upgrades: How to create upgrades for a layer.
  • Milestones: How to create milestones for a layer.
  • Buyables: Create rebuyable upgrades for your layer (with the option to make them respec-able). Can be used to make Enhancers or Space Buildings.
  • Clickables: A more generalized variant of buyables, for any kind of thing that is sometimes clickable. Between these and Buyables, you can do just about anything.

Other components

  • Challenges: How to create challenges for a layer.
  • Bars: Display some information as a progress bar, gague, or similar. They are highly customizable, and can be horizontal and vertical as well.
  • Subtabs and Microtabs: Create subtabs for your tabs, as well as "microtab" components that you can put inside the tabs.
  • Achievements: How to create achievements for a layer (or for the whole game).
  • Infoboxes: Boxes containing text that can be shown or hidden.
',14),i=[r];function s(l,d,c,h,u,m){return t(),a("div",null,i)}const y=e(n,[["render",s]]);export{p as __pageData,y as default}; diff --git a/assets/public_gamedevtree_docs_!general-info.md.a23875ce.lean.js b/assets/public_gamedevtree_docs_!general-info.md.9545d5e0.lean.js similarity index 91% rename from assets/public_gamedevtree_docs_!general-info.md.a23875ce.lean.js rename to assets/public_gamedevtree_docs_!general-info.md.9545d5e0.lean.js index 23ff9f6d9..6210dcabf 100644 --- a/assets/public_gamedevtree_docs_!general-info.md.a23875ce.lean.js +++ b/assets/public_gamedevtree_docs_!general-info.md.9545d5e0.lean.js @@ -1 +1 @@ -import{_ as e,c as a,o as t,a as o}from"./app.a576d425.js";const p=JSON.parse('{"title":"The-Modding-Tree","description":"","frontmatter":{},"headers":[{"level":2,"title":"General:","slug":"general","link":"#general","children":[]},{"level":2,"title":"Common components","slug":"common-components","link":"#common-components","children":[]},{"level":2,"title":"Other components","slug":"other-components","link":"#other-components","children":[]}],"relativePath":"public/gamedevtree/docs/!general-info.md","lastUpdated":null}'),n={name:"public/gamedevtree/docs/!general-info.md"},r=o("",14),i=[r];function s(l,d,c,h,u,m){return t(),a("div",null,i)}const y=e(n,[["render",s]]);export{p as __pageData,y as default}; +import{_ as e,c as a,o as t,a as o}from"./app.9bfeb8de.js";const p=JSON.parse('{"title":"The-Modding-Tree","description":"","frontmatter":{},"headers":[{"level":2,"title":"General:","slug":"general","link":"#general","children":[]},{"level":2,"title":"Common components","slug":"common-components","link":"#common-components","children":[]},{"level":2,"title":"Other components","slug":"other-components","link":"#other-components","children":[]}],"relativePath":"public/gamedevtree/docs/!general-info.md","lastUpdated":null}'),n={name:"public/gamedevtree/docs/!general-info.md"},r=o("",14),i=[r];function s(l,d,c,h,u,m){return t(),a("div",null,i)}const y=e(n,[["render",s]]);export{p as __pageData,y as default}; diff --git a/assets/public_gamedevtree_docs_achievements.md.6dd68dae.js b/assets/public_gamedevtree_docs_achievements.md.bdb26d53.js similarity index 98% rename from assets/public_gamedevtree_docs_achievements.md.6dd68dae.js rename to assets/public_gamedevtree_docs_achievements.md.bdb26d53.js index db9b17753..5bac68dee 100644 --- a/assets/public_gamedevtree_docs_achievements.md.6dd68dae.js +++ b/assets/public_gamedevtree_docs_achievements.md.bdb26d53.js @@ -1,4 +1,4 @@ -import{_ as e,c as a,o as s,a as t}from"./app.a576d425.js";const y=JSON.parse('{"title":"Achievements","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/achievements.md","lastUpdated":null}'),n={name:"public/gamedevtree/docs/achievements.md"},o=t(`

Achievements

Achievements are awarded to the player when they meet a certain goal, and give some benefit. Currently, they are pretty basic, but additional features will be added later to help.

You can make global achievements by putting them in a side layer (make its row "side" instead of a number)

Useful functions for dealing with achievements and implementing their effects:

  • hasAchievement(layer, id): determine if the player has the Achievement
  • achievementEffect(layer, id): Returns the current effects of the achievement, if any

Achievements should be formatted like this:

js
    achievements: {
+import{_ as e,c as a,o as s,a as t}from"./app.9bfeb8de.js";const y=JSON.parse('{"title":"Achievements","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/achievements.md","lastUpdated":null}'),n={name:"public/gamedevtree/docs/achievements.md"},o=t(`

Achievements

Achievements are awarded to the player when they meet a certain goal, and give some benefit. Currently, they are pretty basic, but additional features will be added later to help.

You can make global achievements by putting them in a side layer (make its row "side" instead of a number)

Useful functions for dealing with achievements and implementing their effects:

  • hasAchievement(layer, id): determine if the player has the Achievement
  • achievementEffect(layer, id): Returns the current effects of the achievement, if any

Achievements should be formatted like this:

js
    achievements: {
         rows: # of rows
         cols: # of columns
         11: {
diff --git a/assets/public_gamedevtree_docs_achievements.md.6dd68dae.lean.js b/assets/public_gamedevtree_docs_achievements.md.bdb26d53.lean.js
similarity index 84%
rename from assets/public_gamedevtree_docs_achievements.md.6dd68dae.lean.js
rename to assets/public_gamedevtree_docs_achievements.md.bdb26d53.lean.js
index 39382d347..532e709a5 100644
--- a/assets/public_gamedevtree_docs_achievements.md.6dd68dae.lean.js
+++ b/assets/public_gamedevtree_docs_achievements.md.bdb26d53.lean.js
@@ -1 +1 @@
-import{_ as e,c as a,o as s,a as t}from"./app.a576d425.js";const y=JSON.parse('{"title":"Achievements","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/achievements.md","lastUpdated":null}'),n={name:"public/gamedevtree/docs/achievements.md"},o=t("",9),l=[o];function i(p,r,c,h,d,u){return s(),a("div",null,l)}const v=e(n,[["render",i]]);export{y as __pageData,v as default};
+import{_ as e,c as a,o as s,a as t}from"./app.9bfeb8de.js";const y=JSON.parse('{"title":"Achievements","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/achievements.md","lastUpdated":null}'),n={name:"public/gamedevtree/docs/achievements.md"},o=t("",9),l=[o];function i(p,r,c,h,d,u){return s(),a("div",null,l)}const v=e(n,[["render",i]]);export{y as __pageData,v as default};
diff --git a/assets/public_gamedevtree_docs_bars.md.3acff572.js b/assets/public_gamedevtree_docs_bars.md.d1e4a476.js
similarity index 98%
rename from assets/public_gamedevtree_docs_bars.md.3acff572.js
rename to assets/public_gamedevtree_docs_bars.md.d1e4a476.js
index 3e7235ca0..41b8186e6 100644
--- a/assets/public_gamedevtree_docs_bars.md.3acff572.js
+++ b/assets/public_gamedevtree_docs_bars.md.d1e4a476.js
@@ -1,4 +1,4 @@
-import{_ as s,c as a,o as e,a as t}from"./app.a576d425.js";const b=JSON.parse('{"title":"Bars","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/bars.md","lastUpdated":null}'),n={name:"public/gamedevtree/docs/bars.md"},o=t(`

Bars

Bars let you display information in a more direct way. It can be a progress bar, health bar, capacity gague, or anything else.

Bars are defined like other Big Features:

js
    bars: {
+import{_ as s,c as a,o as e,a as t}from"./app.9bfeb8de.js";const b=JSON.parse('{"title":"Bars","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/bars.md","lastUpdated":null}'),n={name:"public/gamedevtree/docs/bars.md"},o=t(`

Bars

Bars let you display information in a more direct way. It can be a progress bar, health bar, capacity gague, or anything else.

Bars are defined like other Big Features:

js
    bars: {
         bigBar: {
             display() {return "Blah"},
             etc
diff --git a/assets/public_gamedevtree_docs_bars.md.3acff572.lean.js b/assets/public_gamedevtree_docs_bars.md.d1e4a476.lean.js
similarity index 83%
rename from assets/public_gamedevtree_docs_bars.md.3acff572.lean.js
rename to assets/public_gamedevtree_docs_bars.md.d1e4a476.lean.js
index 9f5c23741..c2aa83c6d 100644
--- a/assets/public_gamedevtree_docs_bars.md.3acff572.lean.js
+++ b/assets/public_gamedevtree_docs_bars.md.d1e4a476.lean.js
@@ -1 +1 @@
-import{_ as s,c as a,o as e,a as t}from"./app.a576d425.js";const b=JSON.parse('{"title":"Bars","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/bars.md","lastUpdated":null}'),n={name:"public/gamedevtree/docs/bars.md"},o=t("",6),l=[o];function r(p,i,c,d,u,h){return e(),a("div",null,l)}const F=s(n,[["render",r]]);export{b as __pageData,F as default};
+import{_ as s,c as a,o as e,a as t}from"./app.9bfeb8de.js";const b=JSON.parse('{"title":"Bars","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/bars.md","lastUpdated":null}'),n={name:"public/gamedevtree/docs/bars.md"},o=t("",6),l=[o];function r(p,i,c,d,u,h){return e(),a("div",null,l)}const F=s(n,[["render",r]]);export{b as __pageData,F as default};
diff --git a/assets/public_gamedevtree_docs_basic-layer-breakdown.md.86e5c20b.js b/assets/public_gamedevtree_docs_basic-layer-breakdown.md.2c1c7779.js
similarity index 99%
rename from assets/public_gamedevtree_docs_basic-layer-breakdown.md.86e5c20b.js
rename to assets/public_gamedevtree_docs_basic-layer-breakdown.md.2c1c7779.js
index 6eccdfccd..19d59c519 100644
--- a/assets/public_gamedevtree_docs_basic-layer-breakdown.md.86e5c20b.js
+++ b/assets/public_gamedevtree_docs_basic-layer-breakdown.md.2c1c7779.js
@@ -1,4 +1,4 @@
-import{_ as s,c as n,o as a,a as l}from"./app.a576d425.js";const d=JSON.parse('{"title":"Basic layer breakdown","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/basic-layer-breakdown.md","lastUpdated":null}'),o={name:"public/gamedevtree/docs/basic-layer-breakdown.md"},p=l(`

Basic layer breakdown

This is a very minimal layer with minimal features. Most things will require additional features.

js
    p: {
+import{_ as s,c as n,o as a,a as l}from"./app.9bfeb8de.js";const d=JSON.parse('{"title":"Basic layer breakdown","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/basic-layer-breakdown.md","lastUpdated":null}'),o={name:"public/gamedevtree/docs/basic-layer-breakdown.md"},p=l(`

Basic layer breakdown

This is a very minimal layer with minimal features. Most things will require additional features.

js
    p: {
         startData() { return {                  // startData is a function that returns default data for a layer. 
             unlocked: false,                    // You can add more variables here to add them to your layer.
             points: new Decimal(0),             // "points" is the internal name for the main resource of the layer.
diff --git a/assets/public_gamedevtree_docs_basic-layer-breakdown.md.86e5c20b.lean.js b/assets/public_gamedevtree_docs_basic-layer-breakdown.md.2c1c7779.lean.js
similarity index 85%
rename from assets/public_gamedevtree_docs_basic-layer-breakdown.md.86e5c20b.lean.js
rename to assets/public_gamedevtree_docs_basic-layer-breakdown.md.2c1c7779.lean.js
index d87226fb2..23d6ecee1 100644
--- a/assets/public_gamedevtree_docs_basic-layer-breakdown.md.86e5c20b.lean.js
+++ b/assets/public_gamedevtree_docs_basic-layer-breakdown.md.2c1c7779.lean.js
@@ -1 +1 @@
-import{_ as s,c as n,o as a,a as l}from"./app.a576d425.js";const d=JSON.parse('{"title":"Basic layer breakdown","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/basic-layer-breakdown.md","lastUpdated":null}'),o={name:"public/gamedevtree/docs/basic-layer-breakdown.md"},p=l("",3),e=[p];function r(t,c,F,y,i,D){return a(),n("div",null,e)}const h=s(o,[["render",r]]);export{d as __pageData,h as default};
+import{_ as s,c as n,o as a,a as l}from"./app.9bfeb8de.js";const d=JSON.parse('{"title":"Basic layer breakdown","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/basic-layer-breakdown.md","lastUpdated":null}'),o={name:"public/gamedevtree/docs/basic-layer-breakdown.md"},p=l("",3),e=[p];function r(t,c,F,y,i,D){return a(),n("div",null,e)}const h=s(o,[["render",r]]);export{d as __pageData,h as default};
diff --git a/assets/public_gamedevtree_docs_buyables.md.5db9eaa6.js b/assets/public_gamedevtree_docs_buyables.md.3e42223a.js
similarity index 99%
rename from assets/public_gamedevtree_docs_buyables.md.5db9eaa6.js
rename to assets/public_gamedevtree_docs_buyables.md.3e42223a.js
index 0c5999951..0840e6468 100644
--- a/assets/public_gamedevtree_docs_buyables.md.5db9eaa6.js
+++ b/assets/public_gamedevtree_docs_buyables.md.3e42223a.js
@@ -1,4 +1,4 @@
-import{_ as s,c as e,o as a,a as n}from"./app.a576d425.js";const F=JSON.parse('{"title":"Buyables","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/buyables.md","lastUpdated":null}'),t={name:"public/gamedevtree/docs/buyables.md"},l=n(`

Buyables

Buyables are usually things that can be bought multiple times with scaling costs. If you set a respec function, the player can reset the purchases to get their currency back.

The amount of a buyable owned is a Decimal. You can get or set the amount of a buyable with getBuyableAmt(layer, id) and setBuyableAmt(layer, id, amt). You can use buyableEffect(layer, id) to get the current effects of a buyable.

Buyables should be formatted like this:

js
    buyables: {
+import{_ as s,c as e,o as a,a as n}from"./app.9bfeb8de.js";const F=JSON.parse('{"title":"Buyables","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/buyables.md","lastUpdated":null}'),t={name:"public/gamedevtree/docs/buyables.md"},l=n(`

Buyables

Buyables are usually things that can be bought multiple times with scaling costs. If you set a respec function, the player can reset the purchases to get their currency back.

The amount of a buyable owned is a Decimal. You can get or set the amount of a buyable with getBuyableAmt(layer, id) and setBuyableAmt(layer, id, amt). You can use buyableEffect(layer, id) to get the current effects of a buyable.

Buyables should be formatted like this:

js
    buyables: {
         rows: # of rows
         cols: # of columns
         respec() {}, //**optional**, implement it to reset things and give back your currency.
diff --git a/assets/public_gamedevtree_docs_buyables.md.5db9eaa6.lean.js b/assets/public_gamedevtree_docs_buyables.md.3e42223a.lean.js
similarity index 84%
rename from assets/public_gamedevtree_docs_buyables.md.5db9eaa6.lean.js
rename to assets/public_gamedevtree_docs_buyables.md.3e42223a.lean.js
index 2d48c5049..61545513b 100644
--- a/assets/public_gamedevtree_docs_buyables.md.5db9eaa6.lean.js
+++ b/assets/public_gamedevtree_docs_buyables.md.3e42223a.lean.js
@@ -1 +1 @@
-import{_ as s,c as e,o as a,a as n}from"./app.a576d425.js";const F=JSON.parse('{"title":"Buyables","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/buyables.md","lastUpdated":null}'),t={name:"public/gamedevtree/docs/buyables.md"},l=n("",11),o=[l];function p(r,c,i,u,y,b){return a(),e("div",null,o)}const d=s(t,[["render",p]]);export{F as __pageData,d as default};
+import{_ as s,c as e,o as a,a as n}from"./app.9bfeb8de.js";const F=JSON.parse('{"title":"Buyables","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/buyables.md","lastUpdated":null}'),t={name:"public/gamedevtree/docs/buyables.md"},l=n("",11),o=[l];function p(r,c,i,u,y,b){return a(),e("div",null,o)}const d=s(t,[["render",p]]);export{F as __pageData,d as default};
diff --git a/assets/public_gamedevtree_docs_challenges.md.45577e9f.js b/assets/public_gamedevtree_docs_challenges.md.ba285646.js
similarity index 99%
rename from assets/public_gamedevtree_docs_challenges.md.45577e9f.js
rename to assets/public_gamedevtree_docs_challenges.md.ba285646.js
index 9d75a8c41..ad6a7100c 100644
--- a/assets/public_gamedevtree_docs_challenges.md.45577e9f.js
+++ b/assets/public_gamedevtree_docs_challenges.md.ba285646.js
@@ -1,4 +1,4 @@
-import{_ as e,c as a,o as n,a as s}from"./app.a576d425.js";const d=JSON.parse('{"title":"Challenges","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/challenges.md","lastUpdated":null}'),l={name:"public/gamedevtree/docs/challenges.md"},t=s(`

Challenges

Useful functions for dealing with Challenges and implementing their effects:

  • inChallenge(layer, id): determine if the player is in a given challenge (or another challenge on the same layer that counts as this one)
  • hasChallenge(layer, id): determine if the player has completed the challenge
  • challengeCompletions(layer, id): determine how many times the player completed the challenge
  • challEffect(layer, id): Returns the current effects of the challenge, if any

Challenges are stored in the following format:

js
    challenges: {
+import{_ as e,c as a,o as n,a as s}from"./app.9bfeb8de.js";const d=JSON.parse('{"title":"Challenges","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/challenges.md","lastUpdated":null}'),l={name:"public/gamedevtree/docs/challenges.md"},t=s(`

Challenges

Useful functions for dealing with Challenges and implementing their effects:

  • inChallenge(layer, id): determine if the player is in a given challenge (or another challenge on the same layer that counts as this one)
  • hasChallenge(layer, id): determine if the player has completed the challenge
  • challengeCompletions(layer, id): determine how many times the player completed the challenge
  • challEffect(layer, id): Returns the current effects of the challenge, if any

Challenges are stored in the following format:

js
    challenges: {
         rows: # of rows
         cols: # of columns
         11: {
diff --git a/assets/public_gamedevtree_docs_challenges.md.45577e9f.lean.js b/assets/public_gamedevtree_docs_challenges.md.ba285646.lean.js
similarity index 84%
rename from assets/public_gamedevtree_docs_challenges.md.45577e9f.lean.js
rename to assets/public_gamedevtree_docs_challenges.md.ba285646.lean.js
index 7f8b2f077..8d5a905c0 100644
--- a/assets/public_gamedevtree_docs_challenges.md.45577e9f.lean.js
+++ b/assets/public_gamedevtree_docs_challenges.md.ba285646.lean.js
@@ -1 +1 @@
-import{_ as e,c as a,o as n,a as s}from"./app.a576d425.js";const d=JSON.parse('{"title":"Challenges","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/challenges.md","lastUpdated":null}'),l={name:"public/gamedevtree/docs/challenges.md"},t=s("",9),o=[t];function i(r,c,p,h,u,y){return n(),a("div",null,o)}const f=e(l,[["render",i]]);export{d as __pageData,f as default};
+import{_ as e,c as a,o as n,a as s}from"./app.9bfeb8de.js";const d=JSON.parse('{"title":"Challenges","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/challenges.md","lastUpdated":null}'),l={name:"public/gamedevtree/docs/challenges.md"},t=s("",9),o=[t];function i(r,c,p,h,u,y){return n(),a("div",null,o)}const f=e(l,[["render",i]]);export{d as __pageData,f as default};
diff --git a/assets/public_gamedevtree_docs_clickables.md.e3b0c6fe.js b/assets/public_gamedevtree_docs_clickables.md.a79f34e0.js
similarity index 98%
rename from assets/public_gamedevtree_docs_clickables.md.e3b0c6fe.js
rename to assets/public_gamedevtree_docs_clickables.md.a79f34e0.js
index e60cc4d97..7fec0b81a 100644
--- a/assets/public_gamedevtree_docs_clickables.md.e3b0c6fe.js
+++ b/assets/public_gamedevtree_docs_clickables.md.a79f34e0.js
@@ -1,4 +1,4 @@
-import{_ as s,c as a,o as e,a as n}from"./app.a576d425.js";const d=JSON.parse('{"title":"Clickables","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/clickables.md","lastUpdated":null}'),l={name:"public/gamedevtree/docs/clickables.md"},t=n(`

Clickables

Clickables are any kind of thing that you can click for an effect. They're a more generalized version of Buyables.

DO NOT USE THESE TO MAKE THINGS THAT YOU CLICK REPEATEDLY FOR A BONUS BECAUSE THOSE ARE AWFUL.

There are several differences between the two. One is that a buyable's saved data is its amount as a Decimal, while Clickables store a "state" which can be a number or string, but not Decimal, array, or object). Buyables have a number of extra features which you can see on their page. Clickables also have a smaller default size.

You can get and set a clickable's state with getClickableState(layer, id) and setClickableState(layer, id, state). You can use clickableEffect(layer, id) to get the current effects of a clickable.

Clickables should be formatted like this:

js
    clickables: {
+import{_ as s,c as a,o as e,a as n}from"./app.9bfeb8de.js";const d=JSON.parse('{"title":"Clickables","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/clickables.md","lastUpdated":null}'),l={name:"public/gamedevtree/docs/clickables.md"},t=n(`

Clickables

Clickables are any kind of thing that you can click for an effect. They're a more generalized version of Buyables.

DO NOT USE THESE TO MAKE THINGS THAT YOU CLICK REPEATEDLY FOR A BONUS BECAUSE THOSE ARE AWFUL.

There are several differences between the two. One is that a buyable's saved data is its amount as a Decimal, while Clickables store a "state" which can be a number or string, but not Decimal, array, or object). Buyables have a number of extra features which you can see on their page. Clickables also have a smaller default size.

You can get and set a clickable's state with getClickableState(layer, id) and setClickableState(layer, id, state). You can use clickableEffect(layer, id) to get the current effects of a clickable.

Clickables should be formatted like this:

js
    clickables: {
         rows: # of rows
         cols: # of columns
         masterButtonPress() // **optional** If this is present, an additional button will appear above the clickables.
diff --git a/assets/public_gamedevtree_docs_clickables.md.e3b0c6fe.lean.js b/assets/public_gamedevtree_docs_clickables.md.a79f34e0.lean.js
similarity index 84%
rename from assets/public_gamedevtree_docs_clickables.md.e3b0c6fe.lean.js
rename to assets/public_gamedevtree_docs_clickables.md.a79f34e0.lean.js
index f4ea9f39b..46c229954 100644
--- a/assets/public_gamedevtree_docs_clickables.md.e3b0c6fe.lean.js
+++ b/assets/public_gamedevtree_docs_clickables.md.a79f34e0.lean.js
@@ -1 +1 @@
-import{_ as s,c as a,o as e,a as n}from"./app.a576d425.js";const d=JSON.parse('{"title":"Clickables","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/clickables.md","lastUpdated":null}'),l={name:"public/gamedevtree/docs/clickables.md"},t=n("",9),o=[t];function p(c,r,i,y,u,F){return e(),a("div",null,o)}const b=s(l,[["render",p]]);export{d as __pageData,b as default};
+import{_ as s,c as a,o as e,a as n}from"./app.9bfeb8de.js";const d=JSON.parse('{"title":"Clickables","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/clickables.md","lastUpdated":null}'),l={name:"public/gamedevtree/docs/clickables.md"},t=n("",9),o=[t];function p(c,r,i,y,u,F){return e(),a("div",null,o)}const b=s(l,[["render",p]]);export{d as __pageData,b as default};
diff --git a/assets/public_gamedevtree_docs_custom-tab-layouts.md.1ea1b7b9.js b/assets/public_gamedevtree_docs_custom-tab-layouts.md.3eccc09f.js
similarity index 99%
rename from assets/public_gamedevtree_docs_custom-tab-layouts.md.1ea1b7b9.js
rename to assets/public_gamedevtree_docs_custom-tab-layouts.md.3eccc09f.js
index 421cbd8c1..dfef3c86f 100644
--- a/assets/public_gamedevtree_docs_custom-tab-layouts.md.1ea1b7b9.js
+++ b/assets/public_gamedevtree_docs_custom-tab-layouts.md.3eccc09f.js
@@ -1,4 +1,4 @@
-import{_ as s,c as a,o,a as t}from"./app.a576d425.js";const h=JSON.parse('{"title":"Custom tab layouts","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/custom-tab-layouts.md","lastUpdated":null}'),n={name:"public/gamedevtree/docs/custom-tab-layouts.md"},e=t(`

Custom tab layouts

Note: If you are using subtabs, tabFormat is used differently, but you still use the same format within each subtabs. See here for more on subtabs

Custom tab layouts can be used to do basically anything in a tab window, especially combined with the "style" layer feature. The tabFormat feature is an array of things, like this:

js
    tabFormat: ["main-display",
+import{_ as s,c as a,o,a as t}from"./app.9bfeb8de.js";const h=JSON.parse('{"title":"Custom tab layouts","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/custom-tab-layouts.md","lastUpdated":null}'),n={name:"public/gamedevtree/docs/custom-tab-layouts.md"},e=t(`

Custom tab layouts

Note: If you are using subtabs, tabFormat is used differently, but you still use the same format within each subtabs. See here for more on subtabs

Custom tab layouts can be used to do basically anything in a tab window, especially combined with the "style" layer feature. The tabFormat feature is an array of things, like this:

js
    tabFormat: ["main-display",
             ["prestige-button", function(){return "Melt your points into "}],
             "blank",
             ["display-text",
diff --git a/assets/public_gamedevtree_docs_custom-tab-layouts.md.1ea1b7b9.lean.js b/assets/public_gamedevtree_docs_custom-tab-layouts.md.3eccc09f.lean.js
similarity index 84%
rename from assets/public_gamedevtree_docs_custom-tab-layouts.md.1ea1b7b9.lean.js
rename to assets/public_gamedevtree_docs_custom-tab-layouts.md.3eccc09f.lean.js
index 7597ffaf8..d52edeb52 100644
--- a/assets/public_gamedevtree_docs_custom-tab-layouts.md.1ea1b7b9.lean.js
+++ b/assets/public_gamedevtree_docs_custom-tab-layouts.md.3eccc09f.lean.js
@@ -1 +1 @@
-import{_ as s,c as a,o,a as t}from"./app.a576d425.js";const h=JSON.parse('{"title":"Custom tab layouts","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/custom-tab-layouts.md","lastUpdated":null}'),n={name:"public/gamedevtree/docs/custom-tab-layouts.md"},e=t("",9),l=[e];function p(r,c,i,y,D,u){return o(),a("div",null,l)}const b=s(n,[["render",p]]);export{h as __pageData,b as default};
+import{_ as s,c as a,o,a as t}from"./app.9bfeb8de.js";const h=JSON.parse('{"title":"Custom tab layouts","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/custom-tab-layouts.md","lastUpdated":null}'),n={name:"public/gamedevtree/docs/custom-tab-layouts.md"},e=t("",9),l=[e];function p(r,c,i,y,D,u){return o(),a("div",null,l)}const b=s(n,[["render",p]]);export{h as __pageData,b as default};
diff --git a/assets/public_gamedevtree_docs_getting-started.md.bb68ff20.js b/assets/public_gamedevtree_docs_getting-started.md.6c2239cf.js
similarity index 98%
rename from assets/public_gamedevtree_docs_getting-started.md.bb68ff20.js
rename to assets/public_gamedevtree_docs_getting-started.md.6c2239cf.js
index f79481351..9688c3afd 100644
--- a/assets/public_gamedevtree_docs_getting-started.md.bb68ff20.js
+++ b/assets/public_gamedevtree_docs_getting-started.md.6c2239cf.js
@@ -1 +1 @@
-import{_ as e,c as t,o,a as i}from"./app.a576d425.js";const y=JSON.parse('{"title":"Getting started","description":"","frontmatter":{},"headers":[{"level":2,"title":"Getting set up with Github and The Modding Tree:","slug":"getting-set-up-with-github-and-the-modding-tree","link":"#getting-set-up-with-github-and-the-modding-tree","children":[]},{"level":2,"title":"Using your repository","slug":"using-your-repository","link":"#using-your-repository","children":[]}],"relativePath":"public/gamedevtree/docs/getting-started.md","lastUpdated":null}'),a={name:"public/gamedevtree/docs/getting-started.md"},n=i('

Getting started

Welcome to The Modding Tree!

Using the Modding Tree, at its simplest level, just requires getting a copy of it onto your computer. However, if you do it the right way, it will help in many ways.

Don't let the word "Github" scare you away. It's actually much easier to use than most people think, especially because most people use it the hard way. The key is Github Desktop, which lets you do everything you need to, without even touching the command line.

The benefits of using Github:

  • It makes it much, much easier to update The Modding Tree.
  • You can share your work without any extra effort using githack, or with a bit more effort, set up a github.io site.
  • It lets you undo changes to your code, and to have multiple versions of it.
  • It lets you collaborate with other people, if you want to.

Getting set up with Github and The Modding Tree:

  1. Install Github Desktop and Visual Studio Code.

  2. Make a Github account. You can handle this on your own.

  3. Log in on your browser, and go back to The Modding Tree page. At the top right, there should be a button that says "fork". Click on it, and then on your username. You now have your own fork, or copy, of The Modding Tree.

  4. Open Github Desktop and log in. Ignore everything else and choose "clone a repository". A "repository" is basically a "Github project", like The Modding Tree. "Cloning" is downloading a copy of the repository to your computer.

  5. Look for The Modding Tree in the list of repositiories (it should be the only one) and click "clone".

  6. Select that you're using it for your own purposes, and click continue. It will download the files and handle everything.

Using your repository

  1. Click on "show in finder" to the right, and then open index.html. This will let you view and test your project!

  2. To edit your project, click "open in VSCode" in Github Desktop.

  3. Open mod.js in VSCode, and look at the top part where it says "modInfo". On the lines below that, change the mod's name to whatever you want, and change the id as well. (It can be any string value, and it's used to determine where the savefile is. Make it something that's probably unique, and don't change it again later.)

  4. Save game.js, and then reload index.html. The title on the tab, as well as on the info page, will now be the new ones!

  5. Go back to Github Desktop. It's time to save your changes into the git system by making a "commit".

  6. At the bottom right corner, add a summary of your changes, and then click "commit to master".

  7. Finally, at the top middle, click "push origin" to push your changes out onto the online repository.

  8. You can view your project on line, or share it with others, by going to https://raw.githack.com/[YOUR-GITHUB-USERNAME]/The-Modding-Tree/master/index.html

And now, you have successfully used Github! You can look at the documentation to see how The Modding Tree's system works and to make your mod a reality.

',11),r=[n];function h(s,l,u,d,p,g){return o(),t("div",null,r)}const m=e(a,[["render",h]]);export{y as __pageData,m as default}; +import{_ as e,c as t,o,a as i}from"./app.9bfeb8de.js";const y=JSON.parse('{"title":"Getting started","description":"","frontmatter":{},"headers":[{"level":2,"title":"Getting set up with Github and The Modding Tree:","slug":"getting-set-up-with-github-and-the-modding-tree","link":"#getting-set-up-with-github-and-the-modding-tree","children":[]},{"level":2,"title":"Using your repository","slug":"using-your-repository","link":"#using-your-repository","children":[]}],"relativePath":"public/gamedevtree/docs/getting-started.md","lastUpdated":null}'),a={name:"public/gamedevtree/docs/getting-started.md"},n=i('

Getting started

Welcome to The Modding Tree!

Using the Modding Tree, at its simplest level, just requires getting a copy of it onto your computer. However, if you do it the right way, it will help in many ways.

Don't let the word "Github" scare you away. It's actually much easier to use than most people think, especially because most people use it the hard way. The key is Github Desktop, which lets you do everything you need to, without even touching the command line.

The benefits of using Github:

  • It makes it much, much easier to update The Modding Tree.
  • You can share your work without any extra effort using githack, or with a bit more effort, set up a github.io site.
  • It lets you undo changes to your code, and to have multiple versions of it.
  • It lets you collaborate with other people, if you want to.

Getting set up with Github and The Modding Tree:

  1. Install Github Desktop and Visual Studio Code.

  2. Make a Github account. You can handle this on your own.

  3. Log in on your browser, and go back to The Modding Tree page. At the top right, there should be a button that says "fork". Click on it, and then on your username. You now have your own fork, or copy, of The Modding Tree.

  4. Open Github Desktop and log in. Ignore everything else and choose "clone a repository". A "repository" is basically a "Github project", like The Modding Tree. "Cloning" is downloading a copy of the repository to your computer.

  5. Look for The Modding Tree in the list of repositiories (it should be the only one) and click "clone".

  6. Select that you're using it for your own purposes, and click continue. It will download the files and handle everything.

Using your repository

  1. Click on "show in finder" to the right, and then open index.html. This will let you view and test your project!

  2. To edit your project, click "open in VSCode" in Github Desktop.

  3. Open mod.js in VSCode, and look at the top part where it says "modInfo". On the lines below that, change the mod's name to whatever you want, and change the id as well. (It can be any string value, and it's used to determine where the savefile is. Make it something that's probably unique, and don't change it again later.)

  4. Save game.js, and then reload index.html. The title on the tab, as well as on the info page, will now be the new ones!

  5. Go back to Github Desktop. It's time to save your changes into the git system by making a "commit".

  6. At the bottom right corner, add a summary of your changes, and then click "commit to master".

  7. Finally, at the top middle, click "push origin" to push your changes out onto the online repository.

  8. You can view your project on line, or share it with others, by going to https://raw.githack.com/[YOUR-GITHUB-USERNAME]/The-Modding-Tree/master/index.html

And now, you have successfully used Github! You can look at the documentation to see how The Modding Tree's system works and to make your mod a reality.

',11),r=[n];function h(s,l,u,d,p,g){return o(),t("div",null,r)}const m=e(a,[["render",h]]);export{y as __pageData,m as default}; diff --git a/assets/public_gamedevtree_docs_getting-started.md.bb68ff20.lean.js b/assets/public_gamedevtree_docs_getting-started.md.6c2239cf.lean.js similarity index 91% rename from assets/public_gamedevtree_docs_getting-started.md.bb68ff20.lean.js rename to assets/public_gamedevtree_docs_getting-started.md.6c2239cf.lean.js index cbb689682..962e72887 100644 --- a/assets/public_gamedevtree_docs_getting-started.md.bb68ff20.lean.js +++ b/assets/public_gamedevtree_docs_getting-started.md.6c2239cf.lean.js @@ -1 +1 @@ -import{_ as e,c as t,o,a as i}from"./app.a576d425.js";const y=JSON.parse('{"title":"Getting started","description":"","frontmatter":{},"headers":[{"level":2,"title":"Getting set up with Github and The Modding Tree:","slug":"getting-set-up-with-github-and-the-modding-tree","link":"#getting-set-up-with-github-and-the-modding-tree","children":[]},{"level":2,"title":"Using your repository","slug":"using-your-repository","link":"#using-your-repository","children":[]}],"relativePath":"public/gamedevtree/docs/getting-started.md","lastUpdated":null}'),a={name:"public/gamedevtree/docs/getting-started.md"},n=i("",11),r=[n];function h(s,l,u,d,p,g){return o(),t("div",null,r)}const m=e(a,[["render",h]]);export{y as __pageData,m as default}; +import{_ as e,c as t,o,a as i}from"./app.9bfeb8de.js";const y=JSON.parse('{"title":"Getting started","description":"","frontmatter":{},"headers":[{"level":2,"title":"Getting set up with Github and The Modding Tree:","slug":"getting-set-up-with-github-and-the-modding-tree","link":"#getting-set-up-with-github-and-the-modding-tree","children":[]},{"level":2,"title":"Using your repository","slug":"using-your-repository","link":"#using-your-repository","children":[]}],"relativePath":"public/gamedevtree/docs/getting-started.md","lastUpdated":null}'),a={name:"public/gamedevtree/docs/getting-started.md"},n=i("",11),r=[n];function h(s,l,u,d,p,g){return o(),t("div",null,r)}const m=e(a,[["render",h]]);export{y as __pageData,m as default}; diff --git a/assets/public_gamedevtree_docs_infoboxes.md.ef434fbf.js b/assets/public_gamedevtree_docs_infoboxes.md.0e07c96e.js similarity index 98% rename from assets/public_gamedevtree_docs_infoboxes.md.ef434fbf.js rename to assets/public_gamedevtree_docs_infoboxes.md.0e07c96e.js index 625b54025..04bf71818 100644 --- a/assets/public_gamedevtree_docs_infoboxes.md.ef434fbf.js +++ b/assets/public_gamedevtree_docs_infoboxes.md.0e07c96e.js @@ -1,4 +1,4 @@ -import{_ as s,c as e,o as a,a as o}from"./app.a576d425.js";const h=JSON.parse('{"title":"Infoboxes","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/infoboxes.md","lastUpdated":null}'),n={name:"public/gamedevtree/docs/infoboxes.md"},t=o(`

Infoboxes

Infoboxes are good for displaying "lore", or story elements, as well as for explaining complicated things.

In the default tab layout, the first infobox will be displayed at the very top of the tab.

Infoboxes are defined like other Big Features:

js
    infoboxes: {
+import{_ as s,c as e,o as a,a as o}from"./app.9bfeb8de.js";const h=JSON.parse('{"title":"Infoboxes","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/infoboxes.md","lastUpdated":null}'),n={name:"public/gamedevtree/docs/infoboxes.md"},t=o(`

Infoboxes

Infoboxes are good for displaying "lore", or story elements, as well as for explaining complicated things.

In the default tab layout, the first infobox will be displayed at the very top of the tab.

Infoboxes are defined like other Big Features:

js
    infoboxes: {
         infobox: {
             display() {return "Blah"},
             etc
diff --git a/assets/public_gamedevtree_docs_infoboxes.md.ef434fbf.lean.js b/assets/public_gamedevtree_docs_infoboxes.md.0e07c96e.lean.js
similarity index 84%
rename from assets/public_gamedevtree_docs_infoboxes.md.ef434fbf.lean.js
rename to assets/public_gamedevtree_docs_infoboxes.md.0e07c96e.lean.js
index ef2e17a68..99cb038f1 100644
--- a/assets/public_gamedevtree_docs_infoboxes.md.ef434fbf.lean.js
+++ b/assets/public_gamedevtree_docs_infoboxes.md.0e07c96e.lean.js
@@ -1 +1 @@
-import{_ as s,c as e,o as a,a as o}from"./app.a576d425.js";const h=JSON.parse('{"title":"Infoboxes","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/infoboxes.md","lastUpdated":null}'),n={name:"public/gamedevtree/docs/infoboxes.md"},t=o("",7),l=[t];function p(i,r,c,d,y,u){return a(),e("div",null,l)}const f=s(n,[["render",p]]);export{h as __pageData,f as default};
+import{_ as s,c as e,o as a,a as o}from"./app.9bfeb8de.js";const h=JSON.parse('{"title":"Infoboxes","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/infoboxes.md","lastUpdated":null}'),n={name:"public/gamedevtree/docs/infoboxes.md"},t=o("",7),l=[t];function p(i,r,c,d,y,u){return a(),e("div",null,l)}const f=s(n,[["render",p]]);export{h as __pageData,f as default};
diff --git a/assets/public_gamedevtree_docs_layer-features.md.4567b331.js b/assets/public_gamedevtree_docs_layer-features.md.9c5507fe.js
similarity index 99%
rename from assets/public_gamedevtree_docs_layer-features.md.4567b331.js
rename to assets/public_gamedevtree_docs_layer-features.md.9c5507fe.js
index aad9f82cf..53d15f46f 100644
--- a/assets/public_gamedevtree_docs_layer-features.md.4567b331.js
+++ b/assets/public_gamedevtree_docs_layer-features.md.9c5507fe.js
@@ -1,4 +1,4 @@
-import{_ as e,c as t,o as a,a as s}from"./app.a576d425.js";const f=JSON.parse('{"title":"Layer Features","description":"","frontmatter":{},"headers":[{"level":2,"title":"Layer Definition features","slug":"layer-definition-features","link":"#layer-definition-features","children":[]},{"level":2,"title":"Big features (all optional)","slug":"big-features-all-optional","link":"#big-features-all-optional","children":[]},{"level":2,"title":"Prestige formula features","slug":"prestige-formula-features","link":"#prestige-formula-features","children":[]},{"level":2,"title":"Tree/node features","slug":"tree-node-features","link":"#tree-node-features","children":[]},{"level":2,"title":"Other features","slug":"other-features","link":"#other-features","children":[]},{"level":2,"title":"Custom Prestige type","slug":"custom-prestige-type","link":"#custom-prestige-type","children":[]}],"relativePath":"public/gamedevtree/docs/layer-features.md","lastUpdated":null}'),o={name:"public/gamedevtree/docs/layer-features.md"},n=s(`

Layer Features

This is a more comprehensive list of established features to add to layers. You can add more freely, if you want to have other functions or values associated with your layer. These have special functionality, though.

You can make almost any value dynamic by using a function in its place, including all display strings and styling/color features.

Key:

  • No label: This is required and the game will crash if it isn't included.
  • sometimes required: This is may be required, depending on other things in the layer.
  • optional: You can leave this out if you don't intend to use that feature for the layer.

Layer Definition features

  • layer: Assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar to access the save value. It makes copying code to new layers easier. It is also assigned to all upgrades and buyables and such.

  • name: Optional, used in reset confirmations (and maybe other places). If absent, it just uses the layer's id.

  • startData(): A function to return the default save data for this layer. Add any variables you have to it. Any nonstandard Decimal variables need to be added to convertToDecimal as well. Standard values: Required: unlocked: a bool determining if this layer is unlocked or not points: a Decimal, the main currency for the layer Optional: total: A Decimal, tracks total amount of main prestige currency best: A Decimal, tracks highest amount of main prestige currency unlockOrder: used to keep track of relevant layers unlocked before this one.

  • color: A color associated with this layer, used in many places. (A string in hex format with a #)

  • row: The row of the layer, starting at 0. This affects where the node appears on the tree, and which resets affect the layer.

     Using "side" instead of a number will cause the layer to appear off to the side as a smaller node (useful for achievements
    +import{_ as e,c as t,o as a,a as s}from"./app.9bfeb8de.js";const f=JSON.parse('{"title":"Layer Features","description":"","frontmatter":{},"headers":[{"level":2,"title":"Layer Definition features","slug":"layer-definition-features","link":"#layer-definition-features","children":[]},{"level":2,"title":"Big features (all optional)","slug":"big-features-all-optional","link":"#big-features-all-optional","children":[]},{"level":2,"title":"Prestige formula features","slug":"prestige-formula-features","link":"#prestige-formula-features","children":[]},{"level":2,"title":"Tree/node features","slug":"tree-node-features","link":"#tree-node-features","children":[]},{"level":2,"title":"Other features","slug":"other-features","link":"#other-features","children":[]},{"level":2,"title":"Custom Prestige type","slug":"custom-prestige-type","link":"#custom-prestige-type","children":[]}],"relativePath":"public/gamedevtree/docs/layer-features.md","lastUpdated":null}'),o={name:"public/gamedevtree/docs/layer-features.md"},n=s(`

    Layer Features

    This is a more comprehensive list of established features to add to layers. You can add more freely, if you want to have other functions or values associated with your layer. These have special functionality, though.

    You can make almost any value dynamic by using a function in its place, including all display strings and styling/color features.

    Key:

    • No label: This is required and the game will crash if it isn't included.
    • sometimes required: This is may be required, depending on other things in the layer.
    • optional: You can leave this out if you don't intend to use that feature for the layer.

    Layer Definition features

    • layer: Assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar to access the save value. It makes copying code to new layers easier. It is also assigned to all upgrades and buyables and such.

    • name: Optional, used in reset confirmations (and maybe other places). If absent, it just uses the layer's id.

    • startData(): A function to return the default save data for this layer. Add any variables you have to it. Any nonstandard Decimal variables need to be added to convertToDecimal as well. Standard values: Required: unlocked: a bool determining if this layer is unlocked or not points: a Decimal, the main currency for the layer Optional: total: A Decimal, tracks total amount of main prestige currency best: A Decimal, tracks highest amount of main prestige currency unlockOrder: used to keep track of relevant layers unlocked before this one.

    • color: A color associated with this layer, used in many places. (A string in hex format with a #)

    • row: The row of the layer, starting at 0. This affects where the node appears on the tree, and which resets affect the layer.

       Using "side" instead of a number will cause the layer to appear off to the side as a smaller node (useful for achievements
        and statistics). Side layers are not affected by resets unless you add a doReset to them.
       
    • resource: Name of the main currency you gain by resetting on this layer.

    • effect(): optional, A function that calculates and returns the current values of any bonuses inherent to the main currency. Can return a value or an object containing multiple values. You will also have to implement the effect where it is applied.

    • effectDescription: optional, A function that returns a description of this effect. If the text stays constant, it can just be a string.

    • layerShown(): A function returning a bool which determines if this layer's node should be visible on the tree. It can also return "ghost", which will hide the layer, but its node will still take up space in the tree.

    • hotkeys: optional, An array containing information on any hotkeys associated with this layer:

      js
      hotkeys: [
           {key: "p", // What the hotkey button is. Use uppercase if it's combined with shift, or "ctrl+x" if ctrl is.
      diff --git a/assets/public_gamedevtree_docs_layer-features.md.4567b331.lean.js b/assets/public_gamedevtree_docs_layer-features.md.9c5507fe.lean.js
      similarity index 94%
      rename from assets/public_gamedevtree_docs_layer-features.md.4567b331.lean.js
      rename to assets/public_gamedevtree_docs_layer-features.md.9c5507fe.lean.js
      index d619dee30..80bc9368c 100644
      --- a/assets/public_gamedevtree_docs_layer-features.md.4567b331.lean.js
      +++ b/assets/public_gamedevtree_docs_layer-features.md.9c5507fe.lean.js
      @@ -1 +1 @@
      -import{_ as e,c as t,o as a,a as s}from"./app.a576d425.js";const f=JSON.parse('{"title":"Layer Features","description":"","frontmatter":{},"headers":[{"level":2,"title":"Layer Definition features","slug":"layer-definition-features","link":"#layer-definition-features","children":[]},{"level":2,"title":"Big features (all optional)","slug":"big-features-all-optional","link":"#big-features-all-optional","children":[]},{"level":2,"title":"Prestige formula features","slug":"prestige-formula-features","link":"#prestige-formula-features","children":[]},{"level":2,"title":"Tree/node features","slug":"tree-node-features","link":"#tree-node-features","children":[]},{"level":2,"title":"Other features","slug":"other-features","link":"#other-features","children":[]},{"level":2,"title":"Custom Prestige type","slug":"custom-prestige-type","link":"#custom-prestige-type","children":[]}],"relativePath":"public/gamedevtree/docs/layer-features.md","lastUpdated":null}'),o={name:"public/gamedevtree/docs/layer-features.md"},n=s("",18),r=[n];function l(i,p,c,u,h,y){return a(),t("div",null,r)}const g=e(o,[["render",l]]);export{f as __pageData,g as default};
      +import{_ as e,c as t,o as a,a as s}from"./app.9bfeb8de.js";const f=JSON.parse('{"title":"Layer Features","description":"","frontmatter":{},"headers":[{"level":2,"title":"Layer Definition features","slug":"layer-definition-features","link":"#layer-definition-features","children":[]},{"level":2,"title":"Big features (all optional)","slug":"big-features-all-optional","link":"#big-features-all-optional","children":[]},{"level":2,"title":"Prestige formula features","slug":"prestige-formula-features","link":"#prestige-formula-features","children":[]},{"level":2,"title":"Tree/node features","slug":"tree-node-features","link":"#tree-node-features","children":[]},{"level":2,"title":"Other features","slug":"other-features","link":"#other-features","children":[]},{"level":2,"title":"Custom Prestige type","slug":"custom-prestige-type","link":"#custom-prestige-type","children":[]}],"relativePath":"public/gamedevtree/docs/layer-features.md","lastUpdated":null}'),o={name:"public/gamedevtree/docs/layer-features.md"},n=s("",18),r=[n];function l(i,p,c,u,h,y){return a(),t("div",null,r)}const g=e(o,[["render",l]]);export{f as __pageData,g as default};
      diff --git a/assets/public_gamedevtree_docs_main-mod-info.md.4b087535.js b/assets/public_gamedevtree_docs_main-mod-info.md.166d6aee.js
      similarity index 99%
      rename from assets/public_gamedevtree_docs_main-mod-info.md.4b087535.js
      rename to assets/public_gamedevtree_docs_main-mod-info.md.166d6aee.js
      index d7009e5d2..e6a18064a 100644
      --- a/assets/public_gamedevtree_docs_main-mod-info.md.4b087535.js
      +++ b/assets/public_gamedevtree_docs_main-mod-info.md.166d6aee.js
      @@ -1,4 +1,4 @@
      -import{_ as e,c as s,o as a,a as n}from"./app.a576d425.js";const f=JSON.parse('{"title":"mod.js","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/main-mod-info.md","lastUpdated":null}'),t={name:"public/gamedevtree/docs/main-mod-info.md"},o=n(`

      mod.js

      All of the code and data that you're likely to edit is here in mod.js! Everything in mod.js will not be altered by updates, besides the addition of new things.

      Here's a breakdown of what's in it:

      • modInfo is where most of the basic configuration for the mod is. It contains:

        • name: The name of your mod. (a string)
        • id: The id for your mod, a unique string that is used to determine savefile location. Setting it is important!
        • author: The name of the author, displayed in the info tab.
        • pointsName: This changes what is displayed instead of "points" for the main currency. (It does not affect it in the code.)
        • discordName, discordLink: If you have a Discord server or other discussion place, you can add a link to it. "discordName" is the text on the link, and "discordLink" is the url of an invite. If you're using a Discord invite, please make sure it's set to never expire.
        • changelogLink: You can use this to set a link to a page where your changelog for the game is displayed.
        • offlineLimit: The maximum amount of offline time that the player can accumulate, in hours. Any extra time is lost. (a number) This is useful because most of these mods are fast-paced enough that too much offline time ruins the balance, such as the time in between updates. That is why I suggest developers disable offline time on their own savefile.
        • initialStartPoints: A Decimal for the amount of points a new player should start with.
      • VERSION is used to describe the current version of your mod. It contains: num: The mod's version number, displayed at the top right of the tree tab. name: The version's name, displayed alongside the number in the info tab.

      • doNotCallTheseFunctionsEveryTick is very important. TMT calls every function anywhere in "layers" every tick to store the result, unless specifically told not to. Functions that have are used to do an action need to be identified. "Official" functions (those in the documentation) are all fine, but if you make any new ones, add their names to this array.

      js
      // (The ones here are examples, all official functions are already taken care of)
      +import{_ as e,c as s,o as a,a as n}from"./app.9bfeb8de.js";const f=JSON.parse('{"title":"mod.js","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/main-mod-info.md","lastUpdated":null}'),t={name:"public/gamedevtree/docs/main-mod-info.md"},o=n(`

      mod.js

      All of the code and data that you're likely to edit is here in mod.js! Everything in mod.js will not be altered by updates, besides the addition of new things.

      Here's a breakdown of what's in it:

      • modInfo is where most of the basic configuration for the mod is. It contains:

        • name: The name of your mod. (a string)
        • id: The id for your mod, a unique string that is used to determine savefile location. Setting it is important!
        • author: The name of the author, displayed in the info tab.
        • pointsName: This changes what is displayed instead of "points" for the main currency. (It does not affect it in the code.)
        • discordName, discordLink: If you have a Discord server or other discussion place, you can add a link to it. "discordName" is the text on the link, and "discordLink" is the url of an invite. If you're using a Discord invite, please make sure it's set to never expire.
        • changelogLink: You can use this to set a link to a page where your changelog for the game is displayed.
        • offlineLimit: The maximum amount of offline time that the player can accumulate, in hours. Any extra time is lost. (a number) This is useful because most of these mods are fast-paced enough that too much offline time ruins the balance, such as the time in between updates. That is why I suggest developers disable offline time on their own savefile.
        • initialStartPoints: A Decimal for the amount of points a new player should start with.
      • VERSION is used to describe the current version of your mod. It contains: num: The mod's version number, displayed at the top right of the tree tab. name: The version's name, displayed alongside the number in the info tab.

      • doNotCallTheseFunctionsEveryTick is very important. TMT calls every function anywhere in "layers" every tick to store the result, unless specifically told not to. Functions that have are used to do an action need to be identified. "Official" functions (those in the documentation) are all fine, but if you make any new ones, add their names to this array.

      js
      // (The ones here are examples, all official functions are already taken care of)
       var doNotCallTheseFunctionsEveryTick = ["doReset", "buy", "onPurchase", "blowUpEverything"]
       
      • getStartPoints(): A function to determine the amount of points the player starts with after a reset. (returns a Decimal value)

      • canGenPoints(): A function returning a boolean for if points should be generated. Use this if you want an upgrade to unlock generating points.

      • getPointGen(): A function that calculates your points per second. Anything that affects your point gain should go into the calculation here.

      • addedPlayerData(): A function that returns any non-layer-related data that you want to be added to the save data and "player" object.

      js
      function addedPlayerData() { return {
       	weather: "Yes",
      diff --git a/assets/public_gamedevtree_docs_main-mod-info.md.4b087535.lean.js b/assets/public_gamedevtree_docs_main-mod-info.md.166d6aee.lean.js
      similarity index 84%
      rename from assets/public_gamedevtree_docs_main-mod-info.md.4b087535.lean.js
      rename to assets/public_gamedevtree_docs_main-mod-info.md.166d6aee.lean.js
      index 8e058b8cf..8f862398e 100644
      --- a/assets/public_gamedevtree_docs_main-mod-info.md.4b087535.lean.js
      +++ b/assets/public_gamedevtree_docs_main-mod-info.md.166d6aee.lean.js
      @@ -1 +1 @@
      -import{_ as e,c as s,o as a,a as n}from"./app.a576d425.js";const f=JSON.parse('{"title":"mod.js","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/main-mod-info.md","lastUpdated":null}'),t={name:"public/gamedevtree/docs/main-mod-info.md"},o=n("",10),l=[o];function i(p,r,c,u,d,h){return a(),s("div",null,l)}const m=e(t,[["render",i]]);export{f as __pageData,m as default};
      +import{_ as e,c as s,o as a,a as n}from"./app.9bfeb8de.js";const f=JSON.parse('{"title":"mod.js","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/main-mod-info.md","lastUpdated":null}'),t={name:"public/gamedevtree/docs/main-mod-info.md"},o=n("",10),l=[o];function i(p,r,c,u,d,h){return a(),s("div",null,l)}const m=e(t,[["render",i]]);export{f as __pageData,m as default};
      diff --git a/assets/public_gamedevtree_docs_milestones.md.7d661bce.js b/assets/public_gamedevtree_docs_milestones.md.c8e0174f.js
      similarity index 98%
      rename from assets/public_gamedevtree_docs_milestones.md.7d661bce.js
      rename to assets/public_gamedevtree_docs_milestones.md.c8e0174f.js
      index beb3117d0..7b89559bb 100644
      --- a/assets/public_gamedevtree_docs_milestones.md.7d661bce.js
      +++ b/assets/public_gamedevtree_docs_milestones.md.c8e0174f.js
      @@ -1,4 +1,4 @@
      -import{_ as e,c as s,o as t,a as n}from"./app.a576d425.js";const m=JSON.parse('{"title":"Milestones","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/milestones.md","lastUpdated":null}'),a={name:"public/gamedevtree/docs/milestones.md"},o=n(`

      Milestones

      Milestones are awarded to the player when they meet a certain goal, and give some benefit. Milestones should be formatted like this:

      js
          milestones: {
      +import{_ as e,c as s,o as t,a as n}from"./app.9bfeb8de.js";const m=JSON.parse('{"title":"Milestones","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/milestones.md","lastUpdated":null}'),a={name:"public/gamedevtree/docs/milestones.md"},o=n(`

      Milestones

      Milestones are awarded to the player when they meet a certain goal, and give some benefit. Milestones should be formatted like this:

      js
          milestones: {
               0: {
                   requirementDesc: "123 waffles",
               }
      diff --git a/assets/public_gamedevtree_docs_milestones.md.7d661bce.lean.js b/assets/public_gamedevtree_docs_milestones.md.c8e0174f.lean.js
      similarity index 84%
      rename from assets/public_gamedevtree_docs_milestones.md.7d661bce.lean.js
      rename to assets/public_gamedevtree_docs_milestones.md.c8e0174f.lean.js
      index 17f11da76..4d1554f04 100644
      --- a/assets/public_gamedevtree_docs_milestones.md.7d661bce.lean.js
      +++ b/assets/public_gamedevtree_docs_milestones.md.c8e0174f.lean.js
      @@ -1 +1 @@
      -import{_ as e,c as s,o as t,a as n}from"./app.a576d425.js";const m=JSON.parse('{"title":"Milestones","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/milestones.md","lastUpdated":null}'),a={name:"public/gamedevtree/docs/milestones.md"},o=n("",6),l=[o];function i(r,p,c,h,u,d){return t(),s("div",null,l)}const y=e(a,[["render",i]]);export{m as __pageData,y as default};
      +import{_ as e,c as s,o as t,a as n}from"./app.9bfeb8de.js";const m=JSON.parse('{"title":"Milestones","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/milestones.md","lastUpdated":null}'),a={name:"public/gamedevtree/docs/milestones.md"},o=n("",6),l=[o];function i(r,p,c,h,u,d){return t(),s("div",null,l)}const y=e(a,[["render",i]]);export{m as __pageData,y as default};
      diff --git a/assets/public_gamedevtree_docs_subtabs-and-microtabs.md.60a1852e.js b/assets/public_gamedevtree_docs_subtabs-and-microtabs.md.1d829b17.js
      similarity index 98%
      rename from assets/public_gamedevtree_docs_subtabs-and-microtabs.md.60a1852e.js
      rename to assets/public_gamedevtree_docs_subtabs-and-microtabs.md.1d829b17.js
      index 2fe55d0ea..0a69a7b00 100644
      --- a/assets/public_gamedevtree_docs_subtabs-and-microtabs.md.60a1852e.js
      +++ b/assets/public_gamedevtree_docs_subtabs-and-microtabs.md.1d829b17.js
      @@ -1,4 +1,4 @@
      -import{_ as s,c as a,o as n,a as t}from"./app.a576d425.js";const D=JSON.parse('{"title":"Subtabs and Microtabs","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/subtabs-and-microtabs.md","lastUpdated":null}'),e={name:"public/gamedevtree/docs/subtabs-and-microtabs.md"},o=t(`

      Subtabs and Microtabs

      Subtabs are separate sections of a tab that you can view by selecting one at the top of the tab. Microtabs are smaller areas that function in much the same way.

      Subtabs are defined by using the tab format like this, where each element of tabFormat is given the name of that subtab:

      js
          tabFormat: {
      +import{_ as s,c as a,o as n,a as t}from"./app.9bfeb8de.js";const D=JSON.parse('{"title":"Subtabs and Microtabs","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/subtabs-and-microtabs.md","lastUpdated":null}'),e={name:"public/gamedevtree/docs/subtabs-and-microtabs.md"},o=t(`

      Subtabs and Microtabs

      Subtabs are separate sections of a tab that you can view by selecting one at the top of the tab. Microtabs are smaller areas that function in much the same way.

      Subtabs are defined by using the tab format like this, where each element of tabFormat is given the name of that subtab:

      js
          tabFormat: {
               "Main tab": {
                   *subtab features*
               },
      diff --git a/assets/public_gamedevtree_docs_subtabs-and-microtabs.md.60a1852e.lean.js b/assets/public_gamedevtree_docs_subtabs-and-microtabs.md.1d829b17.lean.js
      similarity index 85%
      rename from assets/public_gamedevtree_docs_subtabs-and-microtabs.md.60a1852e.lean.js
      rename to assets/public_gamedevtree_docs_subtabs-and-microtabs.md.1d829b17.lean.js
      index 1ad5f8059..9a4925555 100644
      --- a/assets/public_gamedevtree_docs_subtabs-and-microtabs.md.60a1852e.lean.js
      +++ b/assets/public_gamedevtree_docs_subtabs-and-microtabs.md.1d829b17.lean.js
      @@ -1 +1 @@
      -import{_ as s,c as a,o as n,a as t}from"./app.a576d425.js";const D=JSON.parse('{"title":"Subtabs and Microtabs","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/subtabs-and-microtabs.md","lastUpdated":null}'),e={name:"public/gamedevtree/docs/subtabs-and-microtabs.md"},o=t("",9),l=[o];function p(c,r,i,F,u,y){return n(),a("div",null,l)}const h=s(e,[["render",p]]);export{D as __pageData,h as default};
      +import{_ as s,c as a,o as n,a as t}from"./app.9bfeb8de.js";const D=JSON.parse('{"title":"Subtabs and Microtabs","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/subtabs-and-microtabs.md","lastUpdated":null}'),e={name:"public/gamedevtree/docs/subtabs-and-microtabs.md"},o=t("",9),l=[o];function p(c,r,i,F,u,y){return n(),a("div",null,l)}const h=s(e,[["render",p]]);export{D as __pageData,h as default};
      diff --git a/assets/public_gamedevtree_docs_updating-tmt.md.f6459ce1.js b/assets/public_gamedevtree_docs_updating-tmt.md.cde46630.js
      similarity index 96%
      rename from assets/public_gamedevtree_docs_updating-tmt.md.f6459ce1.js
      rename to assets/public_gamedevtree_docs_updating-tmt.md.cde46630.js
      index 98f98378e..1616e8899 100644
      --- a/assets/public_gamedevtree_docs_updating-tmt.md.f6459ce1.js
      +++ b/assets/public_gamedevtree_docs_updating-tmt.md.cde46630.js
      @@ -1 +1 @@
      -import{_ as e,c as t,o as a,a as o}from"./app.a576d425.js";const m=JSON.parse('{"title":"Updating The Modding Tree","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/updating-tmt.md","lastUpdated":null}'),i={name:"public/gamedevtree/docs/updating-tmt.md"},n=o('

      Updating The Modding Tree

      This tutorial assumes that you have used the Getting Started Tutorial, and are using Github Desktop and VSCode for your mod.

      Here's what you have to do when there's a TMT update:

      1. Look at the changelog. It will warn you if the update will break anything or require any changes. Decide if you want to try to update.

      2. Open Github Desktop, and at the top middle, click "fetch origin". This will make Github Desktop get information about the update.

      3. Click where it says "current branch: master" at the top middle, and at the bottom of the thing that appears, click "choose a branch to merge into master.

      4. Select upstream/master. It will likely say there are conflicts, but you have tools to resolve them. Click "Merge upstream/master into master".

      5. A conflict happens when the things you're trying to merge have both made changes in the same place. Click "open in Visual Studio Code" next to the first file.

      6. Scroll down through the file, and look for the parts highlighted in red and green. One of these is your code, and the other is some code that will be modified by the update. Do your best to try to edit things to keep the updated changes, but keep your content.

      7. Continue to do this for all remaining challenges.

      8. Do any other changes required by the update, run the game, fix issues, etc.

      ',4),r=[n];function h(d,s,l,p,u,c){return a(),t("div",null,r)}const _=e(i,[["render",h]]);export{m as __pageData,_ as default}; +import{_ as e,c as t,o as a,a as o}from"./app.9bfeb8de.js";const m=JSON.parse('{"title":"Updating The Modding Tree","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/updating-tmt.md","lastUpdated":null}'),i={name:"public/gamedevtree/docs/updating-tmt.md"},n=o('

      Updating The Modding Tree

      This tutorial assumes that you have used the Getting Started Tutorial, and are using Github Desktop and VSCode for your mod.

      Here's what you have to do when there's a TMT update:

      1. Look at the changelog. It will warn you if the update will break anything or require any changes. Decide if you want to try to update.

      2. Open Github Desktop, and at the top middle, click "fetch origin". This will make Github Desktop get information about the update.

      3. Click where it says "current branch: master" at the top middle, and at the bottom of the thing that appears, click "choose a branch to merge into master.

      4. Select upstream/master. It will likely say there are conflicts, but you have tools to resolve them. Click "Merge upstream/master into master".

      5. A conflict happens when the things you're trying to merge have both made changes in the same place. Click "open in Visual Studio Code" next to the first file.

      6. Scroll down through the file, and look for the parts highlighted in red and green. One of these is your code, and the other is some code that will be modified by the update. Do your best to try to edit things to keep the updated changes, but keep your content.

      7. Continue to do this for all remaining challenges.

      8. Do any other changes required by the update, run the game, fix issues, etc.

      ',4),r=[n];function h(d,s,l,p,u,c){return a(),t("div",null,r)}const _=e(i,[["render",h]]);export{m as __pageData,_ as default}; diff --git a/assets/public_gamedevtree_docs_updating-tmt.md.f6459ce1.lean.js b/assets/public_gamedevtree_docs_updating-tmt.md.cde46630.lean.js similarity index 84% rename from assets/public_gamedevtree_docs_updating-tmt.md.f6459ce1.lean.js rename to assets/public_gamedevtree_docs_updating-tmt.md.cde46630.lean.js index 1addbdf91..d1cd18b41 100644 --- a/assets/public_gamedevtree_docs_updating-tmt.md.f6459ce1.lean.js +++ b/assets/public_gamedevtree_docs_updating-tmt.md.cde46630.lean.js @@ -1 +1 @@ -import{_ as e,c as t,o as a,a as o}from"./app.a576d425.js";const m=JSON.parse('{"title":"Updating The Modding Tree","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/updating-tmt.md","lastUpdated":null}'),i={name:"public/gamedevtree/docs/updating-tmt.md"},n=o("",4),r=[n];function h(d,s,l,p,u,c){return a(),t("div",null,r)}const _=e(i,[["render",h]]);export{m as __pageData,_ as default}; +import{_ as e,c as t,o as a,a as o}from"./app.9bfeb8de.js";const m=JSON.parse('{"title":"Updating The Modding Tree","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/updating-tmt.md","lastUpdated":null}'),i={name:"public/gamedevtree/docs/updating-tmt.md"},n=o("",4),r=[n];function h(d,s,l,p,u,c){return a(),t("div",null,r)}const _=e(i,[["render",h]]);export{m as __pageData,_ as default}; diff --git a/assets/public_gamedevtree_docs_upgrades.md.799f28d0.js b/assets/public_gamedevtree_docs_upgrades.md.c79ac790.js similarity index 98% rename from assets/public_gamedevtree_docs_upgrades.md.799f28d0.js rename to assets/public_gamedevtree_docs_upgrades.md.c79ac790.js index 7e4eb053f..29062b515 100644 --- a/assets/public_gamedevtree_docs_upgrades.md.799f28d0.js +++ b/assets/public_gamedevtree_docs_upgrades.md.c79ac790.js @@ -1,4 +1,4 @@ -import{_ as e,c as s,o as a,a as t}from"./app.a576d425.js";const g=JSON.parse('{"title":"Upgrades","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/upgrades.md","lastUpdated":null}'),n={name:"public/gamedevtree/docs/upgrades.md"},o=t(`

      Upgrades

      Useful functions for dealing with Upgrades and implementing their effects:

      • hasUpgrade(layer, id): determine if the player has the upgrade
      • upgradeEffect(layer, id): Returns the current effects of the upgrade, if any
      • buyUpgrade(layer, id): Buys an upgrade directly (if affordable)

      Hint: Basic point gain is calculated in mod.js's "getPointGen".

      Upgrades are stored in the following format:

      js
          upgrades: {
      +import{_ as e,c as s,o as a,a as t}from"./app.9bfeb8de.js";const g=JSON.parse('{"title":"Upgrades","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/upgrades.md","lastUpdated":null}'),n={name:"public/gamedevtree/docs/upgrades.md"},o=t(`

      Upgrades

      Useful functions for dealing with Upgrades and implementing their effects:

      • hasUpgrade(layer, id): determine if the player has the upgrade
      • upgradeEffect(layer, id): Returns the current effects of the upgrade, if any
      • buyUpgrade(layer, id): Buys an upgrade directly (if affordable)

      Hint: Basic point gain is calculated in mod.js's "getPointGen".

      Upgrades are stored in the following format:

      js
          upgrades: {
               rows: # of rows
               cols: # of columns
               11: {
      diff --git a/assets/public_gamedevtree_docs_upgrades.md.799f28d0.lean.js b/assets/public_gamedevtree_docs_upgrades.md.c79ac790.lean.js
      similarity index 84%
      rename from assets/public_gamedevtree_docs_upgrades.md.799f28d0.lean.js
      rename to assets/public_gamedevtree_docs_upgrades.md.c79ac790.lean.js
      index 4c37dd687..9f64b6d6e 100644
      --- a/assets/public_gamedevtree_docs_upgrades.md.799f28d0.lean.js
      +++ b/assets/public_gamedevtree_docs_upgrades.md.c79ac790.lean.js
      @@ -1 +1 @@
      -import{_ as e,c as s,o as a,a as t}from"./app.a576d425.js";const g=JSON.parse('{"title":"Upgrades","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/upgrades.md","lastUpdated":null}'),n={name:"public/gamedevtree/docs/upgrades.md"},o=t("",10),l=[o];function r(p,i,c,u,d,h){return a(),s("div",null,l)}const f=e(n,[["render",r]]);export{g as __pageData,f as default};
      +import{_ as e,c as s,o as a,a as t}from"./app.9bfeb8de.js";const g=JSON.parse('{"title":"Upgrades","description":"","frontmatter":{},"headers":[],"relativePath":"public/gamedevtree/docs/upgrades.md","lastUpdated":null}'),n={name:"public/gamedevtree/docs/upgrades.md"},o=t("",10),l=[o];function r(p,i,c,u,d,h){return a(),s("div",null,l)}const f=e(n,[["render",r]]);export{g as __pageData,f as default};
      diff --git a/assets/public_kronos_Old Things_2.0-format-changes.md.0dd3e9ad.js b/assets/public_kronos_Old Things_2.0-format-changes.md.8d55c7ef.js
      similarity index 96%
      rename from assets/public_kronos_Old Things_2.0-format-changes.md.0dd3e9ad.js
      rename to assets/public_kronos_Old Things_2.0-format-changes.md.8d55c7ef.js
      index a8cc5aede..82e81790b 100644
      --- a/assets/public_kronos_Old Things_2.0-format-changes.md.0dd3e9ad.js	
      +++ b/assets/public_kronos_Old Things_2.0-format-changes.md.8d55c7ef.js	
      @@ -1 +1 @@
      -import{_ as e,c as a,o as t,a as n}from"./app.a576d425.js";const u=JSON.parse('{"title":"2.0 format changes","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/Old Things/2.0-format-changes.md","lastUpdated":null}'),i={name:"public/kronos/Old Things/2.0-format-changes.md"},o=n('

      2.0 format changes

      • Temp format is changed from temp.something[layer] to temp[layer].something, for consistency
      • Challenges are now saved as an object with the amount of completions in each spot. (This will break saves.)
      • effectDisplay in Challenges and Upgrades no longer takes an argument, and neither does effect for Buyables
      • Buyable cost can take an argument for amount of buyables, but it needs to function if no argument is supplied (it should do the cost for the next purchase).
      • Generation of Points now happens in the main game loop (not in a layer update function), enabled by canGenPoints in game.js.
      • Changed fullLayerReset to layerDataReset, which takes an array of names of values to keep

      In addition, many names were changed, mostly expanding abbreviations:

      All instances of:

      • chall -> challenge
      • unl -> unlocked
      • upg -> upgrade (besides CSS)
      • amt -> amount
      • desc -> description
      • resCeil -> roundUpCost
      • order -> unlockOrder
      • incr_order -> increaseUnlockOrder

      Challenges:

      • desc -> challengeDescription
      • reward -> rewardDescription
      • effect -> rewardEffect
      • effectDisplay -> rewardDisplay
      • active -> challengeActive
      ',7),l=[o];function s(r,c,d,h,g,p){return t(),a("div",null,l)}const m=e(i,[["render",s]]);export{u as __pageData,m as default}; +import{_ as e,c as a,o as t,a as n}from"./app.9bfeb8de.js";const u=JSON.parse('{"title":"2.0 format changes","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/Old Things/2.0-format-changes.md","lastUpdated":null}'),i={name:"public/kronos/Old Things/2.0-format-changes.md"},o=n('

      2.0 format changes

      • Temp format is changed from temp.something[layer] to temp[layer].something, for consistency
      • Challenges are now saved as an object with the amount of completions in each spot. (This will break saves.)
      • effectDisplay in Challenges and Upgrades no longer takes an argument, and neither does effect for Buyables
      • Buyable cost can take an argument for amount of buyables, but it needs to function if no argument is supplied (it should do the cost for the next purchase).
      • Generation of Points now happens in the main game loop (not in a layer update function), enabled by canGenPoints in game.js.
      • Changed fullLayerReset to layerDataReset, which takes an array of names of values to keep

      In addition, many names were changed, mostly expanding abbreviations:

      All instances of:

      • chall -> challenge
      • unl -> unlocked
      • upg -> upgrade (besides CSS)
      • amt -> amount
      • desc -> description
      • resCeil -> roundUpCost
      • order -> unlockOrder
      • incr_order -> increaseUnlockOrder

      Challenges:

      • desc -> challengeDescription
      • reward -> rewardDescription
      • effect -> rewardEffect
      • effectDisplay -> rewardDisplay
      • active -> challengeActive
      ',7),l=[o];function s(r,c,d,h,g,p){return t(),a("div",null,l)}const m=e(i,[["render",s]]);export{u as __pageData,m as default}; diff --git a/assets/public_kronos_Old Things_2.0-format-changes.md.0dd3e9ad.lean.js b/assets/public_kronos_Old Things_2.0-format-changes.md.8d55c7ef.lean.js similarity index 85% rename from assets/public_kronos_Old Things_2.0-format-changes.md.0dd3e9ad.lean.js rename to assets/public_kronos_Old Things_2.0-format-changes.md.8d55c7ef.lean.js index c1c420f26..b33e2bf10 100644 --- a/assets/public_kronos_Old Things_2.0-format-changes.md.0dd3e9ad.lean.js +++ b/assets/public_kronos_Old Things_2.0-format-changes.md.8d55c7ef.lean.js @@ -1 +1 @@ -import{_ as e,c as a,o as t,a as n}from"./app.a576d425.js";const u=JSON.parse('{"title":"2.0 format changes","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/Old Things/2.0-format-changes.md","lastUpdated":null}'),i={name:"public/kronos/Old Things/2.0-format-changes.md"},o=n("",7),l=[o];function s(r,c,d,h,g,p){return t(),a("div",null,l)}const m=e(i,[["render",s]]);export{u as __pageData,m as default}; +import{_ as e,c as a,o as t,a as n}from"./app.9bfeb8de.js";const u=JSON.parse('{"title":"2.0 format changes","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/Old Things/2.0-format-changes.md","lastUpdated":null}'),i={name:"public/kronos/Old Things/2.0-format-changes.md"},o=n("",7),l=[o];function s(r,c,d,h,g,p){return t(),a("div",null,l)}const m=e(i,[["render",s]]);export{u as __pageData,m as default}; diff --git a/assets/public_kronos_README.md.ecc49558.js b/assets/public_kronos_README.md.7ff4927f.js similarity index 91% rename from assets/public_kronos_README.md.ecc49558.js rename to assets/public_kronos_README.md.7ff4927f.js index 2c2dcf706..9059906a7 100644 --- a/assets/public_kronos_README.md.ecc49558.js +++ b/assets/public_kronos_README.md.7ff4927f.js @@ -1 +1 @@ -import{_ as e,c as o,o as t,a}from"./app.a576d425.js";const m=JSON.parse('{"title":"Kronos","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/README.md","lastUpdated":null}'),r={name:"public/kronos/README.md"},s=a('

      Kronos

      Play here.

      Updating the website:

      • git submodule update --remote
      • git add -A
      • git commit -m "Updated kronos"
      • git push
      ',4),d=[s];function i(n,c,l,_,p,h){return t(),o("div",null,d)}const f=e(r,[["render",i]]);export{m as __pageData,f as default}; +import{_ as e,c as o,o as t,a}from"./app.9bfeb8de.js";const m=JSON.parse('{"title":"Kronos","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/README.md","lastUpdated":null}'),r={name:"public/kronos/README.md"},s=a('

      Kronos

      Play here.

      Updating the website:

      • git submodule update --remote
      • git add -A
      • git commit -m "Updated kronos"
      • git push
      ',4),d=[s];function i(n,c,l,_,p,h){return t(),o("div",null,d)}const f=e(r,[["render",i]]);export{m as __pageData,f as default}; diff --git a/assets/public_kronos_README.md.ecc49558.lean.js b/assets/public_kronos_README.md.7ff4927f.lean.js similarity index 82% rename from assets/public_kronos_README.md.ecc49558.lean.js rename to assets/public_kronos_README.md.7ff4927f.lean.js index 77fe0c3d6..8a514ad51 100644 --- a/assets/public_kronos_README.md.ecc49558.lean.js +++ b/assets/public_kronos_README.md.7ff4927f.lean.js @@ -1 +1 @@ -import{_ as e,c as o,o as t,a}from"./app.a576d425.js";const m=JSON.parse('{"title":"Kronos","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/README.md","lastUpdated":null}'),r={name:"public/kronos/README.md"},s=a("",4),d=[s];function i(n,c,l,_,p,h){return t(),o("div",null,d)}const f=e(r,[["render",i]]);export{m as __pageData,f as default}; +import{_ as e,c as o,o as t,a}from"./app.9bfeb8de.js";const m=JSON.parse('{"title":"Kronos","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/README.md","lastUpdated":null}'),r={name:"public/kronos/README.md"},s=a("",4),d=[s];function i(n,c,l,_,p,h){return t(),o("div",null,d)}const f=e(r,[["render",i]]);export{m as __pageData,f as default}; diff --git a/assets/public_kronos_changelog.md.01d7b07d.js b/assets/public_kronos_changelog.md.8fbfea45.js similarity index 99% rename from assets/public_kronos_changelog.md.01d7b07d.js rename to assets/public_kronos_changelog.md.8fbfea45.js index 0f494c2e2..0fdf26475 100644 --- a/assets/public_kronos_changelog.md.01d7b07d.js +++ b/assets/public_kronos_changelog.md.8fbfea45.js @@ -1 +1 @@ -import{_ as e,c as i,o as l,a}from"./app.a576d425.js";const m=JSON.parse('{"title":"The Modding Tree changelog:","description":"","frontmatter":{},"headers":[{"level":3,"title":"v2.5.9.2 - 5/19/21","slug":"v2-5-9-2-5-19-21","link":"#v2-5-9-2-5-19-21","children":[]},{"level":3,"title":"v2.5.9.1 - 5/18/21","slug":"v2-5-9-1-5-18-21","link":"#v2-5-9-1-5-18-21","children":[]},{"level":3,"title":"v2.5.9 - 5/18/21","slug":"v2-5-9-5-18-21","link":"#v2-5-9-5-18-21","children":[]},{"level":3,"title":"v2.5.8 - 5/17/21","slug":"v2-5-8-5-17-21","link":"#v2-5-8-5-17-21","children":[]},{"level":3,"title":"v2.5.7 - 5/15/21","slug":"v2-5-7-5-15-21","link":"#v2-5-7-5-15-21","children":[]},{"level":3,"title":"v2.5.6 - 5/14/21","slug":"v2-5-6-5-14-21","link":"#v2-5-6-5-14-21","children":[]},{"level":3,"title":"v2.5.5.2 - 5/12/21","slug":"v2-5-5-2-5-12-21","link":"#v2-5-5-2-5-12-21","children":[]},{"level":3,"title":"v2.5.5.1 - 5/12/21","slug":"v2-5-5-1-5-12-21","link":"#v2-5-5-1-5-12-21","children":[]},{"level":3,"title":"v2.5.5 - 5/12/21","slug":"v2-5-5-5-12-21","link":"#v2-5-5-5-12-21","children":[]},{"level":3,"title":"v2.5.4 - 5/10/21","slug":"v2-5-4-5-10-21","link":"#v2-5-4-5-10-21","children":[]},{"level":3,"title":"v2.5.3 - 5/8/21","slug":"v2-5-3-5-8-21","link":"#v2-5-3-5-8-21","children":[]},{"level":3,"title":"v2.5.2.1 - 5/7/21","slug":"v2-5-2-1-5-7-21","link":"#v2-5-2-1-5-7-21","children":[]},{"level":3,"title":"v2.5.2 - 5/7/21","slug":"v2-5-2-5-7-21","link":"#v2-5-2-5-7-21","children":[]},{"level":3,"title":"v2.5.1 - 5/7/21","slug":"v2-5-1-5-7-21","link":"#v2-5-1-5-7-21","children":[]},{"level":2,"title":"v2.5: Dreams Really Do Come True - 5/7/21","slug":"v2-5-dreams-really-do-come-true-5-7-21","link":"#v2-5-dreams-really-do-come-true-5-7-21","children":[{"level":3,"title":"v2.4.1 - 4/29/21","slug":"v2-4-1-4-29-21","link":"#v2-4-1-4-29-21","children":[]}]},{"level":2,"title":"v2.4: Rationalized Edition - 4/29/21","slug":"v2-4-rationalized-edition-4-29-21","link":"#v2-4-rationalized-edition-4-29-21","children":[{"level":3,"title":"v2.\u03C0.1 - 4/7/21","slug":"v2-\u03C0-1-4-7-21","link":"#v2-\u03C0-1-4-7-21","children":[]}]},{"level":2,"title":"v2.\u03C0: Incrementally Updated - 2/5/21","slug":"v2-\u03C0-incrementally-updated-2-5-21","link":"#v2-\u03C0-incrementally-updated-2-5-21","children":[{"level":3,"title":"v2.3.5 - 12/21/20","slug":"v2-3-5-12-21-20","link":"#v2-3-5-12-21-20","children":[]},{"level":3,"title":"v2.3.4 - 12/16/20","slug":"v2-3-4-12-16-20","link":"#v2-3-4-12-16-20","children":[]},{"level":3,"title":"v2.3.3 - 12/13/20","slug":"v2-3-3-12-13-20","link":"#v2-3-3-12-13-20","children":[]},{"level":3,"title":"v2.3.2 - 12/13/20","slug":"v2-3-2-12-13-20","link":"#v2-3-2-12-13-20","children":[]},{"level":3,"title":"v2.3.1 - 12/12/20","slug":"v2-3-1-12-12-20","link":"#v2-3-1-12-12-20","children":[]}]},{"level":2,"title":"v2.3: Cooler and Newer Edition - 12/10/20","slug":"v2-3-cooler-and-newer-edition-12-10-20","link":"#v2-3-cooler-and-newer-edition-12-10-20","children":[{"level":3,"title":"v2.2.8 - 12/03/20","slug":"v2-2-8-12-03-20","link":"#v2-2-8-12-03-20","children":[]},{"level":3,"title":"v2.2.7 - 11/30/20","slug":"v2-2-7-11-30-20","link":"#v2-2-7-11-30-20","children":[]},{"level":3,"title":"v2.2.6 - 11/30/20","slug":"v2-2-6-11-30-20","link":"#v2-2-6-11-30-20","children":[]},{"level":3,"title":"v2.2.5 - 11/29/20","slug":"v2-2-5-11-29-20","link":"#v2-2-5-11-29-20","children":[]},{"level":3,"title":"v2.2.4 - 11/28/20","slug":"v2-2-4-11-28-20","link":"#v2-2-4-11-28-20","children":[]},{"level":3,"title":"v2.2.3 - 11/28/20","slug":"v2-2-3-11-28-20","link":"#v2-2-3-11-28-20","children":[]},{"level":3,"title":"v2.2.2 - 11/22/20","slug":"v2-2-2-11-22-20","link":"#v2-2-2-11-22-20","children":[]},{"level":3,"title":"v2.2.1 - 11/7/20","slug":"v2-2-1-11-7-20","link":"#v2-2-1-11-7-20","children":[]}]},{"level":2,"title":"v2.2: Uprooted - 11/7/20","slug":"v2-2-uprooted-11-7-20","link":"#v2-2-uprooted-11-7-20","children":[{"level":3,"title":"v2.1.4 - 10/25/20","slug":"v2-1-4-10-25-20","link":"#v2-1-4-10-25-20","children":[]},{"level":3,"title":"v2.1.3.1 - 10/21/20","slug":"v2-1-3-1-10-21-20","link":"#v2-1-3-1-10-21-20","children":[]},{"level":3,"title":"v2.1.3 - 10/21/20","slug":"v2-1-3-10-21-20","link":"#v2-1-3-10-21-20","children":[]},{"level":3,"title":"v2.1.2 - 10/19/20","slug":"v2-1-2-10-19-20","link":"#v2-1-2-10-19-20","children":[]},{"level":3,"title":"v2.1.1 - 10/17/20","slug":"v2-1-1-10-17-20","link":"#v2-1-1-10-17-20","children":[]}]},{"level":2,"title":"v2.1: We should have thought of this sooner! - 10/17/20","slug":"v2-1-we-should-have-thought-of-this-sooner-10-17-20","link":"#v2-1-we-should-have-thought-of-this-sooner-10-17-20","children":[{"level":3,"title":"v2.0.5 - 10/16/20","slug":"v2-0-5-10-16-20","link":"#v2-0-5-10-16-20","children":[]},{"level":3,"title":"v2.0.4 - 10/16/20","slug":"v2-0-4-10-16-20","link":"#v2-0-4-10-16-20","children":[]},{"level":3,"title":"v2.0.3 - 10/16/20","slug":"v2-0-3-10-16-20","link":"#v2-0-3-10-16-20","children":[]},{"level":3,"title":"v2.0.2 - 10/15/20","slug":"v2-0-2-10-15-20","link":"#v2-0-2-10-15-20","children":[]},{"level":3,"title":"v2.0.1 - 10/15/20","slug":"v2-0-1-10-15-20","link":"#v2-0-1-10-15-20","children":[]}]},{"level":2,"title":"v2.0: The Pinnacle of Achievement Mountain - 10/15/20","slug":"v2-0-the-pinnacle-of-achievement-mountain-10-15-20","link":"#v2-0-the-pinnacle-of-achievement-mountain-10-15-20","children":[{"level":3,"title":"v1.3.5:","slug":"v1-3-5","link":"#v1-3-5","children":[]},{"level":3,"title":"v1.3.4 - 10/8/20","slug":"v1-3-4-10-8-20","link":"#v1-3-4-10-8-20","children":[]},{"level":3,"title":"v1.3.3 - 10/7/20","slug":"v1-3-3-10-7-20","link":"#v1-3-3-10-7-20","children":[]},{"level":3,"title":"v1.3.1 - 10/7/20","slug":"v1-3-1-10-7-20","link":"#v1-3-1-10-7-20","children":[]}]},{"level":2,"title":"v1.3: Tabception... ception! - 10/7/20","slug":"v1-3-tabception-ception-10-7-20","link":"#v1-3-tabception-ception-10-7-20","children":[{"level":3,"title":"v1.2.4 - 10/4/20","slug":"v1-2-4-10-4-20","link":"#v1-2-4-10-4-20","children":[]},{"level":3,"title":"v1.2.3 - 10/3/20","slug":"v1-2-3-10-3-20","link":"#v1-2-3-10-3-20","children":[]}]},{"level":2,"title":"v1.2: This Changes Everything! - 10/3/20","slug":"v1-2-this-changes-everything-10-3-20","link":"#v1-2-this-changes-everything-10-3-20","children":[{"level":3,"title":"v1.1.1 - 9/30/20","slug":"v1-1-1-9-30-20","link":"#v1-1-1-9-30-20","children":[]}]},{"level":2,"title":"v1.1: Enhanced Edition - 9/30/20","slug":"v1-1-enhanced-edition-9-30-20","link":"#v1-1-enhanced-edition-9-30-20","children":[]},{"level":2,"title":"v1.0 - 9/27/20","slug":"v1-0-9-27-20","link":"#v1-0-9-27-20","children":[]}],"relativePath":"public/kronos/changelog.md","lastUpdated":null}'),t={name:"public/kronos/changelog.md"},n=a('

      The Modding Tree changelog:

      v2.5.9.2 - 5/19/21

      • Fixed many issues with things not updating.

      v2.5.9.1 - 5/18/21

      • Made text inputs never give NaNs.

      v2.5.9 - 5/18/21

      • Fixed issue when using text inputs for Numbers.
      • Added particle color feature.
      • Particle speed and dir are updated as it moves.
      • Added setSpeed and setDir for particles.
      • Added more trig functions.

      v2.5.8 - 5/17/21

      • Added makeShinies, which creates a stationary particle in a random spot.
      • Bars will visually update more quickly.
      • Fixed a major particle-related issue.
      • Fixed autoUpgrade.
      • Fixed a minor visual issue with tree nodes.

      v2.5.7 - 5/15/21

      • Added a particle system! Not only can it be used for visual effects, but particles can interact with the mouse. They could be used to create golden cookies or collectables, for example.
      • Added marked feature to buyables, clickables, and challenges. By default, stars multi-completion challenges when maxed.
      • Added 'deactivated' feature to layers, which disables many features.
      • Improved number formatting slightly.

      v2.5.6 - 5/14/21

      • You can now use non-numeric ids for upgrades, buyables, etc.
      • Fixed an exploit that let you buy an extra buyable.
      • Moved basic getter/setter functions to easyAccess.js.

      v2.5.5.2 - 5/12/21

      • Fixed a major issue with buyables.
      • Fixed a variety of tabFormat-related issues.
      • Fixed commas appearing in decimal places (thanks to pg132!)

      v2.5.5.1 - 5/12/21

      • Fixed clickables.

      v2.5.5 - 5/12/21

      • Added grids! They are a grid of buttons which behave the same, but have their own data. Good for inventory grids, map tiles, and more!
      • Added "marked" feature to add a mark to a node. Can be an image instead of a star. (Originally by Jacorb)
      • Added "layer-proxy" component that lets you use components from another layer.
      • Added the ability to display non-whole numbers in main-display.

      v2.5.4 - 5/10/21

      • Added a setting to always use single-tab mode.
      • Added directMult, which multiplies prestige gain after exponents and softcaps. It actually multiplies gain for static layers.
      • Added onEnter and onExit for challenges.
      • Improved displaying numbers between 0.0001 and 0.1.
      • Added documentation on how gainMult/Exp work for static layers.
      • Fixed a visual issue on mobile, thanks to thepaperpilot.
      • Improved documentation in general.

      v2.5.3 - 5/8/21

      • Improved performance of tab formats and bars.
      • Respec confirmation settings are now kept on resets.
      • Improved compatibility with older browsers.
      • Fixed missing pixel on vertical bars.

      v2.5.2.1 - 5/7/21

      • Fixed microtabs making layers highlight incorrectly.

      v2.5.2 - 5/7/21

      • Added glowColor for subtabs.
      • Improved the display for extremely small numbers.
      • Fixed issues in the buyable docs.

      v2.5.1 - 5/7/21

      • Fixed dynamic things in tabFormat not updating.

      v2.5: Dreams Really Do Come True - 5/7/21

      • Optimizations, hopefully a significant amount.
      • Added OOM/s point gen display at high values (thanks to Ducdat!)
      • Only one tab will display if the window is not wide enough (also thanks to Ducdat!)
      • Holding down a buyable's button now buys it continuously.
      • New milestone setting will also show the most recently unlocked milestone. (Also renamed all settings to be clearer)
      • Added an onHold feature for clickables.
      • Layer nodes will be highlighted even if the player is on the same tab.
      • Added customizable node glowColor.
      • Added buyable purchaseLimit.
      • Amount is automatically supplied to buyable cost and effect functions.
      • Locked (not yet visible) milestones no longer take up space. Also fixed hidden milestones taking a tiny bit of space.
      • Re-centered respec buttons.
      • Force-displayed tooltips are not hidden by resets.
      • Added formatting support for very small numbers. Disabled in most places by default because rounding errors might cause issues. Access it with formatSmall, or enable it globally by adding "allowSmall: true" to modInfo.

      v2.4.1 - 4/29/21

      • A number of minor fixes, many thanks to thepaperpilot.
      • The respec confirmation checkbox is now part of the respec-button component. (This also fixes the checkbox appearing when there is no respec button)
      • Added a few undocumented changes to the 2.4 changelog (the two at the bottom)

      v2.4: Rationalized Edition - 4/29/21

      • Completely reworked tooltips. Shift-click a node to force its tooltip to stay displayed. (And hopefully finally fixed flickering!)

      • Added text-input and slider components.

      • Added the ability to toggle respec confirmations.

      • Added custom respec confirmation messages.

      • The red layer highlight will not appear before a layer is unlocked.

      • Added unlocking hotkeys.

      • You no longer need to supply 'rows' and 'cols' for any Big Features.

      • Node symbols can use HTML.

      • Added documentation for the respec button.

      • Added prestigeNotify to subtabs, and prestigeNotify in subtabs also highlights the layer node.

      • The version number no longer contains special characters or irrational numbers.

      • Added ctrlDown and shiftDown variables.

      • Tooltips now use HTML (this means you need to replace any newlines with
        )

      v2.\u03C0.1 - 4/7/21

      • Fixed formatting for some larger numbers.
      • Upgrades will expand if there is too much text to display.
      • Fixed styling challenges.
      • No longer attempts to display a base currency when there is none.

      v2.\u03C0: Incrementally Updated - 2/5/21

      • Performance improvements.
      • Fixed tooltips overlapping with the top display.
      • Clicking a popup dismisses it immediately.
      • Added support for bulk challenge completions.
      • "Best" is updated automatically.
      • Fixed keeping Decimal values on reset.
      • Code reorganization and style improvements by fudo.

      v2.3.5 - 12/21/20

      • Added resetTime, which tracks the time since a layer prestiged or was reset.
      • A layer node will be highlighted red if one of its subtabs is highlighted red.
      • Fixed issues with keeping challenges, buyables, and clickables on reset.
      • Improved the unlocking of custom layers.
      • Other minor fixes.

      v2.3.4 - 12/16/20

      • Added a node image feature.
      • Resource display now always shows the amount of the currency the layer's gain is based on.
      • Added spacing between tree nodes.
      • Another attempt to fix tooltip flickering.

      v2.3.3 - 12/13/20

      • Fixed the first node in a row always taking up space.
      • layerShown is now optional.
      • All prestige types can now use features for custom prestige types.

      v2.3.2 - 12/13/20

      • Fixed achievement/milestone popups.

      v2.3.1 - 12/12/20

      • Another attempt to fix flickering tooltips.
      • The "this" keyword should work everywhere except tabFormat arrays (although I may have missed some things).
      • Fixed tree branches not updating when scrolling on the right-side tab.
      • Fixed a spacing issue when a node's symbol is ""
      • Removed some old, unneeded files.

      v2.3: Cooler and Newer Edition - 12/10/20

      • Added achievement/milestone popups (thank you to Jacorb for this contribution!)
      • The changelog tab is back, and can be set in mod.js.
      • Layer nodes and respec buttons will not be clicked by pressing "enter".
      • Possible fix for flickering tooltips and strange transitions.
      • The victory screen text is configurable.
      • Added image and textStyle features to achievements.
      • Added an argument to use specific rows in an "upgrades" component.
      • Fixed the comma appearing in the main display when there was no effectDescription
      • Added the ability to easily make a tab that is a collection of layers in subtabs.
      • Improved spacing for embedding layers with subtabs into subtabs.

      v2.2.8 - 12/03/20

      • Double-clicking a layer node brings you to the main subtab for that layer.
      • Attempted to fix challenges visually updating a different way.
      • Added a softcap function for use in formulas.
      • Added displayRow feature, which lets layers be shown somewhere separate from where they are in the reset order (e.g. side layers)
      • Fixed autoupgrade issue.

      v2.2.7 - 11/30/20

      • Added autoUpgrade feature.
      • resource-display now shows resource gain per second if passiveGain is active.
      • Fixed formatting issues on some large numbers.
      • Better support for using classed objects in player and in layers/tmp.
      • Made hard resetting more effective.
      • Removed Herobrine from getStartClickables.

      v2.2.6 - 11/30/20

      • Added goalDescription for challenges and made the new "canComplete" system the standard.
      • Another attempt to fix challenges not visually updating.
      • Fixed side layers not appearing.
      • Fixed getStartClickables again.

      v2.2.5 - 11/29/20

      • Added features for overriding the displays and costs/goals of upgrades and challenges to make them fully custom.
      • best, total, and unlocked are always automatically added to layerData (but best and total will only display if you add them yourself).
      • Fixed getStartClickables.

      v2.2.4 - 11/28/20

      • Added softcap and softcapPower features (for Normal layers)
      • Offline time limit and default max tick length were fixed (previously the limits were 1000x too large)
      • Added fixOldSaves.
      • You can use HTML in main-display.
      • Fixed a number of minor oddities.

      v2.2.3 - 11/28/20

      • Layers will be highlighted if you can finish a challenge.
      • The "can complete challenge" color now overrides the "already completed" color.
      • Button nodes now work as side "layers".
      • Setting a tooltip to "" hides it entirely.

      v2.2.2 - 11/22/20

      • Fixed right half of the screen being unclickable in some circumstances.
      • Fixed tree branches being offset.
      • Fix to lastSafeTab.

      v2.2.1 - 11/7/20

      • Added a small highlight to layers you can meaningfully prestige on.
      • Added passiveGeneration and autoPrestige features to standardize prestige automation. (The old ways still work, but the new ones work better with other things)
      • Improved milestones visually a bit.
      • "best" and "total" are now only displayed if present in startData.
      • Fixed issues with things not updating visually. (Thank you to to Jacorb!)
      • Side layers and button nodes can now be highlighted.
      • Updated docs on the new tree-related features.

      v2.2: Uprooted - 11/7/20

      • You can now embed a layer inside of a subtab or microtab!
      • Added support for hiding or reformatting the tree tab
      • Added non-layer button nodes
      • Added shouldNotify to subtab/microtab buttons. (You can make them highlighted)
      • Added commas to large exponents.
      • Upgrades now only show "currently" if they have an effectDisplay (so not for constant effects).
      • Achievements are part of the default tab format.
      • NaN is now handled more intelligently.
      • Renamed files, and moved less relevant ones to another folder.
      • The "hide completed challenges" setting now only hides challenges at max completions.
      • Thank you to thepaperpilot for fixing errors in docs and improving the infobox appearance!
      • Many other minor fixes.

      v2.1.4 - 10/25/20

      • Added an infobox component. Thank you to thepaperpilot for this contribution!
      • Layer type is now optional, and defaults to "none".
      • Improved the look of bars and tab buttons.
      • Improved spacing between layer nodes (also thanks to thepaperpilot!)
      • Fixed the "blank" component breaking if only specifying the height.
      • Fixed some numbers not displaying with enough digits.
      • Made a few more things able to be functions.
      • A few other minor fixes.

      v2.1.3.1 - 10/21/20

      • Fixed the update function.

      v2.1.3 - 10/21/20

      • gainMult and gainExp are now optional.
      • Layer unlocking is now kept on reset.
      • Game should start up faster.
      • Layer updates now have a determined order and starts with earlier-rowed layers.
      • Automation now has a determined order and starts with later-rowed layers.
      • Fixed issues with resetting clickables and challenges.
      • Commas should no longer appear in the decimal places of a number.
      • Fixed potential issue in displaying the tree.

      v2.1.2 - 10/19/20

      • Added buyUpgrade function (buyUpg still works though)
      • Added author name to modInfo.
      • Fix to crash caused when the name of a subtab or microtab is changed.
      • Fixes to outdated information in docs.
      • Improvements to Discord links.
      • Thank you to thepaperpilot for contributing to this update!

      v2.1.1 - 10/17/20

      • Added resource-display component, which displays the base currency for the prestige layer, as well as the best and/or total of this layer's prestige currency.
      • Fixed the value for the base currency not updating in resource-display.

      v2.1: We should have thought of this sooner! - 10/17/20

      • Moved most of the code users will want to edit to mod.js, added documentation for it.
        • Specifically, modInfo, VERSION, canGenPoints, getPointGen, and maxTickLength
      • Added getStartPoints()
      • Added the ability to store non-layer-related data
      • Added the ability to display more things at the top of the tree tab below points.
      • Made the endgame condition customizable
      • Added "sell one" and "sell all" buttons for buyables.
      • Moved the old "game" to demo.js, and replaced it with a minimal game that won't cause issues when edited.
      • Fixed issues with version number
      • Fixed number formatting issue making things like "10e9" appear.

      v2.0.5 - 10/16/20

      • Made more features (including prestige parameters) able to be dynamic.
      • Layer nodes can be hidden but still take up space with "ghost" visibility
      • Added clickableEffect for real.
      • Fixed some visual issues with bars.
      • A few other minor tweaks and improvements.

      v2.0.4 - 10/16/20

      • Fixed HTML on buttons interfering with clicking on them.

      v2.0.3 - 10/16/20

      • Fixed hotkeys not displaying in info.
      • Fixed the game supressing all external hotkeys.
      • You can use more things as currencies for upgrade costs and challenge goals using currencyLocation.
      • Added maxTickLength, which can be used to prevent offline time or tab-switching from breaking time-limit based mechanics.
      • Made buyable respec buttons and clickable "master" buttons their own components, and gave them a hide/show feature.
      • Added a general "tooltip" feature for achievements.

      v2.0.2 - 10/15/20

      • Branches are now dynamic (they can be functions).
      • Fixed a crash related to offline time.
      • Fixed links being too wide.

      v2.0.1 - 10/15/20

      • Fixed side layers appearing multiple times.

      v2.0: The Pinnacle of Achievement Mountain - 10/15/20

      • Added progress bars, which are highly customizable and can be horizontal or vertical!
      • Added "side layers", displayed smaller and off to the side, and don't get reset by default. They can be used for global achievements and statistics. Speaking of which...
      • Added achievements!
      • Added clickables, a more generalized variant of buyables.
      • Almost every value in layer data can be either a function or a constant value!
      • Added support for multiple completions of challenges.
      • Added "none" prestige type, which removes the need for any other prestige-related features.
      • The points display and other gui elements stay at the top of the screen when the tree scrolls.
      • Added getter/setter functions for the amounts and effects of most Big Features
      • Moved modInfo to game.js, added a spot in modInfo for a Discord link, changelog link. Also added a separate mod version from the TMT version in VERSION.
      • Tree structure is based on layer data, no index.html editing is needed.
      • Tmp does not need to be manually updated.
      • You don't have to have the same amount of upgrades in every row (and challs and buyables)
      • "unlocked" is optional for all Big Components (defaults to true).
      • All displays will update correctly.
      • Changelog is no longer in index.html at all.
      • Generation of Points now happens in the main game loop
      • Changed the reset functions to make keeping things easier
      • Renamed many things to increase readability (see the list in the link below)
      • Improved documentation based on feedback

      v1.3.5:

      • Completely automated convertToDecimal, now you never have to worry about it again.
      • Branches can be defined without a color id. But they can also use hex values for color ids!
      • Created a tutorial for getting started with TMT and Github.
      • Page title is now automatically taken from mod name.

      v1.3.4 - 10/8/20

      • Added "midsection" feature to add things to a tab's layout while still keeping the standard layout.
      • Fix for being able to buy more buyables than you should.

      v1.3.3 - 10/7/20

      • Fix for the "order of operations" issue in temp.

      v1.3.1 - 10/7/20

      • Added custom CSS and tooltips for Layer Nodes.
      • Added custom CSS for upgrades, buyables, milestones, and challenges, both individually and layer-wide.
      • You can now use HTML in most display text!
      • You can now make milestones unlockable and not display immediately.
      • Fixed importing saves, and issue with upgrades not appearing, and probably more.
      • Optional "name" layer feature, used in confirmation messages.

      v1.3: Tabception... ception! - 10/7/20

      • Added subtabs! And also a Micro-tab component to let you make smaller subtab-esque areas anywhere.
      • Added a "custom" prestige formula type, and a number of features to support it.
      • Added points/sec display (can be disabled).
      • Added h-line, v-line and image-display components, plus components for individual upgrades, challenges, and milestones.
      • Added upgEffect, buyableEffect, and challEffect functions.
      • Added "hide completed challenges" setting.
      • Moved old changelogs to a separate place.
      • Fixed hasMilestone and incr_order.
      • Static layers now show the currency amount needed for the next one if you can buy max.

      v1.2.4 - 10/4/20

      • Layers are now highlighted if you can buy an upgrade, and a new feature, shouldNotify, lets you make it highlight other ways.
      • Fixed bugs with hasUpg, hasChall, hasMilestone, and inChallenge.
      • Changed the sample code to use the above functions for convenience.

      v1.2.3 - 10/3/20

      • Added a row component, which displays a list of objects in a row.
      • Added a column component, which displays a list of objects in a column (useful within a row).
      • Changed blanks to have a customizable width and height.

      v1.2: This Changes Everything! - 10/3/20

      • Many layer features can now be static values or functions. (This made some formats change, which will break old things)
      • You can now use the "this" keyword, to make code easier to transfer when making new layers.
      • Also added "this.layer", which is the current layer's name, and works on existing subfeatures (e.g. individual upgrades) as well! Subfeatures also have "this.id".
      • Fixed a big save issue. If you use a unique mod id, your save will never conflict with other mods.
      • Added a configurable offline time limit in modinfo at the top of index.html. (default 1 hour)
      • Added a few minor features, and updated the docs with new information.

      v1.1.1 - 9/30/20

      • You can define hotkeys directly from layer config.

      v1.1: Enhanced Edition - 9/30/20

      • Added "Buyables", which can function like Space Buildings or Enhancers.
      • Custom CSS can now be used on any component! Make the third argument an object with CSS parameters.
      • Lots of minor good things.

      v1.0 - 9/27/20

      • First release.
      ',115),o=[n];function d(r,s,h,u,c,v){return l(),i("div",null,o)}const g=e(t,[["render",d]]);export{m as __pageData,g as default}; +import{_ as e,c as i,o as l,a}from"./app.9bfeb8de.js";const m=JSON.parse('{"title":"The Modding Tree changelog:","description":"","frontmatter":{},"headers":[{"level":3,"title":"v2.5.9.2 - 5/19/21","slug":"v2-5-9-2-5-19-21","link":"#v2-5-9-2-5-19-21","children":[]},{"level":3,"title":"v2.5.9.1 - 5/18/21","slug":"v2-5-9-1-5-18-21","link":"#v2-5-9-1-5-18-21","children":[]},{"level":3,"title":"v2.5.9 - 5/18/21","slug":"v2-5-9-5-18-21","link":"#v2-5-9-5-18-21","children":[]},{"level":3,"title":"v2.5.8 - 5/17/21","slug":"v2-5-8-5-17-21","link":"#v2-5-8-5-17-21","children":[]},{"level":3,"title":"v2.5.7 - 5/15/21","slug":"v2-5-7-5-15-21","link":"#v2-5-7-5-15-21","children":[]},{"level":3,"title":"v2.5.6 - 5/14/21","slug":"v2-5-6-5-14-21","link":"#v2-5-6-5-14-21","children":[]},{"level":3,"title":"v2.5.5.2 - 5/12/21","slug":"v2-5-5-2-5-12-21","link":"#v2-5-5-2-5-12-21","children":[]},{"level":3,"title":"v2.5.5.1 - 5/12/21","slug":"v2-5-5-1-5-12-21","link":"#v2-5-5-1-5-12-21","children":[]},{"level":3,"title":"v2.5.5 - 5/12/21","slug":"v2-5-5-5-12-21","link":"#v2-5-5-5-12-21","children":[]},{"level":3,"title":"v2.5.4 - 5/10/21","slug":"v2-5-4-5-10-21","link":"#v2-5-4-5-10-21","children":[]},{"level":3,"title":"v2.5.3 - 5/8/21","slug":"v2-5-3-5-8-21","link":"#v2-5-3-5-8-21","children":[]},{"level":3,"title":"v2.5.2.1 - 5/7/21","slug":"v2-5-2-1-5-7-21","link":"#v2-5-2-1-5-7-21","children":[]},{"level":3,"title":"v2.5.2 - 5/7/21","slug":"v2-5-2-5-7-21","link":"#v2-5-2-5-7-21","children":[]},{"level":3,"title":"v2.5.1 - 5/7/21","slug":"v2-5-1-5-7-21","link":"#v2-5-1-5-7-21","children":[]},{"level":2,"title":"v2.5: Dreams Really Do Come True - 5/7/21","slug":"v2-5-dreams-really-do-come-true-5-7-21","link":"#v2-5-dreams-really-do-come-true-5-7-21","children":[{"level":3,"title":"v2.4.1 - 4/29/21","slug":"v2-4-1-4-29-21","link":"#v2-4-1-4-29-21","children":[]}]},{"level":2,"title":"v2.4: Rationalized Edition - 4/29/21","slug":"v2-4-rationalized-edition-4-29-21","link":"#v2-4-rationalized-edition-4-29-21","children":[{"level":3,"title":"v2.\u03C0.1 - 4/7/21","slug":"v2-\u03C0-1-4-7-21","link":"#v2-\u03C0-1-4-7-21","children":[]}]},{"level":2,"title":"v2.\u03C0: Incrementally Updated - 2/5/21","slug":"v2-\u03C0-incrementally-updated-2-5-21","link":"#v2-\u03C0-incrementally-updated-2-5-21","children":[{"level":3,"title":"v2.3.5 - 12/21/20","slug":"v2-3-5-12-21-20","link":"#v2-3-5-12-21-20","children":[]},{"level":3,"title":"v2.3.4 - 12/16/20","slug":"v2-3-4-12-16-20","link":"#v2-3-4-12-16-20","children":[]},{"level":3,"title":"v2.3.3 - 12/13/20","slug":"v2-3-3-12-13-20","link":"#v2-3-3-12-13-20","children":[]},{"level":3,"title":"v2.3.2 - 12/13/20","slug":"v2-3-2-12-13-20","link":"#v2-3-2-12-13-20","children":[]},{"level":3,"title":"v2.3.1 - 12/12/20","slug":"v2-3-1-12-12-20","link":"#v2-3-1-12-12-20","children":[]}]},{"level":2,"title":"v2.3: Cooler and Newer Edition - 12/10/20","slug":"v2-3-cooler-and-newer-edition-12-10-20","link":"#v2-3-cooler-and-newer-edition-12-10-20","children":[{"level":3,"title":"v2.2.8 - 12/03/20","slug":"v2-2-8-12-03-20","link":"#v2-2-8-12-03-20","children":[]},{"level":3,"title":"v2.2.7 - 11/30/20","slug":"v2-2-7-11-30-20","link":"#v2-2-7-11-30-20","children":[]},{"level":3,"title":"v2.2.6 - 11/30/20","slug":"v2-2-6-11-30-20","link":"#v2-2-6-11-30-20","children":[]},{"level":3,"title":"v2.2.5 - 11/29/20","slug":"v2-2-5-11-29-20","link":"#v2-2-5-11-29-20","children":[]},{"level":3,"title":"v2.2.4 - 11/28/20","slug":"v2-2-4-11-28-20","link":"#v2-2-4-11-28-20","children":[]},{"level":3,"title":"v2.2.3 - 11/28/20","slug":"v2-2-3-11-28-20","link":"#v2-2-3-11-28-20","children":[]},{"level":3,"title":"v2.2.2 - 11/22/20","slug":"v2-2-2-11-22-20","link":"#v2-2-2-11-22-20","children":[]},{"level":3,"title":"v2.2.1 - 11/7/20","slug":"v2-2-1-11-7-20","link":"#v2-2-1-11-7-20","children":[]}]},{"level":2,"title":"v2.2: Uprooted - 11/7/20","slug":"v2-2-uprooted-11-7-20","link":"#v2-2-uprooted-11-7-20","children":[{"level":3,"title":"v2.1.4 - 10/25/20","slug":"v2-1-4-10-25-20","link":"#v2-1-4-10-25-20","children":[]},{"level":3,"title":"v2.1.3.1 - 10/21/20","slug":"v2-1-3-1-10-21-20","link":"#v2-1-3-1-10-21-20","children":[]},{"level":3,"title":"v2.1.3 - 10/21/20","slug":"v2-1-3-10-21-20","link":"#v2-1-3-10-21-20","children":[]},{"level":3,"title":"v2.1.2 - 10/19/20","slug":"v2-1-2-10-19-20","link":"#v2-1-2-10-19-20","children":[]},{"level":3,"title":"v2.1.1 - 10/17/20","slug":"v2-1-1-10-17-20","link":"#v2-1-1-10-17-20","children":[]}]},{"level":2,"title":"v2.1: We should have thought of this sooner! - 10/17/20","slug":"v2-1-we-should-have-thought-of-this-sooner-10-17-20","link":"#v2-1-we-should-have-thought-of-this-sooner-10-17-20","children":[{"level":3,"title":"v2.0.5 - 10/16/20","slug":"v2-0-5-10-16-20","link":"#v2-0-5-10-16-20","children":[]},{"level":3,"title":"v2.0.4 - 10/16/20","slug":"v2-0-4-10-16-20","link":"#v2-0-4-10-16-20","children":[]},{"level":3,"title":"v2.0.3 - 10/16/20","slug":"v2-0-3-10-16-20","link":"#v2-0-3-10-16-20","children":[]},{"level":3,"title":"v2.0.2 - 10/15/20","slug":"v2-0-2-10-15-20","link":"#v2-0-2-10-15-20","children":[]},{"level":3,"title":"v2.0.1 - 10/15/20","slug":"v2-0-1-10-15-20","link":"#v2-0-1-10-15-20","children":[]}]},{"level":2,"title":"v2.0: The Pinnacle of Achievement Mountain - 10/15/20","slug":"v2-0-the-pinnacle-of-achievement-mountain-10-15-20","link":"#v2-0-the-pinnacle-of-achievement-mountain-10-15-20","children":[{"level":3,"title":"v1.3.5:","slug":"v1-3-5","link":"#v1-3-5","children":[]},{"level":3,"title":"v1.3.4 - 10/8/20","slug":"v1-3-4-10-8-20","link":"#v1-3-4-10-8-20","children":[]},{"level":3,"title":"v1.3.3 - 10/7/20","slug":"v1-3-3-10-7-20","link":"#v1-3-3-10-7-20","children":[]},{"level":3,"title":"v1.3.1 - 10/7/20","slug":"v1-3-1-10-7-20","link":"#v1-3-1-10-7-20","children":[]}]},{"level":2,"title":"v1.3: Tabception... ception! - 10/7/20","slug":"v1-3-tabception-ception-10-7-20","link":"#v1-3-tabception-ception-10-7-20","children":[{"level":3,"title":"v1.2.4 - 10/4/20","slug":"v1-2-4-10-4-20","link":"#v1-2-4-10-4-20","children":[]},{"level":3,"title":"v1.2.3 - 10/3/20","slug":"v1-2-3-10-3-20","link":"#v1-2-3-10-3-20","children":[]}]},{"level":2,"title":"v1.2: This Changes Everything! - 10/3/20","slug":"v1-2-this-changes-everything-10-3-20","link":"#v1-2-this-changes-everything-10-3-20","children":[{"level":3,"title":"v1.1.1 - 9/30/20","slug":"v1-1-1-9-30-20","link":"#v1-1-1-9-30-20","children":[]}]},{"level":2,"title":"v1.1: Enhanced Edition - 9/30/20","slug":"v1-1-enhanced-edition-9-30-20","link":"#v1-1-enhanced-edition-9-30-20","children":[]},{"level":2,"title":"v1.0 - 9/27/20","slug":"v1-0-9-27-20","link":"#v1-0-9-27-20","children":[]}],"relativePath":"public/kronos/changelog.md","lastUpdated":null}'),t={name:"public/kronos/changelog.md"},n=a('

      The Modding Tree changelog:

      v2.5.9.2 - 5/19/21

      • Fixed many issues with things not updating.

      v2.5.9.1 - 5/18/21

      • Made text inputs never give NaNs.

      v2.5.9 - 5/18/21

      • Fixed issue when using text inputs for Numbers.
      • Added particle color feature.
      • Particle speed and dir are updated as it moves.
      • Added setSpeed and setDir for particles.
      • Added more trig functions.

      v2.5.8 - 5/17/21

      • Added makeShinies, which creates a stationary particle in a random spot.
      • Bars will visually update more quickly.
      • Fixed a major particle-related issue.
      • Fixed autoUpgrade.
      • Fixed a minor visual issue with tree nodes.

      v2.5.7 - 5/15/21

      • Added a particle system! Not only can it be used for visual effects, but particles can interact with the mouse. They could be used to create golden cookies or collectables, for example.
      • Added marked feature to buyables, clickables, and challenges. By default, stars multi-completion challenges when maxed.
      • Added 'deactivated' feature to layers, which disables many features.
      • Improved number formatting slightly.

      v2.5.6 - 5/14/21

      • You can now use non-numeric ids for upgrades, buyables, etc.
      • Fixed an exploit that let you buy an extra buyable.
      • Moved basic getter/setter functions to easyAccess.js.

      v2.5.5.2 - 5/12/21

      • Fixed a major issue with buyables.
      • Fixed a variety of tabFormat-related issues.
      • Fixed commas appearing in decimal places (thanks to pg132!)

      v2.5.5.1 - 5/12/21

      • Fixed clickables.

      v2.5.5 - 5/12/21

      • Added grids! They are a grid of buttons which behave the same, but have their own data. Good for inventory grids, map tiles, and more!
      • Added "marked" feature to add a mark to a node. Can be an image instead of a star. (Originally by Jacorb)
      • Added "layer-proxy" component that lets you use components from another layer.
      • Added the ability to display non-whole numbers in main-display.

      v2.5.4 - 5/10/21

      • Added a setting to always use single-tab mode.
      • Added directMult, which multiplies prestige gain after exponents and softcaps. It actually multiplies gain for static layers.
      • Added onEnter and onExit for challenges.
      • Improved displaying numbers between 0.0001 and 0.1.
      • Added documentation on how gainMult/Exp work for static layers.
      • Fixed a visual issue on mobile, thanks to thepaperpilot.
      • Improved documentation in general.

      v2.5.3 - 5/8/21

      • Improved performance of tab formats and bars.
      • Respec confirmation settings are now kept on resets.
      • Improved compatibility with older browsers.
      • Fixed missing pixel on vertical bars.

      v2.5.2.1 - 5/7/21

      • Fixed microtabs making layers highlight incorrectly.

      v2.5.2 - 5/7/21

      • Added glowColor for subtabs.
      • Improved the display for extremely small numbers.
      • Fixed issues in the buyable docs.

      v2.5.1 - 5/7/21

      • Fixed dynamic things in tabFormat not updating.

      v2.5: Dreams Really Do Come True - 5/7/21

      • Optimizations, hopefully a significant amount.
      • Added OOM/s point gen display at high values (thanks to Ducdat!)
      • Only one tab will display if the window is not wide enough (also thanks to Ducdat!)
      • Holding down a buyable's button now buys it continuously.
      • New milestone setting will also show the most recently unlocked milestone. (Also renamed all settings to be clearer)
      • Added an onHold feature for clickables.
      • Layer nodes will be highlighted even if the player is on the same tab.
      • Added customizable node glowColor.
      • Added buyable purchaseLimit.
      • Amount is automatically supplied to buyable cost and effect functions.
      • Locked (not yet visible) milestones no longer take up space. Also fixed hidden milestones taking a tiny bit of space.
      • Re-centered respec buttons.
      • Force-displayed tooltips are not hidden by resets.
      • Added formatting support for very small numbers. Disabled in most places by default because rounding errors might cause issues. Access it with formatSmall, or enable it globally by adding "allowSmall: true" to modInfo.

      v2.4.1 - 4/29/21

      • A number of minor fixes, many thanks to thepaperpilot.
      • The respec confirmation checkbox is now part of the respec-button component. (This also fixes the checkbox appearing when there is no respec button)
      • Added a few undocumented changes to the 2.4 changelog (the two at the bottom)

      v2.4: Rationalized Edition - 4/29/21

      • Completely reworked tooltips. Shift-click a node to force its tooltip to stay displayed. (And hopefully finally fixed flickering!)

      • Added text-input and slider components.

      • Added the ability to toggle respec confirmations.

      • Added custom respec confirmation messages.

      • The red layer highlight will not appear before a layer is unlocked.

      • Added unlocking hotkeys.

      • You no longer need to supply 'rows' and 'cols' for any Big Features.

      • Node symbols can use HTML.

      • Added documentation for the respec button.

      • Added prestigeNotify to subtabs, and prestigeNotify in subtabs also highlights the layer node.

      • The version number no longer contains special characters or irrational numbers.

      • Added ctrlDown and shiftDown variables.

      • Tooltips now use HTML (this means you need to replace any newlines with
        )

      v2.\u03C0.1 - 4/7/21

      • Fixed formatting for some larger numbers.
      • Upgrades will expand if there is too much text to display.
      • Fixed styling challenges.
      • No longer attempts to display a base currency when there is none.

      v2.\u03C0: Incrementally Updated - 2/5/21

      • Performance improvements.
      • Fixed tooltips overlapping with the top display.
      • Clicking a popup dismisses it immediately.
      • Added support for bulk challenge completions.
      • "Best" is updated automatically.
      • Fixed keeping Decimal values on reset.
      • Code reorganization and style improvements by fudo.

      v2.3.5 - 12/21/20

      • Added resetTime, which tracks the time since a layer prestiged or was reset.
      • A layer node will be highlighted red if one of its subtabs is highlighted red.
      • Fixed issues with keeping challenges, buyables, and clickables on reset.
      • Improved the unlocking of custom layers.
      • Other minor fixes.

      v2.3.4 - 12/16/20

      • Added a node image feature.
      • Resource display now always shows the amount of the currency the layer's gain is based on.
      • Added spacing between tree nodes.
      • Another attempt to fix tooltip flickering.

      v2.3.3 - 12/13/20

      • Fixed the first node in a row always taking up space.
      • layerShown is now optional.
      • All prestige types can now use features for custom prestige types.

      v2.3.2 - 12/13/20

      • Fixed achievement/milestone popups.

      v2.3.1 - 12/12/20

      • Another attempt to fix flickering tooltips.
      • The "this" keyword should work everywhere except tabFormat arrays (although I may have missed some things).
      • Fixed tree branches not updating when scrolling on the right-side tab.
      • Fixed a spacing issue when a node's symbol is ""
      • Removed some old, unneeded files.

      v2.3: Cooler and Newer Edition - 12/10/20

      • Added achievement/milestone popups (thank you to Jacorb for this contribution!)
      • The changelog tab is back, and can be set in mod.js.
      • Layer nodes and respec buttons will not be clicked by pressing "enter".
      • Possible fix for flickering tooltips and strange transitions.
      • The victory screen text is configurable.
      • Added image and textStyle features to achievements.
      • Added an argument to use specific rows in an "upgrades" component.
      • Fixed the comma appearing in the main display when there was no effectDescription
      • Added the ability to easily make a tab that is a collection of layers in subtabs.
      • Improved spacing for embedding layers with subtabs into subtabs.

      v2.2.8 - 12/03/20

      • Double-clicking a layer node brings you to the main subtab for that layer.
      • Attempted to fix challenges visually updating a different way.
      • Added a softcap function for use in formulas.
      • Added displayRow feature, which lets layers be shown somewhere separate from where they are in the reset order (e.g. side layers)
      • Fixed autoupgrade issue.

      v2.2.7 - 11/30/20

      • Added autoUpgrade feature.
      • resource-display now shows resource gain per second if passiveGain is active.
      • Fixed formatting issues on some large numbers.
      • Better support for using classed objects in player and in layers/tmp.
      • Made hard resetting more effective.
      • Removed Herobrine from getStartClickables.

      v2.2.6 - 11/30/20

      • Added goalDescription for challenges and made the new "canComplete" system the standard.
      • Another attempt to fix challenges not visually updating.
      • Fixed side layers not appearing.
      • Fixed getStartClickables again.

      v2.2.5 - 11/29/20

      • Added features for overriding the displays and costs/goals of upgrades and challenges to make them fully custom.
      • best, total, and unlocked are always automatically added to layerData (but best and total will only display if you add them yourself).
      • Fixed getStartClickables.

      v2.2.4 - 11/28/20

      • Added softcap and softcapPower features (for Normal layers)
      • Offline time limit and default max tick length were fixed (previously the limits were 1000x too large)
      • Added fixOldSaves.
      • You can use HTML in main-display.
      • Fixed a number of minor oddities.

      v2.2.3 - 11/28/20

      • Layers will be highlighted if you can finish a challenge.
      • The "can complete challenge" color now overrides the "already completed" color.
      • Button nodes now work as side "layers".
      • Setting a tooltip to "" hides it entirely.

      v2.2.2 - 11/22/20

      • Fixed right half of the screen being unclickable in some circumstances.
      • Fixed tree branches being offset.
      • Fix to lastSafeTab.

      v2.2.1 - 11/7/20

      • Added a small highlight to layers you can meaningfully prestige on.
      • Added passiveGeneration and autoPrestige features to standardize prestige automation. (The old ways still work, but the new ones work better with other things)
      • Improved milestones visually a bit.
      • "best" and "total" are now only displayed if present in startData.
      • Fixed issues with things not updating visually. (Thank you to to Jacorb!)
      • Side layers and button nodes can now be highlighted.
      • Updated docs on the new tree-related features.

      v2.2: Uprooted - 11/7/20

      • You can now embed a layer inside of a subtab or microtab!
      • Added support for hiding or reformatting the tree tab
      • Added non-layer button nodes
      • Added shouldNotify to subtab/microtab buttons. (You can make them highlighted)
      • Added commas to large exponents.
      • Upgrades now only show "currently" if they have an effectDisplay (so not for constant effects).
      • Achievements are part of the default tab format.
      • NaN is now handled more intelligently.
      • Renamed files, and moved less relevant ones to another folder.
      • The "hide completed challenges" setting now only hides challenges at max completions.
      • Thank you to thepaperpilot for fixing errors in docs and improving the infobox appearance!
      • Many other minor fixes.

      v2.1.4 - 10/25/20

      • Added an infobox component. Thank you to thepaperpilot for this contribution!
      • Layer type is now optional, and defaults to "none".
      • Improved the look of bars and tab buttons.
      • Improved spacing between layer nodes (also thanks to thepaperpilot!)
      • Fixed the "blank" component breaking if only specifying the height.
      • Fixed some numbers not displaying with enough digits.
      • Made a few more things able to be functions.
      • A few other minor fixes.

      v2.1.3.1 - 10/21/20

      • Fixed the update function.

      v2.1.3 - 10/21/20

      • gainMult and gainExp are now optional.
      • Layer unlocking is now kept on reset.
      • Game should start up faster.
      • Layer updates now have a determined order and starts with earlier-rowed layers.
      • Automation now has a determined order and starts with later-rowed layers.
      • Fixed issues with resetting clickables and challenges.
      • Commas should no longer appear in the decimal places of a number.
      • Fixed potential issue in displaying the tree.

      v2.1.2 - 10/19/20

      • Added buyUpgrade function (buyUpg still works though)
      • Added author name to modInfo.
      • Fix to crash caused when the name of a subtab or microtab is changed.
      • Fixes to outdated information in docs.
      • Improvements to Discord links.
      • Thank you to thepaperpilot for contributing to this update!

      v2.1.1 - 10/17/20

      • Added resource-display component, which displays the base currency for the prestige layer, as well as the best and/or total of this layer's prestige currency.
      • Fixed the value for the base currency not updating in resource-display.

      v2.1: We should have thought of this sooner! - 10/17/20

      • Moved most of the code users will want to edit to mod.js, added documentation for it.
        • Specifically, modInfo, VERSION, canGenPoints, getPointGen, and maxTickLength
      • Added getStartPoints()
      • Added the ability to store non-layer-related data
      • Added the ability to display more things at the top of the tree tab below points.
      • Made the endgame condition customizable
      • Added "sell one" and "sell all" buttons for buyables.
      • Moved the old "game" to demo.js, and replaced it with a minimal game that won't cause issues when edited.
      • Fixed issues with version number
      • Fixed number formatting issue making things like "10e9" appear.

      v2.0.5 - 10/16/20

      • Made more features (including prestige parameters) able to be dynamic.
      • Layer nodes can be hidden but still take up space with "ghost" visibility
      • Added clickableEffect for real.
      • Fixed some visual issues with bars.
      • A few other minor tweaks and improvements.

      v2.0.4 - 10/16/20

      • Fixed HTML on buttons interfering with clicking on them.

      v2.0.3 - 10/16/20

      • Fixed hotkeys not displaying in info.
      • Fixed the game supressing all external hotkeys.
      • You can use more things as currencies for upgrade costs and challenge goals using currencyLocation.
      • Added maxTickLength, which can be used to prevent offline time or tab-switching from breaking time-limit based mechanics.
      • Made buyable respec buttons and clickable "master" buttons their own components, and gave them a hide/show feature.
      • Added a general "tooltip" feature for achievements.

      v2.0.2 - 10/15/20

      • Branches are now dynamic (they can be functions).
      • Fixed a crash related to offline time.
      • Fixed links being too wide.

      v2.0.1 - 10/15/20

      • Fixed side layers appearing multiple times.

      v2.0: The Pinnacle of Achievement Mountain - 10/15/20

      • Added progress bars, which are highly customizable and can be horizontal or vertical!
      • Added "side layers", displayed smaller and off to the side, and don't get reset by default. They can be used for global achievements and statistics. Speaking of which...
      • Added achievements!
      • Added clickables, a more generalized variant of buyables.
      • Almost every value in layer data can be either a function or a constant value!
      • Added support for multiple completions of challenges.
      • Added "none" prestige type, which removes the need for any other prestige-related features.
      • The points display and other gui elements stay at the top of the screen when the tree scrolls.
      • Added getter/setter functions for the amounts and effects of most Big Features
      • Moved modInfo to game.js, added a spot in modInfo for a Discord link, changelog link. Also added a separate mod version from the TMT version in VERSION.
      • Tree structure is based on layer data, no index.html editing is needed.
      • Tmp does not need to be manually updated.
      • You don't have to have the same amount of upgrades in every row (and challs and buyables)
      • "unlocked" is optional for all Big Components (defaults to true).
      • All displays will update correctly.
      • Changelog is no longer in index.html at all.
      • Generation of Points now happens in the main game loop
      • Changed the reset functions to make keeping things easier
      • Renamed many things to increase readability (see the list in the link below)
      • Improved documentation based on feedback

      v1.3.5:

      • Completely automated convertToDecimal, now you never have to worry about it again.
      • Branches can be defined without a color id. But they can also use hex values for color ids!
      • Created a tutorial for getting started with TMT and Github.
      • Page title is now automatically taken from mod name.

      v1.3.4 - 10/8/20

      • Added "midsection" feature to add things to a tab's layout while still keeping the standard layout.
      • Fix for being able to buy more buyables than you should.

      v1.3.3 - 10/7/20

      • Fix for the "order of operations" issue in temp.

      v1.3.1 - 10/7/20

      • Added custom CSS and tooltips for Layer Nodes.
      • Added custom CSS for upgrades, buyables, milestones, and challenges, both individually and layer-wide.
      • You can now use HTML in most display text!
      • You can now make milestones unlockable and not display immediately.
      • Fixed importing saves, and issue with upgrades not appearing, and probably more.
      • Optional "name" layer feature, used in confirmation messages.

      v1.3: Tabception... ception! - 10/7/20

      • Added subtabs! And also a Micro-tab component to let you make smaller subtab-esque areas anywhere.
      • Added a "custom" prestige formula type, and a number of features to support it.
      • Added points/sec display (can be disabled).
      • Added h-line, v-line and image-display components, plus components for individual upgrades, challenges, and milestones.
      • Added upgEffect, buyableEffect, and challEffect functions.
      • Added "hide completed challenges" setting.
      • Moved old changelogs to a separate place.
      • Fixed hasMilestone and incr_order.
      • Static layers now show the currency amount needed for the next one if you can buy max.

      v1.2.4 - 10/4/20

      • Layers are now highlighted if you can buy an upgrade, and a new feature, shouldNotify, lets you make it highlight other ways.
      • Fixed bugs with hasUpg, hasChall, hasMilestone, and inChallenge.
      • Changed the sample code to use the above functions for convenience.

      v1.2.3 - 10/3/20

      • Added a row component, which displays a list of objects in a row.
      • Added a column component, which displays a list of objects in a column (useful within a row).
      • Changed blanks to have a customizable width and height.

      v1.2: This Changes Everything! - 10/3/20

      • Many layer features can now be static values or functions. (This made some formats change, which will break old things)
      • You can now use the "this" keyword, to make code easier to transfer when making new layers.
      • Also added "this.layer", which is the current layer's name, and works on existing subfeatures (e.g. individual upgrades) as well! Subfeatures also have "this.id".
      • Fixed a big save issue. If you use a unique mod id, your save will never conflict with other mods.
      • Added a configurable offline time limit in modinfo at the top of index.html. (default 1 hour)
      • Added a few minor features, and updated the docs with new information.

      v1.1.1 - 9/30/20

      • You can define hotkeys directly from layer config.

      v1.1: Enhanced Edition - 9/30/20

      • Added "Buyables", which can function like Space Buildings or Enhancers.
      • Custom CSS can now be used on any component! Make the third argument an object with CSS parameters.
      • Lots of minor good things.

      v1.0 - 9/27/20

      • First release.
      ',115),o=[n];function d(r,s,h,u,c,v){return l(),i("div",null,o)}const g=e(t,[["render",d]]);export{m as __pageData,g as default}; diff --git a/assets/public_kronos_changelog.md.01d7b07d.lean.js b/assets/public_kronos_changelog.md.8fbfea45.lean.js similarity index 99% rename from assets/public_kronos_changelog.md.01d7b07d.lean.js rename to assets/public_kronos_changelog.md.8fbfea45.lean.js index b1a588413..a160f31b0 100644 --- a/assets/public_kronos_changelog.md.01d7b07d.lean.js +++ b/assets/public_kronos_changelog.md.8fbfea45.lean.js @@ -1 +1 @@ -import{_ as e,c as i,o as l,a}from"./app.a576d425.js";const m=JSON.parse('{"title":"The Modding Tree changelog:","description":"","frontmatter":{},"headers":[{"level":3,"title":"v2.5.9.2 - 5/19/21","slug":"v2-5-9-2-5-19-21","link":"#v2-5-9-2-5-19-21","children":[]},{"level":3,"title":"v2.5.9.1 - 5/18/21","slug":"v2-5-9-1-5-18-21","link":"#v2-5-9-1-5-18-21","children":[]},{"level":3,"title":"v2.5.9 - 5/18/21","slug":"v2-5-9-5-18-21","link":"#v2-5-9-5-18-21","children":[]},{"level":3,"title":"v2.5.8 - 5/17/21","slug":"v2-5-8-5-17-21","link":"#v2-5-8-5-17-21","children":[]},{"level":3,"title":"v2.5.7 - 5/15/21","slug":"v2-5-7-5-15-21","link":"#v2-5-7-5-15-21","children":[]},{"level":3,"title":"v2.5.6 - 5/14/21","slug":"v2-5-6-5-14-21","link":"#v2-5-6-5-14-21","children":[]},{"level":3,"title":"v2.5.5.2 - 5/12/21","slug":"v2-5-5-2-5-12-21","link":"#v2-5-5-2-5-12-21","children":[]},{"level":3,"title":"v2.5.5.1 - 5/12/21","slug":"v2-5-5-1-5-12-21","link":"#v2-5-5-1-5-12-21","children":[]},{"level":3,"title":"v2.5.5 - 5/12/21","slug":"v2-5-5-5-12-21","link":"#v2-5-5-5-12-21","children":[]},{"level":3,"title":"v2.5.4 - 5/10/21","slug":"v2-5-4-5-10-21","link":"#v2-5-4-5-10-21","children":[]},{"level":3,"title":"v2.5.3 - 5/8/21","slug":"v2-5-3-5-8-21","link":"#v2-5-3-5-8-21","children":[]},{"level":3,"title":"v2.5.2.1 - 5/7/21","slug":"v2-5-2-1-5-7-21","link":"#v2-5-2-1-5-7-21","children":[]},{"level":3,"title":"v2.5.2 - 5/7/21","slug":"v2-5-2-5-7-21","link":"#v2-5-2-5-7-21","children":[]},{"level":3,"title":"v2.5.1 - 5/7/21","slug":"v2-5-1-5-7-21","link":"#v2-5-1-5-7-21","children":[]},{"level":2,"title":"v2.5: Dreams Really Do Come True - 5/7/21","slug":"v2-5-dreams-really-do-come-true-5-7-21","link":"#v2-5-dreams-really-do-come-true-5-7-21","children":[{"level":3,"title":"v2.4.1 - 4/29/21","slug":"v2-4-1-4-29-21","link":"#v2-4-1-4-29-21","children":[]}]},{"level":2,"title":"v2.4: Rationalized Edition - 4/29/21","slug":"v2-4-rationalized-edition-4-29-21","link":"#v2-4-rationalized-edition-4-29-21","children":[{"level":3,"title":"v2.\u03C0.1 - 4/7/21","slug":"v2-\u03C0-1-4-7-21","link":"#v2-\u03C0-1-4-7-21","children":[]}]},{"level":2,"title":"v2.\u03C0: Incrementally Updated - 2/5/21","slug":"v2-\u03C0-incrementally-updated-2-5-21","link":"#v2-\u03C0-incrementally-updated-2-5-21","children":[{"level":3,"title":"v2.3.5 - 12/21/20","slug":"v2-3-5-12-21-20","link":"#v2-3-5-12-21-20","children":[]},{"level":3,"title":"v2.3.4 - 12/16/20","slug":"v2-3-4-12-16-20","link":"#v2-3-4-12-16-20","children":[]},{"level":3,"title":"v2.3.3 - 12/13/20","slug":"v2-3-3-12-13-20","link":"#v2-3-3-12-13-20","children":[]},{"level":3,"title":"v2.3.2 - 12/13/20","slug":"v2-3-2-12-13-20","link":"#v2-3-2-12-13-20","children":[]},{"level":3,"title":"v2.3.1 - 12/12/20","slug":"v2-3-1-12-12-20","link":"#v2-3-1-12-12-20","children":[]}]},{"level":2,"title":"v2.3: Cooler and Newer Edition - 12/10/20","slug":"v2-3-cooler-and-newer-edition-12-10-20","link":"#v2-3-cooler-and-newer-edition-12-10-20","children":[{"level":3,"title":"v2.2.8 - 12/03/20","slug":"v2-2-8-12-03-20","link":"#v2-2-8-12-03-20","children":[]},{"level":3,"title":"v2.2.7 - 11/30/20","slug":"v2-2-7-11-30-20","link":"#v2-2-7-11-30-20","children":[]},{"level":3,"title":"v2.2.6 - 11/30/20","slug":"v2-2-6-11-30-20","link":"#v2-2-6-11-30-20","children":[]},{"level":3,"title":"v2.2.5 - 11/29/20","slug":"v2-2-5-11-29-20","link":"#v2-2-5-11-29-20","children":[]},{"level":3,"title":"v2.2.4 - 11/28/20","slug":"v2-2-4-11-28-20","link":"#v2-2-4-11-28-20","children":[]},{"level":3,"title":"v2.2.3 - 11/28/20","slug":"v2-2-3-11-28-20","link":"#v2-2-3-11-28-20","children":[]},{"level":3,"title":"v2.2.2 - 11/22/20","slug":"v2-2-2-11-22-20","link":"#v2-2-2-11-22-20","children":[]},{"level":3,"title":"v2.2.1 - 11/7/20","slug":"v2-2-1-11-7-20","link":"#v2-2-1-11-7-20","children":[]}]},{"level":2,"title":"v2.2: Uprooted - 11/7/20","slug":"v2-2-uprooted-11-7-20","link":"#v2-2-uprooted-11-7-20","children":[{"level":3,"title":"v2.1.4 - 10/25/20","slug":"v2-1-4-10-25-20","link":"#v2-1-4-10-25-20","children":[]},{"level":3,"title":"v2.1.3.1 - 10/21/20","slug":"v2-1-3-1-10-21-20","link":"#v2-1-3-1-10-21-20","children":[]},{"level":3,"title":"v2.1.3 - 10/21/20","slug":"v2-1-3-10-21-20","link":"#v2-1-3-10-21-20","children":[]},{"level":3,"title":"v2.1.2 - 10/19/20","slug":"v2-1-2-10-19-20","link":"#v2-1-2-10-19-20","children":[]},{"level":3,"title":"v2.1.1 - 10/17/20","slug":"v2-1-1-10-17-20","link":"#v2-1-1-10-17-20","children":[]}]},{"level":2,"title":"v2.1: We should have thought of this sooner! - 10/17/20","slug":"v2-1-we-should-have-thought-of-this-sooner-10-17-20","link":"#v2-1-we-should-have-thought-of-this-sooner-10-17-20","children":[{"level":3,"title":"v2.0.5 - 10/16/20","slug":"v2-0-5-10-16-20","link":"#v2-0-5-10-16-20","children":[]},{"level":3,"title":"v2.0.4 - 10/16/20","slug":"v2-0-4-10-16-20","link":"#v2-0-4-10-16-20","children":[]},{"level":3,"title":"v2.0.3 - 10/16/20","slug":"v2-0-3-10-16-20","link":"#v2-0-3-10-16-20","children":[]},{"level":3,"title":"v2.0.2 - 10/15/20","slug":"v2-0-2-10-15-20","link":"#v2-0-2-10-15-20","children":[]},{"level":3,"title":"v2.0.1 - 10/15/20","slug":"v2-0-1-10-15-20","link":"#v2-0-1-10-15-20","children":[]}]},{"level":2,"title":"v2.0: The Pinnacle of Achievement Mountain - 10/15/20","slug":"v2-0-the-pinnacle-of-achievement-mountain-10-15-20","link":"#v2-0-the-pinnacle-of-achievement-mountain-10-15-20","children":[{"level":3,"title":"v1.3.5:","slug":"v1-3-5","link":"#v1-3-5","children":[]},{"level":3,"title":"v1.3.4 - 10/8/20","slug":"v1-3-4-10-8-20","link":"#v1-3-4-10-8-20","children":[]},{"level":3,"title":"v1.3.3 - 10/7/20","slug":"v1-3-3-10-7-20","link":"#v1-3-3-10-7-20","children":[]},{"level":3,"title":"v1.3.1 - 10/7/20","slug":"v1-3-1-10-7-20","link":"#v1-3-1-10-7-20","children":[]}]},{"level":2,"title":"v1.3: Tabception... ception! - 10/7/20","slug":"v1-3-tabception-ception-10-7-20","link":"#v1-3-tabception-ception-10-7-20","children":[{"level":3,"title":"v1.2.4 - 10/4/20","slug":"v1-2-4-10-4-20","link":"#v1-2-4-10-4-20","children":[]},{"level":3,"title":"v1.2.3 - 10/3/20","slug":"v1-2-3-10-3-20","link":"#v1-2-3-10-3-20","children":[]}]},{"level":2,"title":"v1.2: This Changes Everything! - 10/3/20","slug":"v1-2-this-changes-everything-10-3-20","link":"#v1-2-this-changes-everything-10-3-20","children":[{"level":3,"title":"v1.1.1 - 9/30/20","slug":"v1-1-1-9-30-20","link":"#v1-1-1-9-30-20","children":[]}]},{"level":2,"title":"v1.1: Enhanced Edition - 9/30/20","slug":"v1-1-enhanced-edition-9-30-20","link":"#v1-1-enhanced-edition-9-30-20","children":[]},{"level":2,"title":"v1.0 - 9/27/20","slug":"v1-0-9-27-20","link":"#v1-0-9-27-20","children":[]}],"relativePath":"public/kronos/changelog.md","lastUpdated":null}'),t={name:"public/kronos/changelog.md"},n=a("",115),o=[n];function d(r,s,h,u,c,v){return l(),i("div",null,o)}const g=e(t,[["render",d]]);export{m as __pageData,g as default}; +import{_ as e,c as i,o as l,a}from"./app.9bfeb8de.js";const m=JSON.parse('{"title":"The Modding Tree changelog:","description":"","frontmatter":{},"headers":[{"level":3,"title":"v2.5.9.2 - 5/19/21","slug":"v2-5-9-2-5-19-21","link":"#v2-5-9-2-5-19-21","children":[]},{"level":3,"title":"v2.5.9.1 - 5/18/21","slug":"v2-5-9-1-5-18-21","link":"#v2-5-9-1-5-18-21","children":[]},{"level":3,"title":"v2.5.9 - 5/18/21","slug":"v2-5-9-5-18-21","link":"#v2-5-9-5-18-21","children":[]},{"level":3,"title":"v2.5.8 - 5/17/21","slug":"v2-5-8-5-17-21","link":"#v2-5-8-5-17-21","children":[]},{"level":3,"title":"v2.5.7 - 5/15/21","slug":"v2-5-7-5-15-21","link":"#v2-5-7-5-15-21","children":[]},{"level":3,"title":"v2.5.6 - 5/14/21","slug":"v2-5-6-5-14-21","link":"#v2-5-6-5-14-21","children":[]},{"level":3,"title":"v2.5.5.2 - 5/12/21","slug":"v2-5-5-2-5-12-21","link":"#v2-5-5-2-5-12-21","children":[]},{"level":3,"title":"v2.5.5.1 - 5/12/21","slug":"v2-5-5-1-5-12-21","link":"#v2-5-5-1-5-12-21","children":[]},{"level":3,"title":"v2.5.5 - 5/12/21","slug":"v2-5-5-5-12-21","link":"#v2-5-5-5-12-21","children":[]},{"level":3,"title":"v2.5.4 - 5/10/21","slug":"v2-5-4-5-10-21","link":"#v2-5-4-5-10-21","children":[]},{"level":3,"title":"v2.5.3 - 5/8/21","slug":"v2-5-3-5-8-21","link":"#v2-5-3-5-8-21","children":[]},{"level":3,"title":"v2.5.2.1 - 5/7/21","slug":"v2-5-2-1-5-7-21","link":"#v2-5-2-1-5-7-21","children":[]},{"level":3,"title":"v2.5.2 - 5/7/21","slug":"v2-5-2-5-7-21","link":"#v2-5-2-5-7-21","children":[]},{"level":3,"title":"v2.5.1 - 5/7/21","slug":"v2-5-1-5-7-21","link":"#v2-5-1-5-7-21","children":[]},{"level":2,"title":"v2.5: Dreams Really Do Come True - 5/7/21","slug":"v2-5-dreams-really-do-come-true-5-7-21","link":"#v2-5-dreams-really-do-come-true-5-7-21","children":[{"level":3,"title":"v2.4.1 - 4/29/21","slug":"v2-4-1-4-29-21","link":"#v2-4-1-4-29-21","children":[]}]},{"level":2,"title":"v2.4: Rationalized Edition - 4/29/21","slug":"v2-4-rationalized-edition-4-29-21","link":"#v2-4-rationalized-edition-4-29-21","children":[{"level":3,"title":"v2.\u03C0.1 - 4/7/21","slug":"v2-\u03C0-1-4-7-21","link":"#v2-\u03C0-1-4-7-21","children":[]}]},{"level":2,"title":"v2.\u03C0: Incrementally Updated - 2/5/21","slug":"v2-\u03C0-incrementally-updated-2-5-21","link":"#v2-\u03C0-incrementally-updated-2-5-21","children":[{"level":3,"title":"v2.3.5 - 12/21/20","slug":"v2-3-5-12-21-20","link":"#v2-3-5-12-21-20","children":[]},{"level":3,"title":"v2.3.4 - 12/16/20","slug":"v2-3-4-12-16-20","link":"#v2-3-4-12-16-20","children":[]},{"level":3,"title":"v2.3.3 - 12/13/20","slug":"v2-3-3-12-13-20","link":"#v2-3-3-12-13-20","children":[]},{"level":3,"title":"v2.3.2 - 12/13/20","slug":"v2-3-2-12-13-20","link":"#v2-3-2-12-13-20","children":[]},{"level":3,"title":"v2.3.1 - 12/12/20","slug":"v2-3-1-12-12-20","link":"#v2-3-1-12-12-20","children":[]}]},{"level":2,"title":"v2.3: Cooler and Newer Edition - 12/10/20","slug":"v2-3-cooler-and-newer-edition-12-10-20","link":"#v2-3-cooler-and-newer-edition-12-10-20","children":[{"level":3,"title":"v2.2.8 - 12/03/20","slug":"v2-2-8-12-03-20","link":"#v2-2-8-12-03-20","children":[]},{"level":3,"title":"v2.2.7 - 11/30/20","slug":"v2-2-7-11-30-20","link":"#v2-2-7-11-30-20","children":[]},{"level":3,"title":"v2.2.6 - 11/30/20","slug":"v2-2-6-11-30-20","link":"#v2-2-6-11-30-20","children":[]},{"level":3,"title":"v2.2.5 - 11/29/20","slug":"v2-2-5-11-29-20","link":"#v2-2-5-11-29-20","children":[]},{"level":3,"title":"v2.2.4 - 11/28/20","slug":"v2-2-4-11-28-20","link":"#v2-2-4-11-28-20","children":[]},{"level":3,"title":"v2.2.3 - 11/28/20","slug":"v2-2-3-11-28-20","link":"#v2-2-3-11-28-20","children":[]},{"level":3,"title":"v2.2.2 - 11/22/20","slug":"v2-2-2-11-22-20","link":"#v2-2-2-11-22-20","children":[]},{"level":3,"title":"v2.2.1 - 11/7/20","slug":"v2-2-1-11-7-20","link":"#v2-2-1-11-7-20","children":[]}]},{"level":2,"title":"v2.2: Uprooted - 11/7/20","slug":"v2-2-uprooted-11-7-20","link":"#v2-2-uprooted-11-7-20","children":[{"level":3,"title":"v2.1.4 - 10/25/20","slug":"v2-1-4-10-25-20","link":"#v2-1-4-10-25-20","children":[]},{"level":3,"title":"v2.1.3.1 - 10/21/20","slug":"v2-1-3-1-10-21-20","link":"#v2-1-3-1-10-21-20","children":[]},{"level":3,"title":"v2.1.3 - 10/21/20","slug":"v2-1-3-10-21-20","link":"#v2-1-3-10-21-20","children":[]},{"level":3,"title":"v2.1.2 - 10/19/20","slug":"v2-1-2-10-19-20","link":"#v2-1-2-10-19-20","children":[]},{"level":3,"title":"v2.1.1 - 10/17/20","slug":"v2-1-1-10-17-20","link":"#v2-1-1-10-17-20","children":[]}]},{"level":2,"title":"v2.1: We should have thought of this sooner! - 10/17/20","slug":"v2-1-we-should-have-thought-of-this-sooner-10-17-20","link":"#v2-1-we-should-have-thought-of-this-sooner-10-17-20","children":[{"level":3,"title":"v2.0.5 - 10/16/20","slug":"v2-0-5-10-16-20","link":"#v2-0-5-10-16-20","children":[]},{"level":3,"title":"v2.0.4 - 10/16/20","slug":"v2-0-4-10-16-20","link":"#v2-0-4-10-16-20","children":[]},{"level":3,"title":"v2.0.3 - 10/16/20","slug":"v2-0-3-10-16-20","link":"#v2-0-3-10-16-20","children":[]},{"level":3,"title":"v2.0.2 - 10/15/20","slug":"v2-0-2-10-15-20","link":"#v2-0-2-10-15-20","children":[]},{"level":3,"title":"v2.0.1 - 10/15/20","slug":"v2-0-1-10-15-20","link":"#v2-0-1-10-15-20","children":[]}]},{"level":2,"title":"v2.0: The Pinnacle of Achievement Mountain - 10/15/20","slug":"v2-0-the-pinnacle-of-achievement-mountain-10-15-20","link":"#v2-0-the-pinnacle-of-achievement-mountain-10-15-20","children":[{"level":3,"title":"v1.3.5:","slug":"v1-3-5","link":"#v1-3-5","children":[]},{"level":3,"title":"v1.3.4 - 10/8/20","slug":"v1-3-4-10-8-20","link":"#v1-3-4-10-8-20","children":[]},{"level":3,"title":"v1.3.3 - 10/7/20","slug":"v1-3-3-10-7-20","link":"#v1-3-3-10-7-20","children":[]},{"level":3,"title":"v1.3.1 - 10/7/20","slug":"v1-3-1-10-7-20","link":"#v1-3-1-10-7-20","children":[]}]},{"level":2,"title":"v1.3: Tabception... ception! - 10/7/20","slug":"v1-3-tabception-ception-10-7-20","link":"#v1-3-tabception-ception-10-7-20","children":[{"level":3,"title":"v1.2.4 - 10/4/20","slug":"v1-2-4-10-4-20","link":"#v1-2-4-10-4-20","children":[]},{"level":3,"title":"v1.2.3 - 10/3/20","slug":"v1-2-3-10-3-20","link":"#v1-2-3-10-3-20","children":[]}]},{"level":2,"title":"v1.2: This Changes Everything! - 10/3/20","slug":"v1-2-this-changes-everything-10-3-20","link":"#v1-2-this-changes-everything-10-3-20","children":[{"level":3,"title":"v1.1.1 - 9/30/20","slug":"v1-1-1-9-30-20","link":"#v1-1-1-9-30-20","children":[]}]},{"level":2,"title":"v1.1: Enhanced Edition - 9/30/20","slug":"v1-1-enhanced-edition-9-30-20","link":"#v1-1-enhanced-edition-9-30-20","children":[]},{"level":2,"title":"v1.0 - 9/27/20","slug":"v1-0-9-27-20","link":"#v1-0-9-27-20","children":[]}],"relativePath":"public/kronos/changelog.md","lastUpdated":null}'),t={name:"public/kronos/changelog.md"},n=a("",115),o=[n];function d(r,s,h,u,c,v){return l(),i("div",null,o)}const g=e(t,[["render",d]]);export{m as __pageData,g as default}; diff --git a/assets/public_kronos_docs_!general-info.md.e82f5cd3.js b/assets/public_kronos_docs_!general-info.md.82616e2a.js similarity index 99% rename from assets/public_kronos_docs_!general-info.md.e82f5cd3.js rename to assets/public_kronos_docs_!general-info.md.82616e2a.js index c000b9e39..415186bc1 100644 --- a/assets/public_kronos_docs_!general-info.md.e82f5cd3.js +++ b/assets/public_kronos_docs_!general-info.md.82616e2a.js @@ -1 +1 @@ -import{_ as e,c as a,o as t,a as o}from"./app.a576d425.js";const g=JSON.parse('{"title":"The-Modding-Tree","description":"","frontmatter":{},"headers":[{"level":2,"title":"Table of Contents","slug":"table-of-contents","link":"#table-of-contents","children":[{"level":3,"title":"General","slug":"general","link":"#general","children":[]},{"level":3,"title":"Common components","slug":"common-components","link":"#common-components","children":[]},{"level":3,"title":"Other components and features","slug":"other-components-and-features","link":"#other-components-and-features","children":[]}]}],"relativePath":"public/kronos/docs/!general-info.md","lastUpdated":null}'),n={name:"public/kronos/docs/!general-info.md"},r=o('

      The-Modding-Tree

      Making a game in The Modding Tree mostly involves defining parameters or functions on objects. If you aren't following the getting started guide, you should start by setting up your basic mod info in mod.js. It's important to set a mod id to ensure saving works properly.

      Beyond that, the main way to add content is through creating layers, often in layers.js. You can add new layers by calling addLayer(layername, layerdata). There is an example of a basic layer in layers.js showing the recommended method. It is just an example and can be freely deleted. You can also use it as a reference or a base for your own layers.

      Most of the time, you won't need to dive deep into the code to create things, but you still can if you really want to, for example to add new Vue components in components.js.

      The Modding Tree uses break_eternity.js to store large values. This means that many numbers are Decimal objects, and must be treated differently. For example, you have to use new Decimal(x) to create a Decimal value instead of a plain number, and perform operations on them by calling functions. e.g, instead of x = x + y, use x = x.add(y). Keep in mind this also applies to comparison operators, which should be replaced with calling the .gt, .gte, .lt, .lte, .eq, and .neq functions. See the break_eternity.js docs for more details on working with Decimal values.

      Almost all values can be either a constant value, or a dynamic value. Dynamic values are defined by putting a function that returns what the value should be at any given time.

      All display text can use basic HTML elements (But you can't use most Vue features there).

      While reading this documentation, the following key will be used when describing features:

      • No label: This is required and the game may crash if it isn't included.
      • sometimes required: This is may be required, depending on other things in the layer.
      • optional: You can leave this out if you don't intend to use that feature for the layer.
      • assigned automagically: This value will be set automatically and override any value you set.
      • deprecated: This feature is not recommended to be used, because newer features are able to achieve the same thing in a better, easier way.

      Table of Contents

      General

      • Getting Started: Getting your own copy of the code set up with Github Desktop.
      • Main mod info: How to set up general things for your mod in mod.js.
      • Basic layer breakdown: Breaking down the components of a layer with minimal features.
      • Layer features: Explanations of all of the different properties that you can give a layer.
      • Custom Tab Layouts: An optional way to give your tabs a different layout. You can even create entirely new components to use.
      • Custom game layouts: You can get rid of the tree tab, add buttons and other things to the tree, or even customize the tab's layout like a layer tab.
      • Updating TMT: Using Github Desktop to update your mod's version of TMT.

      Common components

      • Upgrades: How to create upgrades for a layer.
      • Milestones: How to create milestones for a layer.
      • Buyables: Create rebuyable upgrades for your layer (with the option to make them respec-able). Can be used to make Enhancers or Space Buildings, for example.
      • Clickables: A more generalized variant of buyables, for any kind of thing that is sometimes clickable. Between these and Buyables, you can do just about anything.
      • Achievements: How to create achievements for a layer (or for the whole game).

      Other components and features

      • Challenges: How to create challenges for a layer.
      • Bars: Display some information as a progress bar, gauge, or similar. They are highly customizable, and can be horizontal and vertical as well.
      • Subtabs and Microtabs: Create subtabs for your tabs, as well as "microtab" components that you can put inside the tabs. You can even use them to embed a layer inside another layer!
      • [Grids][grids.md]: Create a group buttons that behave the same, but have their own data. Good for map tiles, an inventory grid, and more!
      • Infoboxes: Boxes containing text that can be shown or hidden.
      • Trees: Make your own trees. You can make non-layer button nodes too!
      • Particle system: Can be used to create particles for visual effects, but also interactable things like golden cookies or collectables.
      ',16),s=[r];function i(l,d,c,h,u,m){return t(),a("div",null,s)}const b=e(n,[["render",i]]);export{g as __pageData,b as default}; +import{_ as e,c as a,o as t,a as o}from"./app.9bfeb8de.js";const g=JSON.parse('{"title":"The-Modding-Tree","description":"","frontmatter":{},"headers":[{"level":2,"title":"Table of Contents","slug":"table-of-contents","link":"#table-of-contents","children":[{"level":3,"title":"General","slug":"general","link":"#general","children":[]},{"level":3,"title":"Common components","slug":"common-components","link":"#common-components","children":[]},{"level":3,"title":"Other components and features","slug":"other-components-and-features","link":"#other-components-and-features","children":[]}]}],"relativePath":"public/kronos/docs/!general-info.md","lastUpdated":null}'),n={name:"public/kronos/docs/!general-info.md"},r=o('

      The-Modding-Tree

      Making a game in The Modding Tree mostly involves defining parameters or functions on objects. If you aren't following the getting started guide, you should start by setting up your basic mod info in mod.js. It's important to set a mod id to ensure saving works properly.

      Beyond that, the main way to add content is through creating layers, often in layers.js. You can add new layers by calling addLayer(layername, layerdata). There is an example of a basic layer in layers.js showing the recommended method. It is just an example and can be freely deleted. You can also use it as a reference or a base for your own layers.

      Most of the time, you won't need to dive deep into the code to create things, but you still can if you really want to, for example to add new Vue components in components.js.

      The Modding Tree uses break_eternity.js to store large values. This means that many numbers are Decimal objects, and must be treated differently. For example, you have to use new Decimal(x) to create a Decimal value instead of a plain number, and perform operations on them by calling functions. e.g, instead of x = x + y, use x = x.add(y). Keep in mind this also applies to comparison operators, which should be replaced with calling the .gt, .gte, .lt, .lte, .eq, and .neq functions. See the break_eternity.js docs for more details on working with Decimal values.

      Almost all values can be either a constant value, or a dynamic value. Dynamic values are defined by putting a function that returns what the value should be at any given time.

      All display text can use basic HTML elements (But you can't use most Vue features there).

      While reading this documentation, the following key will be used when describing features:

      • No label: This is required and the game may crash if it isn't included.
      • sometimes required: This is may be required, depending on other things in the layer.
      • optional: You can leave this out if you don't intend to use that feature for the layer.
      • assigned automagically: This value will be set automatically and override any value you set.
      • deprecated: This feature is not recommended to be used, because newer features are able to achieve the same thing in a better, easier way.

      Table of Contents

      General

      • Getting Started: Getting your own copy of the code set up with Github Desktop.
      • Main mod info: How to set up general things for your mod in mod.js.
      • Basic layer breakdown: Breaking down the components of a layer with minimal features.
      • Layer features: Explanations of all of the different properties that you can give a layer.
      • Custom Tab Layouts: An optional way to give your tabs a different layout. You can even create entirely new components to use.
      • Custom game layouts: You can get rid of the tree tab, add buttons and other things to the tree, or even customize the tab's layout like a layer tab.
      • Updating TMT: Using Github Desktop to update your mod's version of TMT.

      Common components

      • Upgrades: How to create upgrades for a layer.
      • Milestones: How to create milestones for a layer.
      • Buyables: Create rebuyable upgrades for your layer (with the option to make them respec-able). Can be used to make Enhancers or Space Buildings, for example.
      • Clickables: A more generalized variant of buyables, for any kind of thing that is sometimes clickable. Between these and Buyables, you can do just about anything.
      • Achievements: How to create achievements for a layer (or for the whole game).

      Other components and features

      • Challenges: How to create challenges for a layer.
      • Bars: Display some information as a progress bar, gauge, or similar. They are highly customizable, and can be horizontal and vertical as well.
      • Subtabs and Microtabs: Create subtabs for your tabs, as well as "microtab" components that you can put inside the tabs. You can even use them to embed a layer inside another layer!
      • [Grids][grids.md]: Create a group buttons that behave the same, but have their own data. Good for map tiles, an inventory grid, and more!
      • Infoboxes: Boxes containing text that can be shown or hidden.
      • Trees: Make your own trees. You can make non-layer button nodes too!
      • Particle system: Can be used to create particles for visual effects, but also interactable things like golden cookies or collectables.
      ',16),s=[r];function i(l,d,c,h,u,m){return t(),a("div",null,s)}const b=e(n,[["render",i]]);export{g as __pageData,b as default}; diff --git a/assets/public_kronos_docs_!general-info.md.e82f5cd3.lean.js b/assets/public_kronos_docs_!general-info.md.82616e2a.lean.js similarity index 92% rename from assets/public_kronos_docs_!general-info.md.e82f5cd3.lean.js rename to assets/public_kronos_docs_!general-info.md.82616e2a.lean.js index a446cfb4f..0b56cdace 100644 --- a/assets/public_kronos_docs_!general-info.md.e82f5cd3.lean.js +++ b/assets/public_kronos_docs_!general-info.md.82616e2a.lean.js @@ -1 +1 @@ -import{_ as e,c as a,o as t,a as o}from"./app.a576d425.js";const g=JSON.parse('{"title":"The-Modding-Tree","description":"","frontmatter":{},"headers":[{"level":2,"title":"Table of Contents","slug":"table-of-contents","link":"#table-of-contents","children":[{"level":3,"title":"General","slug":"general","link":"#general","children":[]},{"level":3,"title":"Common components","slug":"common-components","link":"#common-components","children":[]},{"level":3,"title":"Other components and features","slug":"other-components-and-features","link":"#other-components-and-features","children":[]}]}],"relativePath":"public/kronos/docs/!general-info.md","lastUpdated":null}'),n={name:"public/kronos/docs/!general-info.md"},r=o("",16),s=[r];function i(l,d,c,h,u,m){return t(),a("div",null,s)}const b=e(n,[["render",i]]);export{g as __pageData,b as default}; +import{_ as e,c as a,o as t,a as o}from"./app.9bfeb8de.js";const g=JSON.parse('{"title":"The-Modding-Tree","description":"","frontmatter":{},"headers":[{"level":2,"title":"Table of Contents","slug":"table-of-contents","link":"#table-of-contents","children":[{"level":3,"title":"General","slug":"general","link":"#general","children":[]},{"level":3,"title":"Common components","slug":"common-components","link":"#common-components","children":[]},{"level":3,"title":"Other components and features","slug":"other-components-and-features","link":"#other-components-and-features","children":[]}]}],"relativePath":"public/kronos/docs/!general-info.md","lastUpdated":null}'),n={name:"public/kronos/docs/!general-info.md"},r=o("",16),s=[r];function i(l,d,c,h,u,m){return t(),a("div",null,s)}const b=e(n,[["render",i]]);export{g as __pageData,b as default}; diff --git a/assets/public_kronos_docs_achievements.md.9dd93db1.js b/assets/public_kronos_docs_achievements.md.bf4e3304.js similarity index 98% rename from assets/public_kronos_docs_achievements.md.9dd93db1.js rename to assets/public_kronos_docs_achievements.md.bf4e3304.js index db25e660e..7a0635b43 100644 --- a/assets/public_kronos_docs_achievements.md.9dd93db1.js +++ b/assets/public_kronos_docs_achievements.md.bf4e3304.js @@ -1,4 +1,4 @@ -import{_ as e,c as t,o as a,a as n}from"./app.a576d425.js";const v=JSON.parse('{"title":"Achievements","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/achievements.md","lastUpdated":null}'),s={name:"public/kronos/docs/achievements.md"},o=n(`

      Achievements

      Achievements are awarded to the player when they meet a certain goal, and optionally give some benefit.

      You can make global achievements by putting them in a side layer by making its row equal to "side" instead of a number.

      Useful functions for dealing with achievements and implementing their effects:

      • hasAchievement(layer, id): determine if the player has the Achievement.
      • achievementEffect(layer, id): Returns the current effects of the achievement, if any.

      Achievements should be formatted like this:

      js
      achievements: {
      +import{_ as e,c as t,o as a,a as n}from"./app.9bfeb8de.js";const v=JSON.parse('{"title":"Achievements","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/achievements.md","lastUpdated":null}'),s={name:"public/kronos/docs/achievements.md"},o=n(`

      Achievements

      Achievements are awarded to the player when they meet a certain goal, and optionally give some benefit.

      You can make global achievements by putting them in a side layer by making its row equal to "side" instead of a number.

      Useful functions for dealing with achievements and implementing their effects:

      • hasAchievement(layer, id): determine if the player has the Achievement.
      • achievementEffect(layer, id): Returns the current effects of the achievement, if any.

      Achievements should be formatted like this:

      js
      achievements: {
           11: {
               name: "Blah",
               more features
      diff --git a/assets/public_kronos_docs_achievements.md.9dd93db1.lean.js b/assets/public_kronos_docs_achievements.md.bf4e3304.lean.js
      similarity index 84%
      rename from assets/public_kronos_docs_achievements.md.9dd93db1.lean.js
      rename to assets/public_kronos_docs_achievements.md.bf4e3304.lean.js
      index 0a50fb940..55ebd574a 100644
      --- a/assets/public_kronos_docs_achievements.md.9dd93db1.lean.js
      +++ b/assets/public_kronos_docs_achievements.md.bf4e3304.lean.js
      @@ -1 +1 @@
      -import{_ as e,c as t,o as a,a as n}from"./app.a576d425.js";const v=JSON.parse('{"title":"Achievements","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/achievements.md","lastUpdated":null}'),s={name:"public/kronos/docs/achievements.md"},o=n("",11),i=[o];function l(p,r,c,h,d,u){return a(),t("div",null,i)}const g=e(s,[["render",l]]);export{v as __pageData,g as default};
      +import{_ as e,c as t,o as a,a as n}from"./app.9bfeb8de.js";const v=JSON.parse('{"title":"Achievements","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/achievements.md","lastUpdated":null}'),s={name:"public/kronos/docs/achievements.md"},o=n("",11),i=[o];function l(p,r,c,h,d,u){return a(),t("div",null,i)}const g=e(s,[["render",l]]);export{v as __pageData,g as default};
      diff --git a/assets/public_kronos_docs_bars.md.7a2fdc93.js b/assets/public_kronos_docs_bars.md.475709df.js
      similarity index 98%
      rename from assets/public_kronos_docs_bars.md.7a2fdc93.js
      rename to assets/public_kronos_docs_bars.md.475709df.js
      index 8292e6616..6e86dc39b 100644
      --- a/assets/public_kronos_docs_bars.md.7a2fdc93.js
      +++ b/assets/public_kronos_docs_bars.md.475709df.js
      @@ -1,4 +1,4 @@
      -import{_ as s,c as a,o as n,a as e}from"./app.a576d425.js";const u=JSON.parse('{"title":"Bars","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/bars.md","lastUpdated":null}'),o={name:"public/kronos/docs/bars.md"},t=e(`

      Bars

      Bars let you display information in a more direct way. It can be a progress bar, health bar, capacity gauge, or anything else.

      Bars are defined like other Big Features:

      js
      bars: {
      +import{_ as s,c as a,o as n,a as e}from"./app.9bfeb8de.js";const u=JSON.parse('{"title":"Bars","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/bars.md","lastUpdated":null}'),o={name:"public/kronos/docs/bars.md"},t=e(`

      Bars

      Bars let you display information in a more direct way. It can be a progress bar, health bar, capacity gauge, or anything else.

      Bars are defined like other Big Features:

      js
      bars: {
           bigBar: {
               direction: RIGHT,
               width: 200,
      diff --git a/assets/public_kronos_docs_bars.md.7a2fdc93.lean.js b/assets/public_kronos_docs_bars.md.475709df.lean.js
      similarity index 83%
      rename from assets/public_kronos_docs_bars.md.7a2fdc93.lean.js
      rename to assets/public_kronos_docs_bars.md.475709df.lean.js
      index 740d5fa37..01daa2c6d 100644
      --- a/assets/public_kronos_docs_bars.md.7a2fdc93.lean.js
      +++ b/assets/public_kronos_docs_bars.md.475709df.lean.js
      @@ -1 +1 @@
      -import{_ as s,c as a,o as n,a as e}from"./app.a576d425.js";const u=JSON.parse('{"title":"Bars","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/bars.md","lastUpdated":null}'),o={name:"public/kronos/docs/bars.md"},t=e("",6),l=[t];function p(r,i,c,y,d,F){return n(),a("div",null,l)}const b=s(o,[["render",p]]);export{u as __pageData,b as default};
      +import{_ as s,c as a,o as n,a as e}from"./app.9bfeb8de.js";const u=JSON.parse('{"title":"Bars","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/bars.md","lastUpdated":null}'),o={name:"public/kronos/docs/bars.md"},t=e("",6),l=[t];function p(r,i,c,y,d,F){return n(),a("div",null,l)}const b=s(o,[["render",p]]);export{u as __pageData,b as default};
      diff --git a/assets/public_kronos_docs_basic-layer-breakdown.md.41933053.js b/assets/public_kronos_docs_basic-layer-breakdown.md.7754454e.js
      similarity index 99%
      rename from assets/public_kronos_docs_basic-layer-breakdown.md.41933053.js
      rename to assets/public_kronos_docs_basic-layer-breakdown.md.7754454e.js
      index e06f82506..85f8039d2 100644
      --- a/assets/public_kronos_docs_basic-layer-breakdown.md.41933053.js
      +++ b/assets/public_kronos_docs_basic-layer-breakdown.md.7754454e.js
      @@ -1,4 +1,4 @@
      -import{_ as s,c as n,o as a,a as o}from"./app.a576d425.js";const A=JSON.parse('{"title":"Basic layer breakdown","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/basic-layer-breakdown.md","lastUpdated":null}'),l={name:"public/kronos/docs/basic-layer-breakdown.md"},p=o(`

      Basic layer breakdown

      This is a very minimal layer with minimal features. Most things will require additional features.

      js
      addLayer("p", {
      +import{_ as s,c as n,o as a,a as o}from"./app.9bfeb8de.js";const A=JSON.parse('{"title":"Basic layer breakdown","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/basic-layer-breakdown.md","lastUpdated":null}'),l={name:"public/kronos/docs/basic-layer-breakdown.md"},p=o(`

      Basic layer breakdown

      This is a very minimal layer with minimal features. Most things will require additional features.

      js
      addLayer("p", {
           startData() { return {                  // startData is a function that returns default data for a layer. 
               unlocked: true,                     // You can add more variables here to add them to your layer.
               points: new Decimal(0),             // "points" is the internal name for the main resource of the layer.
      diff --git a/assets/public_kronos_docs_basic-layer-breakdown.md.41933053.lean.js b/assets/public_kronos_docs_basic-layer-breakdown.md.7754454e.lean.js
      similarity index 85%
      rename from assets/public_kronos_docs_basic-layer-breakdown.md.41933053.lean.js
      rename to assets/public_kronos_docs_basic-layer-breakdown.md.7754454e.lean.js
      index f6618cf8f..41ecd8c5d 100644
      --- a/assets/public_kronos_docs_basic-layer-breakdown.md.41933053.lean.js
      +++ b/assets/public_kronos_docs_basic-layer-breakdown.md.7754454e.lean.js
      @@ -1 +1 @@
      -import{_ as s,c as n,o as a,a as o}from"./app.a576d425.js";const A=JSON.parse('{"title":"Basic layer breakdown","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/basic-layer-breakdown.md","lastUpdated":null}'),l={name:"public/kronos/docs/basic-layer-breakdown.md"},p=o("",3),e=[p];function r(t,c,y,F,D,i){return a(),n("div",null,e)}const u=s(l,[["render",r]]);export{A as __pageData,u as default};
      +import{_ as s,c as n,o as a,a as o}from"./app.9bfeb8de.js";const A=JSON.parse('{"title":"Basic layer breakdown","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/basic-layer-breakdown.md","lastUpdated":null}'),l={name:"public/kronos/docs/basic-layer-breakdown.md"},p=o("",3),e=[p];function r(t,c,y,F,D,i){return a(),n("div",null,e)}const u=s(l,[["render",r]]);export{A as __pageData,u as default};
      diff --git a/assets/public_kronos_docs_buyables.md.76e7a5af.js b/assets/public_kronos_docs_buyables.md.3875aedf.js
      similarity index 99%
      rename from assets/public_kronos_docs_buyables.md.76e7a5af.js
      rename to assets/public_kronos_docs_buyables.md.3875aedf.js
      index be02daa4a..99233f79e 100644
      --- a/assets/public_kronos_docs_buyables.md.76e7a5af.js
      +++ b/assets/public_kronos_docs_buyables.md.3875aedf.js
      @@ -1,4 +1,4 @@
      -import{_ as s,c as a,o as n,a as e}from"./app.a576d425.js";const b=JSON.parse('{"title":"Buyables","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/buyables.md","lastUpdated":null}'),l={name:"public/kronos/docs/buyables.md"},o=e(`

      Buyables

      Buyables are usually things that can be bought multiple times with scaling costs. They come with optional buttons that can be used for respeccing or selling buyables, among other things.

      The amount of a buyable owned is a Decimal.

      Useful functions for dealing with buyables and implementing their effects:

      • getBuyableAmount(layer, id): get the amount of the buyable the player has
      • setBuyableAmount(layer, id, amount): set the amount of the buyable the player has
      • buyableEffect(layer, id): Returns the current effects of the buyable, if any.

      Buyables should be formatted like this:

      js
      buyables: {
      +import{_ as s,c as a,o as n,a as e}from"./app.9bfeb8de.js";const b=JSON.parse('{"title":"Buyables","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/buyables.md","lastUpdated":null}'),l={name:"public/kronos/docs/buyables.md"},o=e(`

      Buyables

      Buyables are usually things that can be bought multiple times with scaling costs. They come with optional buttons that can be used for respeccing or selling buyables, among other things.

      The amount of a buyable owned is a Decimal.

      Useful functions for dealing with buyables and implementing their effects:

      • getBuyableAmount(layer, id): get the amount of the buyable the player has
      • setBuyableAmount(layer, id, amount): set the amount of the buyable the player has
      • buyableEffect(layer, id): Returns the current effects of the buyable, if any.

      Buyables should be formatted like this:

      js
      buyables: {
           11: {
               cost(x) { return new Decimal(1).mul(x) },
               display() { return "Blah" },
      diff --git a/assets/public_kronos_docs_buyables.md.76e7a5af.lean.js b/assets/public_kronos_docs_buyables.md.3875aedf.lean.js
      similarity index 83%
      rename from assets/public_kronos_docs_buyables.md.76e7a5af.lean.js
      rename to assets/public_kronos_docs_buyables.md.3875aedf.lean.js
      index 95879eb30..f56b07071 100644
      --- a/assets/public_kronos_docs_buyables.md.76e7a5af.lean.js
      +++ b/assets/public_kronos_docs_buyables.md.3875aedf.lean.js
      @@ -1 +1 @@
      -import{_ as s,c as a,o as n,a as e}from"./app.a576d425.js";const b=JSON.parse('{"title":"Buyables","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/buyables.md","lastUpdated":null}'),l={name:"public/kronos/docs/buyables.md"},o=e("",14),t=[o];function p(r,c,i,y,u,F){return n(),a("div",null,t)}const D=s(l,[["render",p]]);export{b as __pageData,D as default};
      +import{_ as s,c as a,o as n,a as e}from"./app.9bfeb8de.js";const b=JSON.parse('{"title":"Buyables","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/buyables.md","lastUpdated":null}'),l={name:"public/kronos/docs/buyables.md"},o=e("",14),t=[o];function p(r,c,i,y,u,F){return n(),a("div",null,t)}const D=s(l,[["render",p]]);export{b as __pageData,D as default};
      diff --git a/assets/public_kronos_docs_challenges.md.c5401b51.js b/assets/public_kronos_docs_challenges.md.0712c330.js
      similarity index 99%
      rename from assets/public_kronos_docs_challenges.md.c5401b51.js
      rename to assets/public_kronos_docs_challenges.md.0712c330.js
      index c347fec44..3e748fb11 100644
      --- a/assets/public_kronos_docs_challenges.md.c5401b51.js
      +++ b/assets/public_kronos_docs_challenges.md.0712c330.js
      @@ -1,4 +1,4 @@
      -import{_ as e,c as n,o as a,a as l}from"./app.a576d425.js";const d=JSON.parse('{"title":"Challenges","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/challenges.md","lastUpdated":null}'),s={name:"public/kronos/docs/challenges.md"},t=l(`

      Challenges

      Challenges can have fully customizable win conditions. Useful functions for dealing with Challenges and implementing their effects:

      • inChallenge(layer, id): determine if the player is in a given challenge (or another challenge on the same layer that counts as this one).
      • hasChallenge(layer, id): determine if the player has completed the challenge.
      • challengeCompletions(layer, id): determine how many times the player completed the challenge.
      • maxedChallenge(layer, id): determines if the player has reached the maximum completions.
      • challengeEffect(layer, id): Returns the current effects of the challenge, if any.

      Challenges are stored in the following format:

      js
      challenges: {
      +import{_ as e,c as n,o as a,a as l}from"./app.9bfeb8de.js";const d=JSON.parse('{"title":"Challenges","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/challenges.md","lastUpdated":null}'),s={name:"public/kronos/docs/challenges.md"},t=l(`

      Challenges

      Challenges can have fully customizable win conditions. Useful functions for dealing with Challenges and implementing their effects:

      • inChallenge(layer, id): determine if the player is in a given challenge (or another challenge on the same layer that counts as this one).
      • hasChallenge(layer, id): determine if the player has completed the challenge.
      • challengeCompletions(layer, id): determine how many times the player completed the challenge.
      • maxedChallenge(layer, id): determines if the player has reached the maximum completions.
      • challengeEffect(layer, id): Returns the current effects of the challenge, if any.

      Challenges are stored in the following format:

      js
      challenges: {
           11: {
               name: "Ouch",
               challengeDescription: "description of ouchie",
      diff --git a/assets/public_kronos_docs_challenges.md.c5401b51.lean.js b/assets/public_kronos_docs_challenges.md.0712c330.lean.js
      similarity index 83%
      rename from assets/public_kronos_docs_challenges.md.c5401b51.lean.js
      rename to assets/public_kronos_docs_challenges.md.0712c330.lean.js
      index 432706676..295830244 100644
      --- a/assets/public_kronos_docs_challenges.md.c5401b51.lean.js
      +++ b/assets/public_kronos_docs_challenges.md.0712c330.lean.js
      @@ -1 +1 @@
      -import{_ as e,c as n,o as a,a as l}from"./app.a576d425.js";const d=JSON.parse('{"title":"Challenges","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/challenges.md","lastUpdated":null}'),s={name:"public/kronos/docs/challenges.md"},t=l("",10),o=[t];function i(r,p,c,h,u,g){return a(),n("div",null,o)}const f=e(s,[["render",i]]);export{d as __pageData,f as default};
      +import{_ as e,c as n,o as a,a as l}from"./app.9bfeb8de.js";const d=JSON.parse('{"title":"Challenges","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/challenges.md","lastUpdated":null}'),s={name:"public/kronos/docs/challenges.md"},t=l("",10),o=[t];function i(r,p,c,h,u,g){return a(),n("div",null,o)}const f=e(s,[["render",i]]);export{d as __pageData,f as default};
      diff --git a/assets/public_kronos_docs_clickables.md.948c09c1.js b/assets/public_kronos_docs_clickables.md.f12083e3.js
      similarity index 98%
      rename from assets/public_kronos_docs_clickables.md.948c09c1.js
      rename to assets/public_kronos_docs_clickables.md.f12083e3.js
      index f7da15efd..2d110a642 100644
      --- a/assets/public_kronos_docs_clickables.md.948c09c1.js
      +++ b/assets/public_kronos_docs_clickables.md.f12083e3.js
      @@ -1,4 +1,4 @@
      -import{_ as e,c as t,o as a,a as s}from"./app.a576d425.js";const f=JSON.parse('{"title":"Clickables","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/clickables.md","lastUpdated":null}'),l={name:"public/kronos/docs/clickables.md"},n=s(`

      Clickables

      Clickables are any kind of thing that you can click for an effect. They're a more generalized version of Buyables.

      DO NOT USE THESE TO MAKE THINGS THAT YOU CLICK REPEATEDLY FOR A BONUS BECAUSE THOSE ARE AWFUL.

      There are several differences between the two. One is that a buyable's saved data is its amount as a Decimal, while Clickables store a "state" which can be a number or string, but not Decimal, array, or object). Buyables have a number of extra features which you can see on their page. Clickables also have a smaller default size.

      Useful functions for dealing with clickables and implementing their effects:

      • getClickableState(layer, id): get the state of the clickable the player has
      • setClickableState(layer, id, state): set the state of the clickable the player has
      • clickableEffect(layer, id): Returns the current effects of the clickable, if any.

      Clickables should be formatted like this:

      js
      clickables: {
      +import{_ as e,c as t,o as a,a as s}from"./app.9bfeb8de.js";const f=JSON.parse('{"title":"Clickables","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/clickables.md","lastUpdated":null}'),l={name:"public/kronos/docs/clickables.md"},n=s(`

      Clickables

      Clickables are any kind of thing that you can click for an effect. They're a more generalized version of Buyables.

      DO NOT USE THESE TO MAKE THINGS THAT YOU CLICK REPEATEDLY FOR A BONUS BECAUSE THOSE ARE AWFUL.

      There are several differences between the two. One is that a buyable's saved data is its amount as a Decimal, while Clickables store a "state" which can be a number or string, but not Decimal, array, or object). Buyables have a number of extra features which you can see on their page. Clickables also have a smaller default size.

      Useful functions for dealing with clickables and implementing their effects:

      • getClickableState(layer, id): get the state of the clickable the player has
      • setClickableState(layer, id, state): set the state of the clickable the player has
      • clickableEffect(layer, id): Returns the current effects of the clickable, if any.

      Clickables should be formatted like this:

      js
      clickables: {
           11: {
               display() {return "Blah"},
               etc
      diff --git a/assets/public_kronos_docs_clickables.md.948c09c1.lean.js b/assets/public_kronos_docs_clickables.md.f12083e3.lean.js
      similarity index 83%
      rename from assets/public_kronos_docs_clickables.md.948c09c1.lean.js
      rename to assets/public_kronos_docs_clickables.md.f12083e3.lean.js
      index 9f1968dc9..cf34a1f2f 100644
      --- a/assets/public_kronos_docs_clickables.md.948c09c1.lean.js
      +++ b/assets/public_kronos_docs_clickables.md.f12083e3.lean.js
      @@ -1 +1 @@
      -import{_ as e,c as t,o as a,a as s}from"./app.a576d425.js";const f=JSON.parse('{"title":"Clickables","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/clickables.md","lastUpdated":null}'),l={name:"public/kronos/docs/clickables.md"},n=s("",12),o=[n];function i(c,r,p,u,h,d){return a(),t("div",null,o)}const y=e(l,[["render",i]]);export{f as __pageData,y as default};
      +import{_ as e,c as t,o as a,a as s}from"./app.9bfeb8de.js";const f=JSON.parse('{"title":"Clickables","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/clickables.md","lastUpdated":null}'),l={name:"public/kronos/docs/clickables.md"},n=s("",12),o=[n];function i(c,r,p,u,h,d){return a(),t("div",null,o)}const y=e(l,[["render",i]]);export{f as __pageData,y as default};
      diff --git a/assets/public_kronos_docs_custom-tab-layouts.md.82768ae7.js b/assets/public_kronos_docs_custom-tab-layouts.md.cf36269b.js
      similarity index 99%
      rename from assets/public_kronos_docs_custom-tab-layouts.md.82768ae7.js
      rename to assets/public_kronos_docs_custom-tab-layouts.md.cf36269b.js
      index 149592eb9..0b65a53ff 100644
      --- a/assets/public_kronos_docs_custom-tab-layouts.md.82768ae7.js
      +++ b/assets/public_kronos_docs_custom-tab-layouts.md.cf36269b.js
      @@ -1,4 +1,4 @@
      -import{_ as s,c as a,o,a as e}from"./app.a576d425.js";const F=JSON.parse('{"title":"Custom tab layouts","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/custom-tab-layouts.md","lastUpdated":null}'),t={name:"public/kronos/docs/custom-tab-layouts.md"},n=e(`

      Custom tab layouts

      Note: If you are using subtabs, tabFormat is used differently, but the same format is used for defining their layouts. See here for more on subtabs.

      Custom tab layouts can be used to do basically anything in a tab window, especially combined with the "style" layer feature. The tabFormat feature is an array of things, like this:

      js
      tabFormat: [
      +import{_ as s,c as a,o,a as e}from"./app.9bfeb8de.js";const F=JSON.parse('{"title":"Custom tab layouts","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/custom-tab-layouts.md","lastUpdated":null}'),t={name:"public/kronos/docs/custom-tab-layouts.md"},n=e(`

      Custom tab layouts

      Note: If you are using subtabs, tabFormat is used differently, but the same format is used for defining their layouts. See here for more on subtabs.

      Custom tab layouts can be used to do basically anything in a tab window, especially combined with the "style" layer feature. The tabFormat feature is an array of things, like this:

      js
      tabFormat: [
           "main-display",
           ["prestige-button", function() { return "Melt your points into " }],
           "blank",
      diff --git a/assets/public_kronos_docs_custom-tab-layouts.md.82768ae7.lean.js b/assets/public_kronos_docs_custom-tab-layouts.md.cf36269b.lean.js
      similarity index 84%
      rename from assets/public_kronos_docs_custom-tab-layouts.md.82768ae7.lean.js
      rename to assets/public_kronos_docs_custom-tab-layouts.md.cf36269b.lean.js
      index 8aa82939c..f1253468f 100644
      --- a/assets/public_kronos_docs_custom-tab-layouts.md.82768ae7.lean.js
      +++ b/assets/public_kronos_docs_custom-tab-layouts.md.cf36269b.lean.js
      @@ -1 +1 @@
      -import{_ as s,c as a,o,a as e}from"./app.a576d425.js";const F=JSON.parse('{"title":"Custom tab layouts","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/custom-tab-layouts.md","lastUpdated":null}'),t={name:"public/kronos/docs/custom-tab-layouts.md"},n=e("",9),l=[n];function p(r,i,c,y,D,u){return o(),a("div",null,l)}const m=s(t,[["render",p]]);export{F as __pageData,m as default};
      +import{_ as s,c as a,o,a as e}from"./app.9bfeb8de.js";const F=JSON.parse('{"title":"Custom tab layouts","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/custom-tab-layouts.md","lastUpdated":null}'),t={name:"public/kronos/docs/custom-tab-layouts.md"},n=e("",9),l=[n];function p(r,i,c,y,D,u){return o(),a("div",null,l)}const m=s(t,[["render",p]]);export{F as __pageData,m as default};
      diff --git a/assets/public_kronos_docs_getting-started.md.ebf2428d.js b/assets/public_kronos_docs_getting-started.md.59f6b8e5.js
      similarity index 98%
      rename from assets/public_kronos_docs_getting-started.md.ebf2428d.js
      rename to assets/public_kronos_docs_getting-started.md.59f6b8e5.js
      index 691917d19..ec1d258f1 100644
      --- a/assets/public_kronos_docs_getting-started.md.ebf2428d.js
      +++ b/assets/public_kronos_docs_getting-started.md.59f6b8e5.js
      @@ -1 +1 @@
      -import{_ as e,c as t,o,a as i}from"./app.a576d425.js";const y=JSON.parse('{"title":"Getting started","description":"","frontmatter":{},"headers":[{"level":2,"title":"Getting set up with Github Desktop, Visual Studio Code, and The Modding Tree:","slug":"getting-set-up-with-github-desktop-visual-studio-code-and-the-modding-tree","link":"#getting-set-up-with-github-desktop-visual-studio-code-and-the-modding-tree","children":[{"level":3,"title":"Using your repository","slug":"using-your-repository","link":"#using-your-repository","children":[]}]}],"relativePath":"public/kronos/docs/getting-started.md","lastUpdated":null}'),a={name:"public/kronos/docs/getting-started.md"},n=i('

      Getting started

      Welcome to The Modding Tree!

      Using the Modding Tree, at its simplest level, just requires getting a copy of it onto your computer. However, if you do it the right way, it will help in many ways.

      Don't let the word "Github" scare you away. It's actually much easier to use than most people think, especially because most people use it the hard way. The key is Github Desktop, which lets you do everything you need to, without even touching the command line.

      The benefits of using Github:

      • It makes it much, much easier to update The Modding Tree.
      • You can share your work without any extra effort using githack, or with a bit more effort, set up a github.io site.
      • It lets you undo changes to your code, and to have multiple versions of it.
      • It lets you collaborate with other people, if you want to.

      Getting set up with Github Desktop, Visual Studio Code, and The Modding Tree:

      1. Install Github Desktop and Visual Studio Code.

      2. Make a Github account. You can handle this on your own.

      3. Log in on your browser, and go back to The Modding Tree page. At the top right, there should be a button that says "fork". Click on it, and then on your username. You now have your own fork, or copy, of The Modding Tree.

      4. Open Github Desktop and log in. Ignore everything else and choose "clone a repository". A "repository" is basically a "Github project", like The Modding Tree. "Cloning" is downloading a copy of the repository to your computer.

      5. Look for The Modding Tree in the list of repositiories (it should be the only one) and click "clone".

      6. Select that you're using it for your own purposes, and click continue. It will download the files and handle everything.

      Using your repository

      1. Click on "show in explorer/finder" to the right, and then open the index.html file in the folder. The page should open up on your browser. This will let you view and test your project locally!

      2. To edit your project, click "open in VSCode" in Github Desktop.

      3. Open mod.js in VSCode, and look at the top part where it has a "modInfo" object. Fill in your mod's name to whatever you want, and change the id as well. (It can be any string value, and it's used to determine where the savefile is. Make it something that's probably unique, and don't change it again later or else it'll effectively wipe existing saves)

      4. Save mod.js, and then reload index.html in your browser. The title on the tab, as well as on the info page, will now be updated! You can reload the page every time you change the code to test it quickly and easily.

      5. Go back to Github Desktop. It's time to save your changes into the git system by making a "commit". This basically saves your work and creates a snapshot of what your code looks like at this moment, allowing you to look back at it later.

      6. At the bottom right corner, add a summary of your changes, and then click "commit to master".

      7. Finally, at the top middle, click "push origin" to push your changes out onto the online repository.

      8. You can view your project on line, or share it with others, by going to https://raw.githack.com/[YOUR-GITHUB-USERNAME]/The-Modding-Tree/master/index.html

      And now, you have successfully used Github! You can look at the documentation to see how The Modding Tree's system works and to make your mod a reality.

      ',11),r=[n];function s(l,h,u,d,p,c){return o(),t("div",null,r)}const m=e(a,[["render",s]]);export{y as __pageData,m as default}; +import{_ as e,c as t,o,a as i}from"./app.9bfeb8de.js";const y=JSON.parse('{"title":"Getting started","description":"","frontmatter":{},"headers":[{"level":2,"title":"Getting set up with Github Desktop, Visual Studio Code, and The Modding Tree:","slug":"getting-set-up-with-github-desktop-visual-studio-code-and-the-modding-tree","link":"#getting-set-up-with-github-desktop-visual-studio-code-and-the-modding-tree","children":[{"level":3,"title":"Using your repository","slug":"using-your-repository","link":"#using-your-repository","children":[]}]}],"relativePath":"public/kronos/docs/getting-started.md","lastUpdated":null}'),a={name:"public/kronos/docs/getting-started.md"},n=i('

      Getting started

      Welcome to The Modding Tree!

      Using the Modding Tree, at its simplest level, just requires getting a copy of it onto your computer. However, if you do it the right way, it will help in many ways.

      Don't let the word "Github" scare you away. It's actually much easier to use than most people think, especially because most people use it the hard way. The key is Github Desktop, which lets you do everything you need to, without even touching the command line.

      The benefits of using Github:

      • It makes it much, much easier to update The Modding Tree.
      • You can share your work without any extra effort using githack, or with a bit more effort, set up a github.io site.
      • It lets you undo changes to your code, and to have multiple versions of it.
      • It lets you collaborate with other people, if you want to.

      Getting set up with Github Desktop, Visual Studio Code, and The Modding Tree:

      1. Install Github Desktop and Visual Studio Code.

      2. Make a Github account. You can handle this on your own.

      3. Log in on your browser, and go back to The Modding Tree page. At the top right, there should be a button that says "fork". Click on it, and then on your username. You now have your own fork, or copy, of The Modding Tree.

      4. Open Github Desktop and log in. Ignore everything else and choose "clone a repository". A "repository" is basically a "Github project", like The Modding Tree. "Cloning" is downloading a copy of the repository to your computer.

      5. Look for The Modding Tree in the list of repositiories (it should be the only one) and click "clone".

      6. Select that you're using it for your own purposes, and click continue. It will download the files and handle everything.

      Using your repository

      1. Click on "show in explorer/finder" to the right, and then open the index.html file in the folder. The page should open up on your browser. This will let you view and test your project locally!

      2. To edit your project, click "open in VSCode" in Github Desktop.

      3. Open mod.js in VSCode, and look at the top part where it has a "modInfo" object. Fill in your mod's name to whatever you want, and change the id as well. (It can be any string value, and it's used to determine where the savefile is. Make it something that's probably unique, and don't change it again later or else it'll effectively wipe existing saves)

      4. Save mod.js, and then reload index.html in your browser. The title on the tab, as well as on the info page, will now be updated! You can reload the page every time you change the code to test it quickly and easily.

      5. Go back to Github Desktop. It's time to save your changes into the git system by making a "commit". This basically saves your work and creates a snapshot of what your code looks like at this moment, allowing you to look back at it later.

      6. At the bottom right corner, add a summary of your changes, and then click "commit to master".

      7. Finally, at the top middle, click "push origin" to push your changes out onto the online repository.

      8. You can view your project on line, or share it with others, by going to https://raw.githack.com/[YOUR-GITHUB-USERNAME]/The-Modding-Tree/master/index.html

      And now, you have successfully used Github! You can look at the documentation to see how The Modding Tree's system works and to make your mod a reality.

      ',11),r=[n];function s(l,h,u,d,p,c){return o(),t("div",null,r)}const m=e(a,[["render",s]]);export{y as __pageData,m as default}; diff --git a/assets/public_kronos_docs_getting-started.md.ebf2428d.lean.js b/assets/public_kronos_docs_getting-started.md.59f6b8e5.lean.js similarity index 92% rename from assets/public_kronos_docs_getting-started.md.ebf2428d.lean.js rename to assets/public_kronos_docs_getting-started.md.59f6b8e5.lean.js index b54707645..016b3f0d6 100644 --- a/assets/public_kronos_docs_getting-started.md.ebf2428d.lean.js +++ b/assets/public_kronos_docs_getting-started.md.59f6b8e5.lean.js @@ -1 +1 @@ -import{_ as e,c as t,o,a as i}from"./app.a576d425.js";const y=JSON.parse('{"title":"Getting started","description":"","frontmatter":{},"headers":[{"level":2,"title":"Getting set up with Github Desktop, Visual Studio Code, and The Modding Tree:","slug":"getting-set-up-with-github-desktop-visual-studio-code-and-the-modding-tree","link":"#getting-set-up-with-github-desktop-visual-studio-code-and-the-modding-tree","children":[{"level":3,"title":"Using your repository","slug":"using-your-repository","link":"#using-your-repository","children":[]}]}],"relativePath":"public/kronos/docs/getting-started.md","lastUpdated":null}'),a={name:"public/kronos/docs/getting-started.md"},n=i("",11),r=[n];function s(l,h,u,d,p,c){return o(),t("div",null,r)}const m=e(a,[["render",s]]);export{y as __pageData,m as default}; +import{_ as e,c as t,o,a as i}from"./app.9bfeb8de.js";const y=JSON.parse('{"title":"Getting started","description":"","frontmatter":{},"headers":[{"level":2,"title":"Getting set up with Github Desktop, Visual Studio Code, and The Modding Tree:","slug":"getting-set-up-with-github-desktop-visual-studio-code-and-the-modding-tree","link":"#getting-set-up-with-github-desktop-visual-studio-code-and-the-modding-tree","children":[{"level":3,"title":"Using your repository","slug":"using-your-repository","link":"#using-your-repository","children":[]}]}],"relativePath":"public/kronos/docs/getting-started.md","lastUpdated":null}'),a={name:"public/kronos/docs/getting-started.md"},n=i("",11),r=[n];function s(l,h,u,d,p,c){return o(),t("div",null,r)}const m=e(a,[["render",s]]);export{y as __pageData,m as default}; diff --git a/assets/public_kronos_docs_grids.md.d18ed46e.js b/assets/public_kronos_docs_grids.md.19b800f2.js similarity index 99% rename from assets/public_kronos_docs_grids.md.d18ed46e.js rename to assets/public_kronos_docs_grids.md.19b800f2.js index 997e0a7d9..8a59e03fe 100644 --- a/assets/public_kronos_docs_grids.md.d18ed46e.js +++ b/assets/public_kronos_docs_grids.md.19b800f2.js @@ -1,4 +1,4 @@ -import{_ as s,c as a,o as n,a as e}from"./app.a576d425.js";const u=JSON.parse('{"title":"Grids","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/grids.md","lastUpdated":null}'),l={name:"public/kronos/docs/grids.md"},o=e(`

      Grids

      Grids are an easier way of making a group of similar clickables. They all have the same behavior, but are different based on their data.

      NOTE: Gridables are similar to clickables in some respects, but are fundamentally different from normal TMT components in quite a few ways. Be sure to keep these in mind:

      • Gridable ids use base 100 instead of base 10, so you can have more than 10 tiles in a row. This means that a grid might look like this: 101 102 201 202
      • Individual gridables are not defined individually. All properties go directly into the "grid" object. Functions are called with arguments for the id of the gridables and its associated data, so you can give them the appropriate appearance and properties based on that.
      • If you need two unrelated grids in a layer, you'll need to use a layer proxy component.

      Useful functions for dealing with grids:

      • getGridData(layer, id): get the data for the chosen gridable
      • setGridData(layer, id, state): set the data for the chosen gridable
      • gridEffect(layer, id): get the effect for the chosen gridable

      The grid should be formatted like this:

      js
      grid: {
      +import{_ as s,c as a,o as n,a as e}from"./app.9bfeb8de.js";const u=JSON.parse('{"title":"Grids","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/grids.md","lastUpdated":null}'),l={name:"public/kronos/docs/grids.md"},o=e(`

      Grids

      Grids are an easier way of making a group of similar clickables. They all have the same behavior, but are different based on their data.

      NOTE: Gridables are similar to clickables in some respects, but are fundamentally different from normal TMT components in quite a few ways. Be sure to keep these in mind:

      • Gridable ids use base 100 instead of base 10, so you can have more than 10 tiles in a row. This means that a grid might look like this: 101 102 201 202
      • Individual gridables are not defined individually. All properties go directly into the "grid" object. Functions are called with arguments for the id of the gridables and its associated data, so you can give them the appropriate appearance and properties based on that.
      • If you need two unrelated grids in a layer, you'll need to use a layer proxy component.

      Useful functions for dealing with grids:

      • getGridData(layer, id): get the data for the chosen gridable
      • setGridData(layer, id, state): set the data for the chosen gridable
      • gridEffect(layer, id): get the effect for the chosen gridable

      The grid should be formatted like this:

      js
      grid: {
           rows: 4, // If these are dynamic make sure to have a max value as well!
           cols: 5,
           getStartData(id) {
      diff --git a/assets/public_kronos_docs_grids.md.d18ed46e.lean.js b/assets/public_kronos_docs_grids.md.19b800f2.lean.js
      similarity index 83%
      rename from assets/public_kronos_docs_grids.md.d18ed46e.lean.js
      rename to assets/public_kronos_docs_grids.md.19b800f2.lean.js
      index de6e42ae2..67dfb795d 100644
      --- a/assets/public_kronos_docs_grids.md.d18ed46e.lean.js
      +++ b/assets/public_kronos_docs_grids.md.19b800f2.lean.js
      @@ -1 +1 @@
      -import{_ as s,c as a,o as n,a as e}from"./app.a576d425.js";const u=JSON.parse('{"title":"Grids","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/grids.md","lastUpdated":null}'),l={name:"public/kronos/docs/grids.md"},o=e("",10),t=[o];function p(r,i,c,d,y,F){return n(),a("div",null,t)}const g=s(l,[["render",p]]);export{u as __pageData,g as default};
      +import{_ as s,c as a,o as n,a as e}from"./app.9bfeb8de.js";const u=JSON.parse('{"title":"Grids","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/grids.md","lastUpdated":null}'),l={name:"public/kronos/docs/grids.md"},o=e("",10),t=[o];function p(r,i,c,d,y,F){return n(),a("div",null,t)}const g=s(l,[["render",p]]);export{u as __pageData,g as default};
      diff --git a/assets/public_kronos_docs_infoboxes.md.29623ec4.js b/assets/public_kronos_docs_infoboxes.md.d589fa70.js
      similarity index 98%
      rename from assets/public_kronos_docs_infoboxes.md.29623ec4.js
      rename to assets/public_kronos_docs_infoboxes.md.d589fa70.js
      index 4648f1c86..dbafc5fa9 100644
      --- a/assets/public_kronos_docs_infoboxes.md.29623ec4.js
      +++ b/assets/public_kronos_docs_infoboxes.md.d589fa70.js
      @@ -1,4 +1,4 @@
      -import{_ as s,c as o,o as a,a as n}from"./app.a576d425.js";const b=JSON.parse('{"title":"Infoboxes","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/infoboxes.md","lastUpdated":null}'),e={name:"public/kronos/docs/infoboxes.md"},t=n(`

      Infoboxes

      Infoboxes are good for displaying "lore", or story elements, as well as for explaining complicated things.

      In the default tab layout, the first infobox will be displayed at the very top of the tab.

      Infoboxes are defined like other Big Features:

      js
      infoboxes: {
      +import{_ as s,c as o,o as a,a as n}from"./app.9bfeb8de.js";const b=JSON.parse('{"title":"Infoboxes","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/infoboxes.md","lastUpdated":null}'),e={name:"public/kronos/docs/infoboxes.md"},t=n(`

      Infoboxes

      Infoboxes are good for displaying "lore", or story elements, as well as for explaining complicated things.

      In the default tab layout, the first infobox will be displayed at the very top of the tab.

      Infoboxes are defined like other Big Features:

      js
      infoboxes: {
           lore: {
               title: "foo",
               body() { return "bar" },
      diff --git a/assets/public_kronos_docs_infoboxes.md.29623ec4.lean.js b/assets/public_kronos_docs_infoboxes.md.d589fa70.lean.js
      similarity index 83%
      rename from assets/public_kronos_docs_infoboxes.md.29623ec4.lean.js
      rename to assets/public_kronos_docs_infoboxes.md.d589fa70.lean.js
      index e79b395f0..11c579446 100644
      --- a/assets/public_kronos_docs_infoboxes.md.29623ec4.lean.js
      +++ b/assets/public_kronos_docs_infoboxes.md.d589fa70.lean.js
      @@ -1 +1 @@
      -import{_ as s,c as o,o as a,a as n}from"./app.a576d425.js";const b=JSON.parse('{"title":"Infoboxes","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/infoboxes.md","lastUpdated":null}'),e={name:"public/kronos/docs/infoboxes.md"},t=n("",7),l=[t];function p(r,i,c,y,d,F){return a(),o("div",null,l)}const h=s(e,[["render",p]]);export{b as __pageData,h as default};
      +import{_ as s,c as o,o as a,a as n}from"./app.9bfeb8de.js";const b=JSON.parse('{"title":"Infoboxes","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/infoboxes.md","lastUpdated":null}'),e={name:"public/kronos/docs/infoboxes.md"},t=n("",7),l=[t];function p(r,i,c,y,d,F){return a(),o("div",null,l)}const h=s(e,[["render",p]]);export{b as __pageData,h as default};
      diff --git a/assets/public_kronos_docs_layer-features.md.718ce31d.js b/assets/public_kronos_docs_layer-features.md.abda9a85.js
      similarity index 99%
      rename from assets/public_kronos_docs_layer-features.md.718ce31d.js
      rename to assets/public_kronos_docs_layer-features.md.abda9a85.js
      index 14ff0d7aa..b0e6e9122 100644
      --- a/assets/public_kronos_docs_layer-features.md.718ce31d.js
      +++ b/assets/public_kronos_docs_layer-features.md.abda9a85.js
      @@ -1,4 +1,4 @@
      -import{_ as e,c as t,o as s,a}from"./app.a576d425.js";const f=JSON.parse('{"title":"Layer Features","description":"","frontmatter":{},"headers":[{"level":2,"title":"Layer Definition features","slug":"layer-definition-features","link":"#layer-definition-features","children":[]},{"level":2,"title":"Big features (all optional)","slug":"big-features-all-optional","link":"#big-features-all-optional","children":[]},{"level":2,"title":"Prestige formula features","slug":"prestige-formula-features","link":"#prestige-formula-features","children":[]},{"level":2,"title":"Other prestige-related features","slug":"other-prestige-related-features","link":"#other-prestige-related-features","children":[]},{"level":2,"title":"Tree/node features","slug":"tree-node-features","link":"#tree-node-features","children":[]},{"level":2,"title":"Other features","slug":"other-features","link":"#other-features","children":[]},{"level":2,"title":"Custom Prestige type","slug":"custom-prestige-type","link":"#custom-prestige-type","children":[]}],"relativePath":"public/kronos/docs/layer-features.md","lastUpdated":null}'),o={name:"public/kronos/docs/layer-features.md"},n=a(`

      Layer Features

      This is a more comprehensive list of established features to add to layers. You can add more freely, if you want to have other functions or values associated with your layer. These have special functionality, though.

      You can make almost any value dynamic by using a function in its place, including all display strings and styling/color features.

      Layer Definition features

      • layer: assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar to access the saved value. It makes copying code to new layers easier. It is also assigned to all upgrades and buyables and such.

      • name: optional. used in reset confirmations (and the default infobox title). If absent, it just uses the layer's id.

      • startData(): A function to return the default save data for this layer. Add any variables you have to it. Make sure to use Decimal values rather than normal numbers.

        Standard values: - Required: - unlocked: a bool determining if this layer is unlocked or not - points: a Decimal, the main currency for the layer - Optional: - total: A Decimal, tracks total amount of main prestige currency. Always tracked, but only shown if you add it here. - best: A Decimal, tracks highest amount of main prestige currency. Always tracked, but only shown if you add it here. - unlockOrder: used to keep track of relevant layers unlocked before this one. - resetTime: A number, time since this layer was last prestiged (or reset by another layer)

      • color: A color associated with this layer, used in many places. (A string in hex format with a #)

      • row: The row of the layer, starting at 0. This affects where the node appears on the standard tree, and which resets affect the layer.

        Using "side" instead of a number will cause the layer to appear off to the side as a smaller node (useful for achievements and statistics). Side layers are not affected by resets unless you add a doReset to them.

      • displayRow: OVERRIDE Changes where the layer node appears without changing where it is in the reset order.

      • resource: Name of the main currency you gain by resetting on this layer.

      • effect(): optional. A function that calculates and returns the current values of any bonuses inherent to the main currency. Can return a value or an object containing multiple values. You will also have to implement the effect where it is applied.

      • effectDescription: optional. A function that returns a description of this effect. If the text stays constant, it can just be a string.

      • layerShown(): optional, A function returning a bool which determines if this layer's node should be visible on the tree. It can also return "ghost", which will hide the layer, but its node will still take up space in the tree. Defaults to true.

      • hotkeys: optional. An array containing information on any hotkeys associated with this layer:

        js
        hotkeys: [
        +import{_ as e,c as t,o as s,a}from"./app.9bfeb8de.js";const f=JSON.parse('{"title":"Layer Features","description":"","frontmatter":{},"headers":[{"level":2,"title":"Layer Definition features","slug":"layer-definition-features","link":"#layer-definition-features","children":[]},{"level":2,"title":"Big features (all optional)","slug":"big-features-all-optional","link":"#big-features-all-optional","children":[]},{"level":2,"title":"Prestige formula features","slug":"prestige-formula-features","link":"#prestige-formula-features","children":[]},{"level":2,"title":"Other prestige-related features","slug":"other-prestige-related-features","link":"#other-prestige-related-features","children":[]},{"level":2,"title":"Tree/node features","slug":"tree-node-features","link":"#tree-node-features","children":[]},{"level":2,"title":"Other features","slug":"other-features","link":"#other-features","children":[]},{"level":2,"title":"Custom Prestige type","slug":"custom-prestige-type","link":"#custom-prestige-type","children":[]}],"relativePath":"public/kronos/docs/layer-features.md","lastUpdated":null}'),o={name:"public/kronos/docs/layer-features.md"},n=a(`

        Layer Features

        This is a more comprehensive list of established features to add to layers. You can add more freely, if you want to have other functions or values associated with your layer. These have special functionality, though.

        You can make almost any value dynamic by using a function in its place, including all display strings and styling/color features.

        Layer Definition features

        • layer: assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar to access the saved value. It makes copying code to new layers easier. It is also assigned to all upgrades and buyables and such.

        • name: optional. used in reset confirmations (and the default infobox title). If absent, it just uses the layer's id.

        • startData(): A function to return the default save data for this layer. Add any variables you have to it. Make sure to use Decimal values rather than normal numbers.

          Standard values: - Required: - unlocked: a bool determining if this layer is unlocked or not - points: a Decimal, the main currency for the layer - Optional: - total: A Decimal, tracks total amount of main prestige currency. Always tracked, but only shown if you add it here. - best: A Decimal, tracks highest amount of main prestige currency. Always tracked, but only shown if you add it here. - unlockOrder: used to keep track of relevant layers unlocked before this one. - resetTime: A number, time since this layer was last prestiged (or reset by another layer)

        • color: A color associated with this layer, used in many places. (A string in hex format with a #)

        • row: The row of the layer, starting at 0. This affects where the node appears on the standard tree, and which resets affect the layer.

          Using "side" instead of a number will cause the layer to appear off to the side as a smaller node (useful for achievements and statistics). Side layers are not affected by resets unless you add a doReset to them.

        • displayRow: OVERRIDE Changes where the layer node appears without changing where it is in the reset order.

        • resource: Name of the main currency you gain by resetting on this layer.

        • effect(): optional. A function that calculates and returns the current values of any bonuses inherent to the main currency. Can return a value or an object containing multiple values. You will also have to implement the effect where it is applied.

        • effectDescription: optional. A function that returns a description of this effect. If the text stays constant, it can just be a string.

        • layerShown(): optional, A function returning a bool which determines if this layer's node should be visible on the tree. It can also return "ghost", which will hide the layer, but its node will still take up space in the tree. Defaults to true.

        • hotkeys: optional. An array containing information on any hotkeys associated with this layer:

          js
          hotkeys: [
               {
                   key: "p", // What the hotkey button is. Use uppercase if it's combined with shift, or "ctrl+x" for holding down ctrl.
                   description: "p: reset your points for prestige points", // The description of the hotkey that is displayed in the game's How To Play tab
          diff --git a/assets/public_kronos_docs_layer-features.md.718ce31d.lean.js b/assets/public_kronos_docs_layer-features.md.abda9a85.lean.js
          similarity index 95%
          rename from assets/public_kronos_docs_layer-features.md.718ce31d.lean.js
          rename to assets/public_kronos_docs_layer-features.md.abda9a85.lean.js
          index 3e2d57c6f..f5fe9bd08 100644
          --- a/assets/public_kronos_docs_layer-features.md.718ce31d.lean.js
          +++ b/assets/public_kronos_docs_layer-features.md.abda9a85.lean.js
          @@ -1 +1 @@
          -import{_ as e,c as t,o as s,a}from"./app.a576d425.js";const f=JSON.parse('{"title":"Layer Features","description":"","frontmatter":{},"headers":[{"level":2,"title":"Layer Definition features","slug":"layer-definition-features","link":"#layer-definition-features","children":[]},{"level":2,"title":"Big features (all optional)","slug":"big-features-all-optional","link":"#big-features-all-optional","children":[]},{"level":2,"title":"Prestige formula features","slug":"prestige-formula-features","link":"#prestige-formula-features","children":[]},{"level":2,"title":"Other prestige-related features","slug":"other-prestige-related-features","link":"#other-prestige-related-features","children":[]},{"level":2,"title":"Tree/node features","slug":"tree-node-features","link":"#tree-node-features","children":[]},{"level":2,"title":"Other features","slug":"other-features","link":"#other-features","children":[]},{"level":2,"title":"Custom Prestige type","slug":"custom-prestige-type","link":"#custom-prestige-type","children":[]}],"relativePath":"public/kronos/docs/layer-features.md","lastUpdated":null}'),o={name:"public/kronos/docs/layer-features.md"},n=a("",20),r=[n];function l(i,p,c,u,h,d){return s(),t("div",null,r)}const g=e(o,[["render",l]]);export{f as __pageData,g as default};
          +import{_ as e,c as t,o as s,a}from"./app.9bfeb8de.js";const f=JSON.parse('{"title":"Layer Features","description":"","frontmatter":{},"headers":[{"level":2,"title":"Layer Definition features","slug":"layer-definition-features","link":"#layer-definition-features","children":[]},{"level":2,"title":"Big features (all optional)","slug":"big-features-all-optional","link":"#big-features-all-optional","children":[]},{"level":2,"title":"Prestige formula features","slug":"prestige-formula-features","link":"#prestige-formula-features","children":[]},{"level":2,"title":"Other prestige-related features","slug":"other-prestige-related-features","link":"#other-prestige-related-features","children":[]},{"level":2,"title":"Tree/node features","slug":"tree-node-features","link":"#tree-node-features","children":[]},{"level":2,"title":"Other features","slug":"other-features","link":"#other-features","children":[]},{"level":2,"title":"Custom Prestige type","slug":"custom-prestige-type","link":"#custom-prestige-type","children":[]}],"relativePath":"public/kronos/docs/layer-features.md","lastUpdated":null}'),o={name:"public/kronos/docs/layer-features.md"},n=a("",20),r=[n];function l(i,p,c,u,h,d){return s(),t("div",null,r)}const g=e(o,[["render",l]]);export{f as __pageData,g as default};
          diff --git a/assets/public_kronos_docs_main-mod-info.md.05ec401c.js b/assets/public_kronos_docs_main-mod-info.md.a3be0116.js
          similarity index 99%
          rename from assets/public_kronos_docs_main-mod-info.md.05ec401c.js
          rename to assets/public_kronos_docs_main-mod-info.md.a3be0116.js
          index 45ce3ec7a..566e1a984 100644
          --- a/assets/public_kronos_docs_main-mod-info.md.05ec401c.js
          +++ b/assets/public_kronos_docs_main-mod-info.md.a3be0116.js
          @@ -1,4 +1,4 @@
          -import{_ as e,c as s,o as a,a as n}from"./app.a576d425.js";const f=JSON.parse('{"title":"mod.js","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/main-mod-info.md","lastUpdated":null}'),t={name:"public/kronos/docs/main-mod-info.md"},o=n(`

          mod.js

          Most of the non-layer code and data that you're likely to edit is here in mod.js. Everything in mod.js will not be altered by updates, besides the addition of new things.

          Here's a breakdown of what's in it:

          • modInfo is where most of the basic configuration for the mod is. It contains:

            • name: The name of your mod. (a string)

            • id: The id for your mod, a unique string that is used to determine savefile location. Be sure to set it when you start making a mod, and don't change it later because it will erase all saves.

            • author: The name of the author, displayed in the info tab.

            • pointsName: This changes what is displayed instead of "points" for the main currency. (It does not affect it in the code.)

            • discordName, discordLink: If you have a Discord server or other discussion place, you can add a link to it.

              "discordName" is the text on the link, and "discordLink" is the url of an invite. If you're using a Discord invite, please make sure it's set to never expire.

            • offlineLimit: The maximum amount of offline time that the player can accumulate, in hours. Any extra time is lost. (a number)

              This is useful because most of these mods are fast-paced enough that too much offline time ruins the balance, such as the time in between updates. That is why I suggest developers disable offline time on their own savefile.

            • initialStartPoints: A Decimal for the amount of points a new player should start with.

          • VERSION is used to describe the current version of your mod. It contains:

            • num: The mod's version number, displayed at the top right of the tree tab.
            • name: The version's name, displayed alongside the number in the info tab.
          • changelog is the HTML displayed in the changelog tab. If this gets particularly long, it might be good to put in a separate file (be sure to add the file to index.html)

          • doNotCallTheseFunctionsEveryTick is very important, if you are adding non-standard functions. TMT calls every function anywhere in "layers" every tick to store the result, unless specifically told not to. Functions that have are used to do an action need to be identified. "Official" functions (those in the documentation) are all fine, but if you make any new ones, add their names to this array.

          js
          // (The ones here are examples, all official functions are already taken care of)
          +import{_ as e,c as s,o as a,a as n}from"./app.9bfeb8de.js";const f=JSON.parse('{"title":"mod.js","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/main-mod-info.md","lastUpdated":null}'),t={name:"public/kronos/docs/main-mod-info.md"},o=n(`

          mod.js

          Most of the non-layer code and data that you're likely to edit is here in mod.js. Everything in mod.js will not be altered by updates, besides the addition of new things.

          Here's a breakdown of what's in it:

          • modInfo is where most of the basic configuration for the mod is. It contains:

            • name: The name of your mod. (a string)

            • id: The id for your mod, a unique string that is used to determine savefile location. Be sure to set it when you start making a mod, and don't change it later because it will erase all saves.

            • author: The name of the author, displayed in the info tab.

            • pointsName: This changes what is displayed instead of "points" for the main currency. (It does not affect it in the code.)

            • discordName, discordLink: If you have a Discord server or other discussion place, you can add a link to it.

              "discordName" is the text on the link, and "discordLink" is the url of an invite. If you're using a Discord invite, please make sure it's set to never expire.

            • offlineLimit: The maximum amount of offline time that the player can accumulate, in hours. Any extra time is lost. (a number)

              This is useful because most of these mods are fast-paced enough that too much offline time ruins the balance, such as the time in between updates. That is why I suggest developers disable offline time on their own savefile.

            • initialStartPoints: A Decimal for the amount of points a new player should start with.

          • VERSION is used to describe the current version of your mod. It contains:

            • num: The mod's version number, displayed at the top right of the tree tab.
            • name: The version's name, displayed alongside the number in the info tab.
          • changelog is the HTML displayed in the changelog tab. If this gets particularly long, it might be good to put in a separate file (be sure to add the file to index.html)

          • doNotCallTheseFunctionsEveryTick is very important, if you are adding non-standard functions. TMT calls every function anywhere in "layers" every tick to store the result, unless specifically told not to. Functions that have are used to do an action need to be identified. "Official" functions (those in the documentation) are all fine, but if you make any new ones, add their names to this array.

          js
          // (The ones here are examples, all official functions are already taken care of)
           var doNotCallTheseFunctionsEveryTick = ["doReset", "buy", "onPurchase", "blowUpEverything"]
           
          • getStartPoints(): A function to determine the amount of points the player starts with after a reset. (returns a Decimal value)

          • canGenPoints(): A function returning a boolean for if points should be generated. Use this if you want an upgrade to unlock generating points.

          • getPointGen(): A function that calculates your points per second. Anything that affects your point gain should go into the calculation here.

          • addedPlayerData(): A function that returns any non-layer-related data that you want to be added to the save data and "player" object.

          js
          function addedPlayerData() { return {
           	weather: "Yes",
          diff --git a/assets/public_kronos_docs_main-mod-info.md.05ec401c.lean.js b/assets/public_kronos_docs_main-mod-info.md.a3be0116.lean.js
          similarity index 84%
          rename from assets/public_kronos_docs_main-mod-info.md.05ec401c.lean.js
          rename to assets/public_kronos_docs_main-mod-info.md.a3be0116.lean.js
          index b4843cb52..054021d5c 100644
          --- a/assets/public_kronos_docs_main-mod-info.md.05ec401c.lean.js
          +++ b/assets/public_kronos_docs_main-mod-info.md.a3be0116.lean.js
          @@ -1 +1 @@
          -import{_ as e,c as s,o as a,a as n}from"./app.a576d425.js";const f=JSON.parse('{"title":"mod.js","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/main-mod-info.md","lastUpdated":null}'),t={name:"public/kronos/docs/main-mod-info.md"},o=n("",10),l=[o];function i(p,r,c,d,u,h){return a(),s("div",null,l)}const m=e(t,[["render",i]]);export{f as __pageData,m as default};
          +import{_ as e,c as s,o as a,a as n}from"./app.9bfeb8de.js";const f=JSON.parse('{"title":"mod.js","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/main-mod-info.md","lastUpdated":null}'),t={name:"public/kronos/docs/main-mod-info.md"},o=n("",10),l=[o];function i(p,r,c,d,u,h){return a(),s("div",null,l)}const m=e(t,[["render",i]]);export{f as __pageData,m as default};
          diff --git a/assets/public_kronos_docs_milestones.md.0e514a5c.js b/assets/public_kronos_docs_milestones.md.63041a6e.js
          similarity index 98%
          rename from assets/public_kronos_docs_milestones.md.0e514a5c.js
          rename to assets/public_kronos_docs_milestones.md.63041a6e.js
          index 2abfb13cb..68a152dba 100644
          --- a/assets/public_kronos_docs_milestones.md.0e514a5c.js
          +++ b/assets/public_kronos_docs_milestones.md.63041a6e.js
          @@ -1,4 +1,4 @@
          -import{_ as s,c as e,o as n,a}from"./app.a576d425.js";const F=JSON.parse('{"title":"Milestones","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/milestones.md","lastUpdated":null}'),o={name:"public/kronos/docs/milestones.md"},t=a(`

          Milestones

          Milestones are awarded to the player when they meet a certain goal, and give some benefit. Milestones should be formatted like this:

          js
          milestones: {
          +import{_ as s,c as e,o as n,a}from"./app.9bfeb8de.js";const F=JSON.parse('{"title":"Milestones","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/milestones.md","lastUpdated":null}'),o={name:"public/kronos/docs/milestones.md"},t=a(`

          Milestones

          Milestones are awarded to the player when they meet a certain goal, and give some benefit. Milestones should be formatted like this:

          js
          milestones: {
               0: {
                   requirementDescription: "123 waffles",
                   effectDescription: "blah",
          diff --git a/assets/public_kronos_docs_milestones.md.0e514a5c.lean.js b/assets/public_kronos_docs_milestones.md.63041a6e.lean.js
          similarity index 83%
          rename from assets/public_kronos_docs_milestones.md.0e514a5c.lean.js
          rename to assets/public_kronos_docs_milestones.md.63041a6e.lean.js
          index 196cdad79..7c3691503 100644
          --- a/assets/public_kronos_docs_milestones.md.0e514a5c.lean.js
          +++ b/assets/public_kronos_docs_milestones.md.63041a6e.lean.js
          @@ -1 +1 @@
          -import{_ as s,c as e,o as n,a}from"./app.a576d425.js";const F=JSON.parse('{"title":"Milestones","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/milestones.md","lastUpdated":null}'),o={name:"public/kronos/docs/milestones.md"},t=a("",7),l=[t];function p(i,r,c,u,d,h){return n(),e("div",null,l)}const g=s(o,[["render",p]]);export{F as __pageData,g as default};
          +import{_ as s,c as e,o as n,a}from"./app.9bfeb8de.js";const F=JSON.parse('{"title":"Milestones","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/milestones.md","lastUpdated":null}'),o={name:"public/kronos/docs/milestones.md"},t=a("",7),l=[t];function p(i,r,c,u,d,h){return n(),e("div",null,l)}const g=s(o,[["render",p]]);export{F as __pageData,g as default};
          diff --git a/assets/public_kronos_docs_particles.md.7b063d3e.js b/assets/public_kronos_docs_particles.md.9405e742.js
          similarity index 99%
          rename from assets/public_kronos_docs_particles.md.7b063d3e.js
          rename to assets/public_kronos_docs_particles.md.9405e742.js
          index 37bddc4a8..1629eb286 100644
          --- a/assets/public_kronos_docs_particles.md.7b063d3e.js
          +++ b/assets/public_kronos_docs_particles.md.9405e742.js
          @@ -1,4 +1,4 @@
          -import{_ as e,c as a,o as s,a as t}from"./app.a576d425.js";const f=JSON.parse('{"title":"Particles","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/particles.md","lastUpdated":null}'),l={name:"public/kronos/docs/particles.md"},n=t(`

          Particles

          Particles are free-floating elements that can move and have many different behaviors. They can also interact with the mouse.

          To make particles, use makeParticles(particle, amount). particle is a particle-defining object, with features as explained below. There is also makeShinies, which uses different defaults and creates stationary particles at a random location. There are also a few other useful things listed at the end.

          js
          
          +import{_ as e,c as a,o as s,a as t}from"./app.9bfeb8de.js";const f=JSON.parse('{"title":"Particles","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/particles.md","lastUpdated":null}'),l={name:"public/kronos/docs/particles.md"},n=t(`

          Particles

          Particles are free-floating elements that can move and have many different behaviors. They can also interact with the mouse.

          To make particles, use makeParticles(particle, amount). particle is a particle-defining object, with features as explained below. There is also makeShinies, which uses different defaults and creates stationary particles at a random location. There are also a few other useful things listed at the end.

          js
          
           const myParticle {
               image:"options_wheel.png",
               spread: 20,
          diff --git a/assets/public_kronos_docs_particles.md.7b063d3e.lean.js b/assets/public_kronos_docs_particles.md.9405e742.lean.js
          similarity index 83%
          rename from assets/public_kronos_docs_particles.md.7b063d3e.lean.js
          rename to assets/public_kronos_docs_particles.md.9405e742.lean.js
          index 53a3c4b5a..4e526d5dd 100644
          --- a/assets/public_kronos_docs_particles.md.7b063d3e.lean.js
          +++ b/assets/public_kronos_docs_particles.md.9405e742.lean.js
          @@ -1 +1 @@
          -import{_ as e,c as a,o as s,a as t}from"./app.a576d425.js";const f=JSON.parse('{"title":"Particles","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/particles.md","lastUpdated":null}'),l={name:"public/kronos/docs/particles.md"},n=t("",11),o=[n];function i(p,r,c,d,h,u){return s(),a("div",null,o)}const D=e(l,[["render",i]]);export{f as __pageData,D as default};
          +import{_ as e,c as a,o as s,a as t}from"./app.9bfeb8de.js";const f=JSON.parse('{"title":"Particles","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/particles.md","lastUpdated":null}'),l={name:"public/kronos/docs/particles.md"},n=t("",11),o=[n];function i(p,r,c,d,h,u){return s(),a("div",null,o)}const D=e(l,[["render",i]]);export{f as __pageData,D as default};
          diff --git a/assets/public_kronos_docs_subtabs-and-microtabs.md.93ca2268.js b/assets/public_kronos_docs_subtabs-and-microtabs.md.a6c47048.js
          similarity index 99%
          rename from assets/public_kronos_docs_subtabs-and-microtabs.md.93ca2268.js
          rename to assets/public_kronos_docs_subtabs-and-microtabs.md.a6c47048.js
          index 4e8f30cc1..a47034268 100644
          --- a/assets/public_kronos_docs_subtabs-and-microtabs.md.93ca2268.js
          +++ b/assets/public_kronos_docs_subtabs-and-microtabs.md.a6c47048.js
          @@ -1,4 +1,4 @@
          -import{_ as s,c as a,o as n,a as o}from"./app.a576d425.js";const h=JSON.parse('{"title":"Subtabs and Microtabs","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/subtabs-and-microtabs.md","lastUpdated":null}'),t={name:"public/kronos/docs/subtabs-and-microtabs.md"},l=o(`

          Subtabs and Microtabs

          Subtabs are separate sections of a tab that you can view by selecting one at the top of the tab. Microtabs are smaller areas that function in much the same way. You can also embed layers inside of subtabs/microtabs.

          Subtabs are defined by using the tab format like this, where each element of tabFormat is given the name of that subtab:

          js
          tabFormat: {
          +import{_ as s,c as a,o as n,a as o}from"./app.9bfeb8de.js";const h=JSON.parse('{"title":"Subtabs and Microtabs","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/subtabs-and-microtabs.md","lastUpdated":null}'),t={name:"public/kronos/docs/subtabs-and-microtabs.md"},l=o(`

          Subtabs and Microtabs

          Subtabs are separate sections of a tab that you can view by selecting one at the top of the tab. Microtabs are smaller areas that function in much the same way. You can also embed layers inside of subtabs/microtabs.

          Subtabs are defined by using the tab format like this, where each element of tabFormat is given the name of that subtab:

          js
          tabFormat: {
               "Main tab": {
                   content: [tab format things],
                   *subtab features*
          diff --git a/assets/public_kronos_docs_subtabs-and-microtabs.md.93ca2268.lean.js b/assets/public_kronos_docs_subtabs-and-microtabs.md.a6c47048.lean.js
          similarity index 85%
          rename from assets/public_kronos_docs_subtabs-and-microtabs.md.93ca2268.lean.js
          rename to assets/public_kronos_docs_subtabs-and-microtabs.md.a6c47048.lean.js
          index a196cb4b0..6cab6c202 100644
          --- a/assets/public_kronos_docs_subtabs-and-microtabs.md.93ca2268.lean.js
          +++ b/assets/public_kronos_docs_subtabs-and-microtabs.md.a6c47048.lean.js
          @@ -1 +1 @@
          -import{_ as s,c as a,o as n,a as o}from"./app.a576d425.js";const h=JSON.parse('{"title":"Subtabs and Microtabs","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/subtabs-and-microtabs.md","lastUpdated":null}'),t={name:"public/kronos/docs/subtabs-and-microtabs.md"},l=o("",9),e=[l];function p(r,c,i,y,F,u){return n(),a("div",null,e)}const D=s(t,[["render",p]]);export{h as __pageData,D as default};
          +import{_ as s,c as a,o as n,a as o}from"./app.9bfeb8de.js";const h=JSON.parse('{"title":"Subtabs and Microtabs","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/subtabs-and-microtabs.md","lastUpdated":null}'),t={name:"public/kronos/docs/subtabs-and-microtabs.md"},l=o("",9),e=[l];function p(r,c,i,y,F,u){return n(),a("div",null,e)}const D=s(t,[["render",p]]);export{h as __pageData,D as default};
          diff --git a/assets/public_kronos_docs_trees-and-tree-customization.md.dde81eb2.js b/assets/public_kronos_docs_trees-and-tree-customization.md.4ffd8021.js
          similarity index 99%
          rename from assets/public_kronos_docs_trees-and-tree-customization.md.dde81eb2.js
          rename to assets/public_kronos_docs_trees-and-tree-customization.md.4ffd8021.js
          index 0911d5906..425eae72e 100644
          --- a/assets/public_kronos_docs_trees-and-tree-customization.md.dde81eb2.js
          +++ b/assets/public_kronos_docs_trees-and-tree-customization.md.4ffd8021.js
          @@ -1,4 +1,4 @@
          -import{_ as e,c as t,o,a}from"./app.a576d425.js";const D=JSON.parse('{"title":"Trees and tree customization","description":"","frontmatter":{},"headers":[{"level":2,"title":"layoutInfo","slug":"layoutinfo","link":"#layoutinfo","children":[]},{"level":2,"title":"Trees","slug":"trees","link":"#trees","children":[]},{"level":2,"title":"Nodes","slug":"nodes","link":"#nodes","children":[]}],"relativePath":"public/kronos/docs/trees-and-tree-customization.md","lastUpdated":null}'),s={name:"public/kronos/docs/trees-and-tree-customization.md"},n=a(`

          Trees and tree customization

          If you want to have something beyond the standard tree on the left tab, you can do that in tree.js. You can change the layout of the tree, including making non-layer nodes, change it into something other than a tree, or hide the left tab altogether. This also introduces the "tree" component, which can be used in your layers as well.

          layoutInfo

          The most important part is layoutInfo, containing:

          • startTab: The id of the default tab to show on the left at the start.
          • showTree: True if the tree tab should be shown at the start of the game. (The other tab will fill the whole page)
          • treeLayout: If present, overrides the tree layout and places nodes as you describe instead (explained in the next section).

          Additionally, if you want the main layout to not be a tree, you can edit the "tree-tab" layer at the bottom of tree.js to modify it just like a normal layer's tab. You can even switch between left tabs, using showNavTab(layer) to make that layer appear on the left.

          Trees

          The tree component is defined as an array of arrays of names of layers or nodes to show in the tree. They work just like layers/ nodes in the main tree (but branches between nodes will only work on the first node if you have duplicates.)

          Here is an example tree:

          js
          [["p"],
          +import{_ as e,c as t,o,a}from"./app.9bfeb8de.js";const D=JSON.parse('{"title":"Trees and tree customization","description":"","frontmatter":{},"headers":[{"level":2,"title":"layoutInfo","slug":"layoutinfo","link":"#layoutinfo","children":[]},{"level":2,"title":"Trees","slug":"trees","link":"#trees","children":[]},{"level":2,"title":"Nodes","slug":"nodes","link":"#nodes","children":[]}],"relativePath":"public/kronos/docs/trees-and-tree-customization.md","lastUpdated":null}'),s={name:"public/kronos/docs/trees-and-tree-customization.md"},n=a(`

          Trees and tree customization

          If you want to have something beyond the standard tree on the left tab, you can do that in tree.js. You can change the layout of the tree, including making non-layer nodes, change it into something other than a tree, or hide the left tab altogether. This also introduces the "tree" component, which can be used in your layers as well.

          layoutInfo

          The most important part is layoutInfo, containing:

          • startTab: The id of the default tab to show on the left at the start.
          • showTree: True if the tree tab should be shown at the start of the game. (The other tab will fill the whole page)
          • treeLayout: If present, overrides the tree layout and places nodes as you describe instead (explained in the next section).

          Additionally, if you want the main layout to not be a tree, you can edit the "tree-tab" layer at the bottom of tree.js to modify it just like a normal layer's tab. You can even switch between left tabs, using showNavTab(layer) to make that layer appear on the left.

          Trees

          The tree component is defined as an array of arrays of names of layers or nodes to show in the tree. They work just like layers/ nodes in the main tree (but branches between nodes will only work on the first node if you have duplicates.)

          Here is an example tree:

          js
          [["p"],
            ["left", "blank", "right", "blank"]
            ["a", "b", "blank", "c", "weirdButton"]]
           

          Nodes

          Nodes are non-layer buttons that can go in trees. They are defined similarly to layers, but with addNode instead of addLayer.

          Features:

          • color: optional, The node's color. (A string in hex format with a #)

          • symbol: optional The text on the button (The id capitalized by default)

          • canClick(): Returns true if the player can click the node. ()

          • onClick(): The function called when the node is clicked.

          • layerShown(): optional, A function returning a bool which determines if this node should be visible. It can also return "ghost", which will hide the layer, but its node will still take up space in its tree.

          • branches: optional. An array of layer/node ids. On a tree, a line will appear from this node to all of the nodes in the list. Alternatively, an entry in the array can be a 2-element array consisting of the id and a color value. The color value can either be a string with a hex color code, or a number from 1-3 (theme-affected colors).

          • nodeStyle: optional. A CSS object, where the keys are CSS attributes, which styles this node on the tree.

          • tooltip() / tooltipLocked(): optional. Functions that return text, which is the tooltip for the node when the layer is unlocked or locked, respectively. By default the tooltips behave the same as in the original Prestige Tree.

          • row: optional, the row that this node appears in (for the default tree).

          • position: optional, Determines the horizontal position of the layer in its row in a default tree. By default, it uses the id, and layers/nodes are sorted in alphabetical order.

          `,14),l=[n];function r(i,p,c,h,d,u){return o(),t("div",null,l)}const f=e(s,[["render",r]]);export{D as __pageData,f as default}; diff --git a/assets/public_kronos_docs_trees-and-tree-customization.md.dde81eb2.lean.js b/assets/public_kronos_docs_trees-and-tree-customization.md.4ffd8021.lean.js similarity index 90% rename from assets/public_kronos_docs_trees-and-tree-customization.md.dde81eb2.lean.js rename to assets/public_kronos_docs_trees-and-tree-customization.md.4ffd8021.lean.js index 850db0e71..e530b83b2 100644 --- a/assets/public_kronos_docs_trees-and-tree-customization.md.dde81eb2.lean.js +++ b/assets/public_kronos_docs_trees-and-tree-customization.md.4ffd8021.lean.js @@ -1 +1 @@ -import{_ as e,c as t,o,a}from"./app.a576d425.js";const D=JSON.parse('{"title":"Trees and tree customization","description":"","frontmatter":{},"headers":[{"level":2,"title":"layoutInfo","slug":"layoutinfo","link":"#layoutinfo","children":[]},{"level":2,"title":"Trees","slug":"trees","link":"#trees","children":[]},{"level":2,"title":"Nodes","slug":"nodes","link":"#nodes","children":[]}],"relativePath":"public/kronos/docs/trees-and-tree-customization.md","lastUpdated":null}'),s={name:"public/kronos/docs/trees-and-tree-customization.md"},n=a("",14),l=[n];function r(i,p,c,h,d,u){return o(),t("div",null,l)}const f=e(s,[["render",r]]);export{D as __pageData,f as default}; +import{_ as e,c as t,o,a}from"./app.9bfeb8de.js";const D=JSON.parse('{"title":"Trees and tree customization","description":"","frontmatter":{},"headers":[{"level":2,"title":"layoutInfo","slug":"layoutinfo","link":"#layoutinfo","children":[]},{"level":2,"title":"Trees","slug":"trees","link":"#trees","children":[]},{"level":2,"title":"Nodes","slug":"nodes","link":"#nodes","children":[]}],"relativePath":"public/kronos/docs/trees-and-tree-customization.md","lastUpdated":null}'),s={name:"public/kronos/docs/trees-and-tree-customization.md"},n=a("",14),l=[n];function r(i,p,c,h,d,u){return o(),t("div",null,l)}const f=e(s,[["render",r]]);export{D as __pageData,f as default}; diff --git a/assets/public_kronos_docs_updating-tmt.md.042ac945.js b/assets/public_kronos_docs_updating-tmt.md.aa800528.js similarity index 96% rename from assets/public_kronos_docs_updating-tmt.md.042ac945.js rename to assets/public_kronos_docs_updating-tmt.md.aa800528.js index 5e5204359..0b75e5cdb 100644 --- a/assets/public_kronos_docs_updating-tmt.md.042ac945.js +++ b/assets/public_kronos_docs_updating-tmt.md.aa800528.js @@ -1 +1 @@ -import{_ as t,c as e,o,a}from"./app.a576d425.js";const m=JSON.parse('{"title":"Updating The Modding Tree","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/updating-tmt.md","lastUpdated":null}'),i={name:"public/kronos/docs/updating-tmt.md"},n=a('

          Updating The Modding Tree

          This tutorial assumes that you have used the Getting Started Tutorial, and are using Github Desktop and VSCode for your mod.

          Here's what you have to do when there's a TMT update:

          1. Look at the changelog. It will warn you if the update will break anything or require any changes. Decide if you want to try to update.

          2. Open Github Desktop, and at the top middle, click "fetch origin". This will make Github Desktop get information about the update.

          3. Click where it says "current branch: master" at the top middle, and at the bottom of the thing that appears, click "choose a branch to merge into master".

          4. Select upstream/master. It will likely say there are conflicts, but you have tools to resolve them. Click "Merge upstream/master into master".

          5. A conflict happens when the things you're trying to merge have both made changes in the same place. Click "open in Visual Studio Code" next to the first file.

          6. Scroll down through the file, and look for the parts highlighted in red and green. One of these is your code, and the other is some code that will be modified by the update. Do your best to try to edit things to keep the updated changes, but keep your content.

          7. Continue to do this for all remaining changes.

          8. Do any other changes required by the update, run the game, fix issues, etc.

          ',4),r=[n];function h(s,d,l,p,u,c){return o(),e("div",null,r)}const _=t(i,[["render",h]]);export{m as __pageData,_ as default}; +import{_ as t,c as e,o,a}from"./app.9bfeb8de.js";const m=JSON.parse('{"title":"Updating The Modding Tree","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/updating-tmt.md","lastUpdated":null}'),i={name:"public/kronos/docs/updating-tmt.md"},n=a('

          Updating The Modding Tree

          This tutorial assumes that you have used the Getting Started Tutorial, and are using Github Desktop and VSCode for your mod.

          Here's what you have to do when there's a TMT update:

          1. Look at the changelog. It will warn you if the update will break anything or require any changes. Decide if you want to try to update.

          2. Open Github Desktop, and at the top middle, click "fetch origin". This will make Github Desktop get information about the update.

          3. Click where it says "current branch: master" at the top middle, and at the bottom of the thing that appears, click "choose a branch to merge into master".

          4. Select upstream/master. It will likely say there are conflicts, but you have tools to resolve them. Click "Merge upstream/master into master".

          5. A conflict happens when the things you're trying to merge have both made changes in the same place. Click "open in Visual Studio Code" next to the first file.

          6. Scroll down through the file, and look for the parts highlighted in red and green. One of these is your code, and the other is some code that will be modified by the update. Do your best to try to edit things to keep the updated changes, but keep your content.

          7. Continue to do this for all remaining changes.

          8. Do any other changes required by the update, run the game, fix issues, etc.

          ',4),r=[n];function h(s,d,l,p,u,c){return o(),e("div",null,r)}const _=t(i,[["render",h]]);export{m as __pageData,_ as default}; diff --git a/assets/public_kronos_docs_updating-tmt.md.042ac945.lean.js b/assets/public_kronos_docs_updating-tmt.md.aa800528.lean.js similarity index 84% rename from assets/public_kronos_docs_updating-tmt.md.042ac945.lean.js rename to assets/public_kronos_docs_updating-tmt.md.aa800528.lean.js index 5a4b260e5..dc146476a 100644 --- a/assets/public_kronos_docs_updating-tmt.md.042ac945.lean.js +++ b/assets/public_kronos_docs_updating-tmt.md.aa800528.lean.js @@ -1 +1 @@ -import{_ as t,c as e,o,a}from"./app.a576d425.js";const m=JSON.parse('{"title":"Updating The Modding Tree","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/updating-tmt.md","lastUpdated":null}'),i={name:"public/kronos/docs/updating-tmt.md"},n=a("",4),r=[n];function h(s,d,l,p,u,c){return o(),e("div",null,r)}const _=t(i,[["render",h]]);export{m as __pageData,_ as default}; +import{_ as t,c as e,o,a}from"./app.9bfeb8de.js";const m=JSON.parse('{"title":"Updating The Modding Tree","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/updating-tmt.md","lastUpdated":null}'),i={name:"public/kronos/docs/updating-tmt.md"},n=a("",4),r=[n];function h(s,d,l,p,u,c){return o(),e("div",null,r)}const _=t(i,[["render",h]]);export{m as __pageData,_ as default}; diff --git a/assets/public_kronos_docs_upgrades.md.75a2743b.js b/assets/public_kronos_docs_upgrades.md.666bb565.js similarity index 98% rename from assets/public_kronos_docs_upgrades.md.75a2743b.js rename to assets/public_kronos_docs_upgrades.md.666bb565.js index 21029da05..8d7ddfe09 100644 --- a/assets/public_kronos_docs_upgrades.md.75a2743b.js +++ b/assets/public_kronos_docs_upgrades.md.666bb565.js @@ -1,4 +1,4 @@ -import{_ as e,c as s,o as a,a as t}from"./app.a576d425.js";const g=JSON.parse('{"title":"Upgrades","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/upgrades.md","lastUpdated":null}'),n={name:"public/kronos/docs/upgrades.md"},o=t(`

          Upgrades

          Useful functions for dealing with Upgrades and implementing their effects:

          • hasUpgrade(layer, id): determine if the player has the upgrade
          • upgradeEffect(layer, id): Returns the current effects of the upgrade, if any
          • buyUpgrade(layer, id): Buys an upgrade directly (if affordable)

          Hint: Basic point gain is calculated in mod.js's "getPointGen" function.

          Upgrades are stored in the following format:

          js
          upgrades: {
          +import{_ as e,c as s,o as a,a as t}from"./app.9bfeb8de.js";const g=JSON.parse('{"title":"Upgrades","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/upgrades.md","lastUpdated":null}'),n={name:"public/kronos/docs/upgrades.md"},o=t(`

          Upgrades

          Useful functions for dealing with Upgrades and implementing their effects:

          • hasUpgrade(layer, id): determine if the player has the upgrade
          • upgradeEffect(layer, id): Returns the current effects of the upgrade, if any
          • buyUpgrade(layer, id): Buys an upgrade directly (if affordable)

          Hint: Basic point gain is calculated in mod.js's "getPointGen" function.

          Upgrades are stored in the following format:

          js
          upgrades: {
               11: {
                   description: "Blah",
                   cost: new Decimal(100),
          diff --git a/assets/public_kronos_docs_upgrades.md.75a2743b.lean.js b/assets/public_kronos_docs_upgrades.md.666bb565.lean.js
          similarity index 83%
          rename from assets/public_kronos_docs_upgrades.md.75a2743b.lean.js
          rename to assets/public_kronos_docs_upgrades.md.666bb565.lean.js
          index a96f5ce8e..ffffbb52d 100644
          --- a/assets/public_kronos_docs_upgrades.md.75a2743b.lean.js
          +++ b/assets/public_kronos_docs_upgrades.md.666bb565.lean.js
          @@ -1 +1 @@
          -import{_ as e,c as s,o as a,a as t}from"./app.a576d425.js";const g=JSON.parse('{"title":"Upgrades","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/upgrades.md","lastUpdated":null}'),n={name:"public/kronos/docs/upgrades.md"},o=t("",13),l=[o];function r(i,p,c,u,d,h){return a(),s("div",null,l)}const f=e(n,[["render",r]]);export{g as __pageData,f as default};
          +import{_ as e,c as s,o as a,a as t}from"./app.9bfeb8de.js";const g=JSON.parse('{"title":"Upgrades","description":"","frontmatter":{},"headers":[],"relativePath":"public/kronos/docs/upgrades.md","lastUpdated":null}'),n={name:"public/kronos/docs/upgrades.md"},o=t("",13),l=[o];function r(i,p,c,u,d,h){return a(),s("div",null,l)}const f=e(n,[["render",r]]);export{g as __pageData,f as default};
          diff --git a/assets/public_lit_Old Things_2.0-format-changes.md.972bc545.js b/assets/public_lit_Old Things_2.0-format-changes.md.ea048463.js
          similarity index 96%
          rename from assets/public_lit_Old Things_2.0-format-changes.md.972bc545.js
          rename to assets/public_lit_Old Things_2.0-format-changes.md.ea048463.js
          index bbe72bad2..4ed248732 100644
          --- a/assets/public_lit_Old Things_2.0-format-changes.md.972bc545.js	
          +++ b/assets/public_lit_Old Things_2.0-format-changes.md.ea048463.js	
          @@ -1 +1 @@
          -import{_ as e,c as a,o as t,a as i}from"./app.a576d425.js";const u=JSON.parse('{"title":"2.0 format changes","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/Old Things/2.0-format-changes.md","lastUpdated":null}'),l={name:"public/lit/Old Things/2.0-format-changes.md"},n=i('

          2.0 format changes

          • Temp format is changed from temp.something[layer] to temp[layer].something, for consistency
          • Challenges are now saved as an object with the amount of completions in each spot. (This will break saves.)
          • effectDisplay in Challenges and Upgrades no longer takes an argument, and neither does effect for Buyables
          • Buyable cost can take an argument for amount of buyables, but it needs to function if no argument is supplied (it should do the cost for the next purchase).
          • Generation of Points now happens in the main game loop (not in a layer update function), enabled by canGenPoints in game.js.
          • Changed fullLayerReset to layerDataReset, which takes an array of names of values to keep

          In addition, many names were changed, mostly expanding abbreviations:

          All instances of:

          • chall -> challenge
          • unl -> unlocked
          • upg -> upgrade (besides CSS)
          • amt -> amount
          • desc -> description
          • resCeil -> roundUpCost
          • order -> unlockOrder
          • incr_order -> increaseUnlockOrder

          Challenges:

          • desc -> challengeDescription
          • reward -> rewardDescription
          • effect -> rewardEffect
          • effectDisplay -> rewardDisplay
          • active -> challengeActive
          ',7),o=[n];function s(r,c,d,h,g,p){return t(),a("div",null,o)}const m=e(l,[["render",s]]);export{u as __pageData,m as default}; +import{_ as e,c as a,o as t,a as i}from"./app.9bfeb8de.js";const u=JSON.parse('{"title":"2.0 format changes","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/Old Things/2.0-format-changes.md","lastUpdated":null}'),l={name:"public/lit/Old Things/2.0-format-changes.md"},n=i('

          2.0 format changes

          • Temp format is changed from temp.something[layer] to temp[layer].something, for consistency
          • Challenges are now saved as an object with the amount of completions in each spot. (This will break saves.)
          • effectDisplay in Challenges and Upgrades no longer takes an argument, and neither does effect for Buyables
          • Buyable cost can take an argument for amount of buyables, but it needs to function if no argument is supplied (it should do the cost for the next purchase).
          • Generation of Points now happens in the main game loop (not in a layer update function), enabled by canGenPoints in game.js.
          • Changed fullLayerReset to layerDataReset, which takes an array of names of values to keep

          In addition, many names were changed, mostly expanding abbreviations:

          All instances of:

          • chall -> challenge
          • unl -> unlocked
          • upg -> upgrade (besides CSS)
          • amt -> amount
          • desc -> description
          • resCeil -> roundUpCost
          • order -> unlockOrder
          • incr_order -> increaseUnlockOrder

          Challenges:

          • desc -> challengeDescription
          • reward -> rewardDescription
          • effect -> rewardEffect
          • effectDisplay -> rewardDisplay
          • active -> challengeActive
          ',7),o=[n];function s(r,c,d,h,g,p){return t(),a("div",null,o)}const m=e(l,[["render",s]]);export{u as __pageData,m as default}; diff --git a/assets/public_lit_Old Things_2.0-format-changes.md.972bc545.lean.js b/assets/public_lit_Old Things_2.0-format-changes.md.ea048463.lean.js similarity index 85% rename from assets/public_lit_Old Things_2.0-format-changes.md.972bc545.lean.js rename to assets/public_lit_Old Things_2.0-format-changes.md.ea048463.lean.js index d843f61cf..bf5881090 100644 --- a/assets/public_lit_Old Things_2.0-format-changes.md.972bc545.lean.js +++ b/assets/public_lit_Old Things_2.0-format-changes.md.ea048463.lean.js @@ -1 +1 @@ -import{_ as e,c as a,o as t,a as i}from"./app.a576d425.js";const u=JSON.parse('{"title":"2.0 format changes","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/Old Things/2.0-format-changes.md","lastUpdated":null}'),l={name:"public/lit/Old Things/2.0-format-changes.md"},n=i("",7),o=[n];function s(r,c,d,h,g,p){return t(),a("div",null,o)}const m=e(l,[["render",s]]);export{u as __pageData,m as default}; +import{_ as e,c as a,o as t,a as i}from"./app.9bfeb8de.js";const u=JSON.parse('{"title":"2.0 format changes","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/Old Things/2.0-format-changes.md","lastUpdated":null}'),l={name:"public/lit/Old Things/2.0-format-changes.md"},n=i("",7),o=[n];function s(r,c,d,h,g,p){return t(),a("div",null,o)}const m=e(l,[["render",s]]);export{u as __pageData,m as default}; diff --git a/assets/public_lit_README.md.8aaa72fa.js b/assets/public_lit_README.md.b961fe43.js similarity index 91% rename from assets/public_lit_README.md.8aaa72fa.js rename to assets/public_lit_README.md.b961fe43.js index 506ba609b..7eed5d5eb 100644 --- a/assets/public_lit_README.md.8aaa72fa.js +++ b/assets/public_lit_README.md.b961fe43.js @@ -1 +1 @@ -import{_ as e,c as t,o,a}from"./app.a576d425.js";const m=JSON.parse('{"title":"Kronos","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/README.md","lastUpdated":null}'),r={name:"public/lit/README.md"},i=a('

          Kronos

          Play here.

          Updating the website:

          • git submodule update --remote
          • git add -A
          • git commit -m "Updated kronos"
          • git push
          ',4),d=[i];function s(c,l,n,_,p,h){return o(),t("div",null,d)}const f=e(r,[["render",s]]);export{m as __pageData,f as default}; +import{_ as e,c as t,o,a}from"./app.9bfeb8de.js";const m=JSON.parse('{"title":"Kronos","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/README.md","lastUpdated":null}'),r={name:"public/lit/README.md"},i=a('

          Kronos

          Play here.

          Updating the website:

          • git submodule update --remote
          • git add -A
          • git commit -m "Updated kronos"
          • git push
          ',4),d=[i];function s(c,l,n,_,p,h){return o(),t("div",null,d)}const f=e(r,[["render",s]]);export{m as __pageData,f as default}; diff --git a/assets/public_lit_README.md.8aaa72fa.lean.js b/assets/public_lit_README.md.b961fe43.lean.js similarity index 82% rename from assets/public_lit_README.md.8aaa72fa.lean.js rename to assets/public_lit_README.md.b961fe43.lean.js index 5cc9cdfda..936eb36bf 100644 --- a/assets/public_lit_README.md.8aaa72fa.lean.js +++ b/assets/public_lit_README.md.b961fe43.lean.js @@ -1 +1 @@ -import{_ as e,c as t,o,a}from"./app.a576d425.js";const m=JSON.parse('{"title":"Kronos","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/README.md","lastUpdated":null}'),r={name:"public/lit/README.md"},i=a("",4),d=[i];function s(c,l,n,_,p,h){return o(),t("div",null,d)}const f=e(r,[["render",s]]);export{m as __pageData,f as default}; +import{_ as e,c as t,o,a}from"./app.9bfeb8de.js";const m=JSON.parse('{"title":"Kronos","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/README.md","lastUpdated":null}'),r={name:"public/lit/README.md"},i=a("",4),d=[i];function s(c,l,n,_,p,h){return o(),t("div",null,d)}const f=e(r,[["render",s]]);export{m as __pageData,f as default}; diff --git a/assets/public_lit_changelog.md.cb7c37fd.js b/assets/public_lit_changelog.md.a5b1cbe9.js similarity index 99% rename from assets/public_lit_changelog.md.cb7c37fd.js rename to assets/public_lit_changelog.md.a5b1cbe9.js index d76c4ab09..08c526c07 100644 --- a/assets/public_lit_changelog.md.cb7c37fd.js +++ b/assets/public_lit_changelog.md.a5b1cbe9.js @@ -1 +1 @@ -import{_ as e,c as i,o as l,a}from"./app.a576d425.js";const m=JSON.parse('{"title":"The Modding Tree changelog:","description":"","frontmatter":{},"headers":[{"level":2,"title":"v2.\u03C0: Incrementally Updated - 2/5/21","slug":"v2-\u03C0-incrementally-updated-2-5-21","link":"#v2-\u03C0-incrementally-updated-2-5-21","children":[]},{"level":2,"title":"v2.3.5 - 12/21/20","slug":"v2-3-5-12-21-20","link":"#v2-3-5-12-21-20","children":[]},{"level":2,"title":"v2.3.4 - 12/16/20","slug":"v2-3-4-12-16-20","link":"#v2-3-4-12-16-20","children":[]},{"level":2,"title":"v2.3.3 - 12/13/20","slug":"v2-3-3-12-13-20","link":"#v2-3-3-12-13-20","children":[]},{"level":2,"title":"v2.3.2 - 12/13/20","slug":"v2-3-2-12-13-20","link":"#v2-3-2-12-13-20","children":[]},{"level":2,"title":"v2.3.1 - 12/12/20","slug":"v2-3-1-12-12-20","link":"#v2-3-1-12-12-20","children":[]},{"level":2,"title":"v2.3: Cooler and Newer Edition - 12/10/20","slug":"v2-3-cooler-and-newer-edition-12-10-20","link":"#v2-3-cooler-and-newer-edition-12-10-20","children":[{"level":3,"title":"v2.2.8 - 12/03/20","slug":"v2-2-8-12-03-20","link":"#v2-2-8-12-03-20","children":[]},{"level":3,"title":"v2.2.7 - 11/30/20","slug":"v2-2-7-11-30-20","link":"#v2-2-7-11-30-20","children":[]},{"level":3,"title":"v2.2.6 - 11/30/20","slug":"v2-2-6-11-30-20","link":"#v2-2-6-11-30-20","children":[]},{"level":3,"title":"v2.2.5 - 11/29/20","slug":"v2-2-5-11-29-20","link":"#v2-2-5-11-29-20","children":[]},{"level":3,"title":"v2.2.4 - 11/28/20","slug":"v2-2-4-11-28-20","link":"#v2-2-4-11-28-20","children":[]},{"level":3,"title":"v2.2.3 - 11/28/20","slug":"v2-2-3-11-28-20","link":"#v2-2-3-11-28-20","children":[]},{"level":3,"title":"v2.2.2 - 11/22/20","slug":"v2-2-2-11-22-20","link":"#v2-2-2-11-22-20","children":[]},{"level":3,"title":"v2.2.1 - 11/7/20","slug":"v2-2-1-11-7-20","link":"#v2-2-1-11-7-20","children":[]}]},{"level":2,"title":"v2.2: Uprooted - 11/7/20","slug":"v2-2-uprooted-11-7-20","link":"#v2-2-uprooted-11-7-20","children":[{"level":3,"title":"v2.1.4 - 10/25/20","slug":"v2-1-4-10-25-20","link":"#v2-1-4-10-25-20","children":[]},{"level":3,"title":"v2.1.3.1 - 10/21/20","slug":"v2-1-3-1-10-21-20","link":"#v2-1-3-1-10-21-20","children":[]},{"level":3,"title":"v2.1.3 - 10/21/20","slug":"v2-1-3-10-21-20","link":"#v2-1-3-10-21-20","children":[]},{"level":3,"title":"v2.1.2 - 10/19/20","slug":"v2-1-2-10-19-20","link":"#v2-1-2-10-19-20","children":[]},{"level":3,"title":"v2.1.1 - 10/17/20","slug":"v2-1-1-10-17-20","link":"#v2-1-1-10-17-20","children":[]}]},{"level":2,"title":"v2.1: We should have thought of this sooner! - 10/17/20","slug":"v2-1-we-should-have-thought-of-this-sooner-10-17-20","link":"#v2-1-we-should-have-thought-of-this-sooner-10-17-20","children":[{"level":3,"title":"v2.0.5 - 10/16/20","slug":"v2-0-5-10-16-20","link":"#v2-0-5-10-16-20","children":[]},{"level":3,"title":"v2.0.4 - 10/16/20","slug":"v2-0-4-10-16-20","link":"#v2-0-4-10-16-20","children":[]},{"level":3,"title":"v2.0.3 - 10/16/20","slug":"v2-0-3-10-16-20","link":"#v2-0-3-10-16-20","children":[]},{"level":3,"title":"v2.0.2 - 10/15/20","slug":"v2-0-2-10-15-20","link":"#v2-0-2-10-15-20","children":[]},{"level":3,"title":"v2.0.1 - 10/15/20","slug":"v2-0-1-10-15-20","link":"#v2-0-1-10-15-20","children":[]}]},{"level":2,"title":"v2.0: The Pinnacle of Achievement Mountain - 10/15/20","slug":"v2-0-the-pinnacle-of-achievement-mountain-10-15-20","link":"#v2-0-the-pinnacle-of-achievement-mountain-10-15-20","children":[{"level":3,"title":"v1.3.5:","slug":"v1-3-5","link":"#v1-3-5","children":[]},{"level":3,"title":"v1.3.4 - 10/8/20","slug":"v1-3-4-10-8-20","link":"#v1-3-4-10-8-20","children":[]},{"level":3,"title":"v1.3.3 - 10/7/20","slug":"v1-3-3-10-7-20","link":"#v1-3-3-10-7-20","children":[]},{"level":3,"title":"v1.3.1 - 10/7/20","slug":"v1-3-1-10-7-20","link":"#v1-3-1-10-7-20","children":[]}]},{"level":2,"title":"v1.3: Tabception... ception! - 10/7/20","slug":"v1-3-tabception-ception-10-7-20","link":"#v1-3-tabception-ception-10-7-20","children":[{"level":3,"title":"v1.2.4 - 10/4/20","slug":"v1-2-4-10-4-20","link":"#v1-2-4-10-4-20","children":[]},{"level":3,"title":"v1.2.3 - 10/3/20","slug":"v1-2-3-10-3-20","link":"#v1-2-3-10-3-20","children":[]}]},{"level":2,"title":"v1.2: This Changes Everything! - 10/3/20","slug":"v1-2-this-changes-everything-10-3-20","link":"#v1-2-this-changes-everything-10-3-20","children":[{"level":3,"title":"v1.1.1:","slug":"v1-1-1","link":"#v1-1-1","children":[]}]},{"level":2,"title":"v1.1: Enhanced Edition","slug":"v1-1-enhanced-edition","link":"#v1-1-enhanced-edition","children":[]},{"level":2,"title":"v1.0:","slug":"v1-0","link":"#v1-0","children":[]}],"relativePath":"public/lit/changelog.md","lastUpdated":null}'),t={name:"public/lit/changelog.md"},n=a('

          The Modding Tree changelog:

          v2.\u03C0: Incrementally Updated - 2/5/21

          • Performance improvements.
          • Fixed tooltips overlapping with the top display.
          • Clicking a popup dismisses it immediately.
          • Added support for bulk challenge completions.
          • "Best" is updated automatically.
          • Fixed keeping Decimal values on reset.
          • Code reorganization and style improvements by fudo.

          v2.3.5 - 12/21/20

          • Added resetTime, which tracks the time since a layer prestiged or was reset.
          • A layer node will be highlighted red if one of its subtabs is highlighted red.
          • Fixed issues with keeping challenges, buyables, and clickables on reset.
          • Improved the unlocking of custom layers.
          • Other minor fixes.

          v2.3.4 - 12/16/20

          • Added a node image feature.
          • Resource display now always shows the amount of the currency the layer's gain is based on.
          • Added spacing between tree nodes.
          • Another attempt to fix tooltip flickering.

          v2.3.3 - 12/13/20

          • Fixed the first node in a row always taking up space.
          • layerShown is now optional.
          • All prestige types can now use features for custom prestige types.

          v2.3.2 - 12/13/20

          • Fixed achievement/milestone popups.

          v2.3.1 - 12/12/20

          • Another attempt to fix flickering tooltips.
          • The "this" keyword should work everywhere except tabFormat arrays (although I may have missed some things).
          • Fixed tree branches not updating when scrolling on the right-side tab.
          • Fixed a spacing issue when a node's symbol is ""
          • Removed some old, unneeded files.

          v2.3: Cooler and Newer Edition - 12/10/20

          • Added achievement/milestone popups (thank you to Jacorb for this contribution!)
          • The changelog tab is back, and can be set in mod.js.
          • Layer nodes and respec buttons will not be clicked by pressing "enter".
          • Possible fix for flickering tooltips and strange transitions.
          • The victory screen text is configurable.
          • Added image and textStyle features to achievements.
          • Added an argument to use specific rows in an "upgrades" component.
          • Fixed the comma appearing in the main display when there was no effectDescription
          • Added the ability to easily make a tab that is a collection of layers in subtabs.
          • Improved spacing for embedding layers with subtabs into subtabs.

          v2.2.8 - 12/03/20

          • Double-clicking a layer node brings you to the main subtab for that layer.
          • Attempted to fix challenges visually updating a different way.
          • Added a softcap function for use in formulas.
          • Added displayRow feature, which lets layers be shown somewhere separate from where they are in the reset order (e.g. side layers)
          • Fixed autoupgrade issue.

          v2.2.7 - 11/30/20

          • Added autoUpgrade feature.
          • resource-display now shows resource gain per second if passiveGain is active.
          • Fixed formatting issues on some large numbers.
          • Better support for using classed objects in player and in layers/tmp.
          • Made hard resetting more effective.
          • Removed Herobrine from getStartClickables.

          v2.2.6 - 11/30/20

          • Added goalDescription for challenges and made the new "canComplete" system the standard.
          • Another attempt to fix challenges not visually updating.
          • Fixed side layers not appearing.
          • Fixed getStartClickables again.

          v2.2.5 - 11/29/20

          • Added features for overriding the displays and costs/goals of upgrades and challenges to make them fully custom.
          • best, total, and unlocked are always automatically added to layerData (but best and total will only display if you add them yourself).
          • Fixed getStartClickables.

          v2.2.4 - 11/28/20

          • Added softcap and softcapPower features (for Normal layers)
          • Offline time limit and default max tick length were fixed (previously the limits were 1000x too large)
          • Added fixOldSaves.
          • You can use HTML in main-display.
          • Fixed a number of minor oddities.

          v2.2.3 - 11/28/20

          • Layers will be highlighted if you can finish a challenge.
          • The "can complete challenge" color now overrides the "already completed" color.
          • Button nodes now work as side "layers".
          • Setting a tooltip to "" hides it entirely.

          v2.2.2 - 11/22/20

          • Fixed right half of the screen being unclickable in some circumstances.
          • Fixed tree branches being offset.
          • Fix to lastSafeTab.

          v2.2.1 - 11/7/20

          • Added a small highlight to layers you can meaningfully prestige on.
          • Added passiveGeneration and autoPrestige features to standardize prestige automation. (The old ways still work, but the new ones work better with other things)
          • Improved milestones visually a bit.
          • "best" and "total" are now only displayed if present in startData.
          • Fixed issues with things not updating visually. (Thank you to to Jacorb!)
          • Side layers and button nodes can now be highlighted.
          • Updated docs on the new tree-related features.

          v2.2: Uprooted - 11/7/20

          • You can now embed a layer inside of a subtab or microtab!
          • Added support for hiding or reformatting the tree tab
          • Added non-layer button nodes
          • Added shouldNotify to subtab/microtab buttons. (You can make them highlighted)
          • Added commas to large exponents.
          • Upgrades now only show "currently" if they have an effectDisplay (so not for constant effects).
          • Achievements are part of the default tab format.
          • NaN is now handled more intelligently.
          • Renamed files, and moved less relevant ones to another folder.
          • The "hide completed challenges" setting now only hides challenges at max completions.
          • Thank you to thepaperpilot for fixing errors in docs and improving the infobox appearance!
          • Many other minor fixes.

          v2.1.4 - 10/25/20

          • Added an infobox component. Thank you to thepaperpilot for this contribution!
          • Layer type is now optional, and defaults to "none".
          • Improved the look of bars and tab buttons.
          • Improved spacing between layer nodes (also thanks to thepaperpilot!)
          • Fixed the "blank" component breaking if only specifying the height.
          • Fixed some numbers not displaying with enough digits.
          • Made a few more things able to be functions.
          • A few other minor fixes.

          v2.1.3.1 - 10/21/20

          • Fixed the update function.

          v2.1.3 - 10/21/20

          • gainMult and gainExp are now optional.
          • Layer unlocking is now kept on reset.
          • Game should start up faster.
          • Layer updates now have a determined order and starts with earlier-rowed layers.
          • Automation now has a determined order and starts with later-rowed layers.
          • Fixed issues with resetting clickables and challenges.
          • Commas should no longer appear in the decimal places of a number.
          • Fixed potential issue in displaying the tree.

          v2.1.2 - 10/19/20

          • Added buyUpgrade function (buyUpg still works though)
          • Added author name to modInfo.
          • Fix to crash caused when the name of a subtab or microtab is changed.
          • Fixes to outdated information in docs.
          • Improvements to Discord links.
          • Thank you to thepaperpilot for contributing to this update!

          v2.1.1 - 10/17/20

          • Added resource-display component, which displays the base currency for the prestige layer, as well as the best and/or total of this layer's prestige currency.
          • Fixed the value for the base currency not updating in resource-display.

          v2.1: We should have thought of this sooner! - 10/17/20

          • Moved most of the code users will want to edit to mod.js, added documentation for it.
            • Specifically, modInfo, VERSION, canGenPoints, getPointGen, and maxTickLength
          • Added getStartPoints()
          • Added the ability to store non-layer-related data
          • Added the ability to display more things at the top of the tree tab below points.
          • Made the endgame condition customizable
          • Added "sell one" and "sell all" buttons for buyables.
          • Moved the old "game" to demo.js, and replaced it with a minimal game that won't cause issues when edited.
          • Fixed issues with version number
          • Fixed number formatting issue making things like "10e9" appear.

          v2.0.5 - 10/16/20

          • Made more features (including prestige parameters) able to be dynamic.
          • Layer nodes can be hidden but still take up space with "ghost" visibility
          • Added clickableEffect for real.
          • Fixed some visual issues with bars.
          • A few other minor tweaks and improvements.

          v2.0.4 - 10/16/20

          • Fixed HTML on buttons interfering with clicking on them.

          v2.0.3 - 10/16/20

          • Fixed hotkeys not displaying in info.
          • Fixed the game supressing all external hotkeys.
          • You can use more things as currencies for upgrade costs and challenge goals using currencyLocation.
          • Added maxTickLength, which can be used to prevent offline time or tab-switching from breaking time-limit based mechanics.
          • Made buyable respec buttons and clickable "master" buttons their own components, and gave them a hide/show feature.
          • Added a general "tooltip" feature for achievements.

          v2.0.2 - 10/15/20

          • Branches are now dynamic (they can be functions).
          • Fixed a crash related to offline time.
          • Fixed links being too wide.

          v2.0.1 - 10/15/20

          • Fixed side layers appearing multiple times.

          v2.0: The Pinnacle of Achievement Mountain - 10/15/20

          • Added progress bars, which are highly customizable and can be horizontal or vertical!
          • Added "side layers", displayed smaller and off to the side, and don't get reset by default. They can be used for global achievements and statistics. Speaking of which...
          • Added achievements!
          • Added clickables, a more generalized variant of buyables.
          • Almost every value in layer data can be either a function or a constant value!
          • Added support for multiple completions of challenges.
          • Added "none" prestige type, which removes the need for any other prestige-related features.
          • The points display and other gui elements stay at the top of the screen when the tree scrolls.
          • Added getter/setter functions for the amounts and effects of most Big Features
          • Moved modInfo to game.js, added a spot in modInfo for a Discord link, changelog link. Also added a separate mod version from the TMT version in VERSION.
          • Tree structure is based on layer data, no index.html editing is needed.
          • Tmp does not need to be manually updated.
          • You don't have to have the same amount of upgrades in every row (and challs and buyables)
          • "unlocked" is optional for all Big Components (defaults to true).
          • All displays will update correctly.
          • Changelog is no longer in index.html at all.
          • Generation of Points now happens in the main game loop
          • Changed the reset functions to make keeping things easier
          • Renamed many things to increase readability (see the list in the link below)
          • Improved documentation based on feedback

          v1.3.5:

          • Completely automated convertToDecimal, now you never have to worry about it again.
          • Branches can be defined without a color id. But they can also use hex values for color ids!
          • Created a tutorial for getting started with TMT and Github.
          • Page title is now automatically taken from mod name.

          v1.3.4 - 10/8/20

          • Added "midsection" feature to add things to a tab's layout while still keeping the standard layout.
          • Fix for being able to buy more buyables than you should.

          v1.3.3 - 10/7/20

          • Fix for the "order of operations" issue in temp.

          v1.3.1 - 10/7/20

          • Added custom CSS and tooltips for Layer Nodes.
          • Added custom CSS for upgrades, buyables, milestones, and challenges, both individually and layer-wide.
          • You can now use HTML in most display text!
          • You can now make milestones unlockable and not display immediately.
          • Fixed importing saves, and issue with upgrades not appearing, and probably more.
          • Optional "name" layer feature, used in confirmation messages.

          v1.3: Tabception... ception! - 10/7/20

          • Added subtabs! And also a Micro-tab component to let you make smaller subtab-esque areas anywhere.
          • Added a "custom" prestige formula type, and a number of features to support it.
          • Added points/sec display (can be disabled).
          • Added h-line, v-line and image-display components, plus components for individual upgrades, challenges, and milestones.
          • Added upgEffect, buyableEffect, and challEffect functions.
          • Added "hide completed challenges" setting.
          • Moved old changelogs to a separate place.
          • Fixed hasMilestone and incr_order.
          • Static layers now show the currency amount needed for the next one if you can buy max.

          v1.2.4 - 10/4/20

          • Layers are now highlighted if you can buy an upgrade, and a new feature, shouldNotify, lets you make it highlight other ways.
          • Fixed bugs with hasUpg, hasChall, hasMilestone, and inChallenge.
          • Changed the sample code to use the above functions for convenience.

          v1.2.3 - 10/3/20

          • Added a row component, which displays a list of objects in a row.
          • Added a column component, which displays a list of objects in a column (useful within a row).
          • Changed blanks to have a customizable width and height.

          v1.2: This Changes Everything! - 10/3/20

          • Many layer features can now be static values or functions. (This made some formats change, which will break old things)
          • You can now use the "this" keyword, to make code easier to transfer when making new layers.
          • Also added "this.layer", which is the current layer's name, and works on existing subfeatures (e.g. individual upgrades) as well! Subfeatures also have "this.id".
          • Fixed a big save issue. If you use a unique mod id, your save will never conflict with other mods.
          • Added a configurable offline time limit in modinfo at the top of index.html. (default 1 hour)
          • Added a few minor features, and updated the docs with new information.

          v1.1.1:

          • You can define hotkeys directly from layer config.

          v1.1: Enhanced Edition

          • Added "Buyables", which can function like Space Buildings or Enhancers.
          • Custom CSS can now be used on any component! Make the third argument an object with CSS parameters.
          • Lots of minor good things.

          v1.0:

          • First release.
          ',79),o=[n];function d(r,s,h,u,c,v){return l(),i("div",null,o)}const f=e(t,[["render",d]]);export{m as __pageData,f as default}; +import{_ as e,c as i,o as l,a}from"./app.9bfeb8de.js";const m=JSON.parse('{"title":"The Modding Tree changelog:","description":"","frontmatter":{},"headers":[{"level":2,"title":"v2.\u03C0: Incrementally Updated - 2/5/21","slug":"v2-\u03C0-incrementally-updated-2-5-21","link":"#v2-\u03C0-incrementally-updated-2-5-21","children":[]},{"level":2,"title":"v2.3.5 - 12/21/20","slug":"v2-3-5-12-21-20","link":"#v2-3-5-12-21-20","children":[]},{"level":2,"title":"v2.3.4 - 12/16/20","slug":"v2-3-4-12-16-20","link":"#v2-3-4-12-16-20","children":[]},{"level":2,"title":"v2.3.3 - 12/13/20","slug":"v2-3-3-12-13-20","link":"#v2-3-3-12-13-20","children":[]},{"level":2,"title":"v2.3.2 - 12/13/20","slug":"v2-3-2-12-13-20","link":"#v2-3-2-12-13-20","children":[]},{"level":2,"title":"v2.3.1 - 12/12/20","slug":"v2-3-1-12-12-20","link":"#v2-3-1-12-12-20","children":[]},{"level":2,"title":"v2.3: Cooler and Newer Edition - 12/10/20","slug":"v2-3-cooler-and-newer-edition-12-10-20","link":"#v2-3-cooler-and-newer-edition-12-10-20","children":[{"level":3,"title":"v2.2.8 - 12/03/20","slug":"v2-2-8-12-03-20","link":"#v2-2-8-12-03-20","children":[]},{"level":3,"title":"v2.2.7 - 11/30/20","slug":"v2-2-7-11-30-20","link":"#v2-2-7-11-30-20","children":[]},{"level":3,"title":"v2.2.6 - 11/30/20","slug":"v2-2-6-11-30-20","link":"#v2-2-6-11-30-20","children":[]},{"level":3,"title":"v2.2.5 - 11/29/20","slug":"v2-2-5-11-29-20","link":"#v2-2-5-11-29-20","children":[]},{"level":3,"title":"v2.2.4 - 11/28/20","slug":"v2-2-4-11-28-20","link":"#v2-2-4-11-28-20","children":[]},{"level":3,"title":"v2.2.3 - 11/28/20","slug":"v2-2-3-11-28-20","link":"#v2-2-3-11-28-20","children":[]},{"level":3,"title":"v2.2.2 - 11/22/20","slug":"v2-2-2-11-22-20","link":"#v2-2-2-11-22-20","children":[]},{"level":3,"title":"v2.2.1 - 11/7/20","slug":"v2-2-1-11-7-20","link":"#v2-2-1-11-7-20","children":[]}]},{"level":2,"title":"v2.2: Uprooted - 11/7/20","slug":"v2-2-uprooted-11-7-20","link":"#v2-2-uprooted-11-7-20","children":[{"level":3,"title":"v2.1.4 - 10/25/20","slug":"v2-1-4-10-25-20","link":"#v2-1-4-10-25-20","children":[]},{"level":3,"title":"v2.1.3.1 - 10/21/20","slug":"v2-1-3-1-10-21-20","link":"#v2-1-3-1-10-21-20","children":[]},{"level":3,"title":"v2.1.3 - 10/21/20","slug":"v2-1-3-10-21-20","link":"#v2-1-3-10-21-20","children":[]},{"level":3,"title":"v2.1.2 - 10/19/20","slug":"v2-1-2-10-19-20","link":"#v2-1-2-10-19-20","children":[]},{"level":3,"title":"v2.1.1 - 10/17/20","slug":"v2-1-1-10-17-20","link":"#v2-1-1-10-17-20","children":[]}]},{"level":2,"title":"v2.1: We should have thought of this sooner! - 10/17/20","slug":"v2-1-we-should-have-thought-of-this-sooner-10-17-20","link":"#v2-1-we-should-have-thought-of-this-sooner-10-17-20","children":[{"level":3,"title":"v2.0.5 - 10/16/20","slug":"v2-0-5-10-16-20","link":"#v2-0-5-10-16-20","children":[]},{"level":3,"title":"v2.0.4 - 10/16/20","slug":"v2-0-4-10-16-20","link":"#v2-0-4-10-16-20","children":[]},{"level":3,"title":"v2.0.3 - 10/16/20","slug":"v2-0-3-10-16-20","link":"#v2-0-3-10-16-20","children":[]},{"level":3,"title":"v2.0.2 - 10/15/20","slug":"v2-0-2-10-15-20","link":"#v2-0-2-10-15-20","children":[]},{"level":3,"title":"v2.0.1 - 10/15/20","slug":"v2-0-1-10-15-20","link":"#v2-0-1-10-15-20","children":[]}]},{"level":2,"title":"v2.0: The Pinnacle of Achievement Mountain - 10/15/20","slug":"v2-0-the-pinnacle-of-achievement-mountain-10-15-20","link":"#v2-0-the-pinnacle-of-achievement-mountain-10-15-20","children":[{"level":3,"title":"v1.3.5:","slug":"v1-3-5","link":"#v1-3-5","children":[]},{"level":3,"title":"v1.3.4 - 10/8/20","slug":"v1-3-4-10-8-20","link":"#v1-3-4-10-8-20","children":[]},{"level":3,"title":"v1.3.3 - 10/7/20","slug":"v1-3-3-10-7-20","link":"#v1-3-3-10-7-20","children":[]},{"level":3,"title":"v1.3.1 - 10/7/20","slug":"v1-3-1-10-7-20","link":"#v1-3-1-10-7-20","children":[]}]},{"level":2,"title":"v1.3: Tabception... ception! - 10/7/20","slug":"v1-3-tabception-ception-10-7-20","link":"#v1-3-tabception-ception-10-7-20","children":[{"level":3,"title":"v1.2.4 - 10/4/20","slug":"v1-2-4-10-4-20","link":"#v1-2-4-10-4-20","children":[]},{"level":3,"title":"v1.2.3 - 10/3/20","slug":"v1-2-3-10-3-20","link":"#v1-2-3-10-3-20","children":[]}]},{"level":2,"title":"v1.2: This Changes Everything! - 10/3/20","slug":"v1-2-this-changes-everything-10-3-20","link":"#v1-2-this-changes-everything-10-3-20","children":[{"level":3,"title":"v1.1.1:","slug":"v1-1-1","link":"#v1-1-1","children":[]}]},{"level":2,"title":"v1.1: Enhanced Edition","slug":"v1-1-enhanced-edition","link":"#v1-1-enhanced-edition","children":[]},{"level":2,"title":"v1.0:","slug":"v1-0","link":"#v1-0","children":[]}],"relativePath":"public/lit/changelog.md","lastUpdated":null}'),t={name:"public/lit/changelog.md"},n=a('

          The Modding Tree changelog:

          v2.\u03C0: Incrementally Updated - 2/5/21

          • Performance improvements.
          • Fixed tooltips overlapping with the top display.
          • Clicking a popup dismisses it immediately.
          • Added support for bulk challenge completions.
          • "Best" is updated automatically.
          • Fixed keeping Decimal values on reset.
          • Code reorganization and style improvements by fudo.

          v2.3.5 - 12/21/20

          • Added resetTime, which tracks the time since a layer prestiged or was reset.
          • A layer node will be highlighted red if one of its subtabs is highlighted red.
          • Fixed issues with keeping challenges, buyables, and clickables on reset.
          • Improved the unlocking of custom layers.
          • Other minor fixes.

          v2.3.4 - 12/16/20

          • Added a node image feature.
          • Resource display now always shows the amount of the currency the layer's gain is based on.
          • Added spacing between tree nodes.
          • Another attempt to fix tooltip flickering.

          v2.3.3 - 12/13/20

          • Fixed the first node in a row always taking up space.
          • layerShown is now optional.
          • All prestige types can now use features for custom prestige types.

          v2.3.2 - 12/13/20

          • Fixed achievement/milestone popups.

          v2.3.1 - 12/12/20

          • Another attempt to fix flickering tooltips.
          • The "this" keyword should work everywhere except tabFormat arrays (although I may have missed some things).
          • Fixed tree branches not updating when scrolling on the right-side tab.
          • Fixed a spacing issue when a node's symbol is ""
          • Removed some old, unneeded files.

          v2.3: Cooler and Newer Edition - 12/10/20

          • Added achievement/milestone popups (thank you to Jacorb for this contribution!)
          • The changelog tab is back, and can be set in mod.js.
          • Layer nodes and respec buttons will not be clicked by pressing "enter".
          • Possible fix for flickering tooltips and strange transitions.
          • The victory screen text is configurable.
          • Added image and textStyle features to achievements.
          • Added an argument to use specific rows in an "upgrades" component.
          • Fixed the comma appearing in the main display when there was no effectDescription
          • Added the ability to easily make a tab that is a collection of layers in subtabs.
          • Improved spacing for embedding layers with subtabs into subtabs.

          v2.2.8 - 12/03/20

          • Double-clicking a layer node brings you to the main subtab for that layer.
          • Attempted to fix challenges visually updating a different way.
          • Added a softcap function for use in formulas.
          • Added displayRow feature, which lets layers be shown somewhere separate from where they are in the reset order (e.g. side layers)
          • Fixed autoupgrade issue.

          v2.2.7 - 11/30/20

          • Added autoUpgrade feature.
          • resource-display now shows resource gain per second if passiveGain is active.
          • Fixed formatting issues on some large numbers.
          • Better support for using classed objects in player and in layers/tmp.
          • Made hard resetting more effective.
          • Removed Herobrine from getStartClickables.

          v2.2.6 - 11/30/20

          • Added goalDescription for challenges and made the new "canComplete" system the standard.
          • Another attempt to fix challenges not visually updating.
          • Fixed side layers not appearing.
          • Fixed getStartClickables again.

          v2.2.5 - 11/29/20

          • Added features for overriding the displays and costs/goals of upgrades and challenges to make them fully custom.
          • best, total, and unlocked are always automatically added to layerData (but best and total will only display if you add them yourself).
          • Fixed getStartClickables.

          v2.2.4 - 11/28/20

          • Added softcap and softcapPower features (for Normal layers)
          • Offline time limit and default max tick length were fixed (previously the limits were 1000x too large)
          • Added fixOldSaves.
          • You can use HTML in main-display.
          • Fixed a number of minor oddities.

          v2.2.3 - 11/28/20

          • Layers will be highlighted if you can finish a challenge.
          • The "can complete challenge" color now overrides the "already completed" color.
          • Button nodes now work as side "layers".
          • Setting a tooltip to "" hides it entirely.

          v2.2.2 - 11/22/20

          • Fixed right half of the screen being unclickable in some circumstances.
          • Fixed tree branches being offset.
          • Fix to lastSafeTab.

          v2.2.1 - 11/7/20

          • Added a small highlight to layers you can meaningfully prestige on.
          • Added passiveGeneration and autoPrestige features to standardize prestige automation. (The old ways still work, but the new ones work better with other things)
          • Improved milestones visually a bit.
          • "best" and "total" are now only displayed if present in startData.
          • Fixed issues with things not updating visually. (Thank you to to Jacorb!)
          • Side layers and button nodes can now be highlighted.
          • Updated docs on the new tree-related features.

          v2.2: Uprooted - 11/7/20

          • You can now embed a layer inside of a subtab or microtab!
          • Added support for hiding or reformatting the tree tab
          • Added non-layer button nodes
          • Added shouldNotify to subtab/microtab buttons. (You can make them highlighted)
          • Added commas to large exponents.
          • Upgrades now only show "currently" if they have an effectDisplay (so not for constant effects).
          • Achievements are part of the default tab format.
          • NaN is now handled more intelligently.
          • Renamed files, and moved less relevant ones to another folder.
          • The "hide completed challenges" setting now only hides challenges at max completions.
          • Thank you to thepaperpilot for fixing errors in docs and improving the infobox appearance!
          • Many other minor fixes.

          v2.1.4 - 10/25/20

          • Added an infobox component. Thank you to thepaperpilot for this contribution!
          • Layer type is now optional, and defaults to "none".
          • Improved the look of bars and tab buttons.
          • Improved spacing between layer nodes (also thanks to thepaperpilot!)
          • Fixed the "blank" component breaking if only specifying the height.
          • Fixed some numbers not displaying with enough digits.
          • Made a few more things able to be functions.
          • A few other minor fixes.

          v2.1.3.1 - 10/21/20

          • Fixed the update function.

          v2.1.3 - 10/21/20

          • gainMult and gainExp are now optional.
          • Layer unlocking is now kept on reset.
          • Game should start up faster.
          • Layer updates now have a determined order and starts with earlier-rowed layers.
          • Automation now has a determined order and starts with later-rowed layers.
          • Fixed issues with resetting clickables and challenges.
          • Commas should no longer appear in the decimal places of a number.
          • Fixed potential issue in displaying the tree.

          v2.1.2 - 10/19/20

          • Added buyUpgrade function (buyUpg still works though)
          • Added author name to modInfo.
          • Fix to crash caused when the name of a subtab or microtab is changed.
          • Fixes to outdated information in docs.
          • Improvements to Discord links.
          • Thank you to thepaperpilot for contributing to this update!

          v2.1.1 - 10/17/20

          • Added resource-display component, which displays the base currency for the prestige layer, as well as the best and/or total of this layer's prestige currency.
          • Fixed the value for the base currency not updating in resource-display.

          v2.1: We should have thought of this sooner! - 10/17/20

          • Moved most of the code users will want to edit to mod.js, added documentation for it.
            • Specifically, modInfo, VERSION, canGenPoints, getPointGen, and maxTickLength
          • Added getStartPoints()
          • Added the ability to store non-layer-related data
          • Added the ability to display more things at the top of the tree tab below points.
          • Made the endgame condition customizable
          • Added "sell one" and "sell all" buttons for buyables.
          • Moved the old "game" to demo.js, and replaced it with a minimal game that won't cause issues when edited.
          • Fixed issues with version number
          • Fixed number formatting issue making things like "10e9" appear.

          v2.0.5 - 10/16/20

          • Made more features (including prestige parameters) able to be dynamic.
          • Layer nodes can be hidden but still take up space with "ghost" visibility
          • Added clickableEffect for real.
          • Fixed some visual issues with bars.
          • A few other minor tweaks and improvements.

          v2.0.4 - 10/16/20

          • Fixed HTML on buttons interfering with clicking on them.

          v2.0.3 - 10/16/20

          • Fixed hotkeys not displaying in info.
          • Fixed the game supressing all external hotkeys.
          • You can use more things as currencies for upgrade costs and challenge goals using currencyLocation.
          • Added maxTickLength, which can be used to prevent offline time or tab-switching from breaking time-limit based mechanics.
          • Made buyable respec buttons and clickable "master" buttons their own components, and gave them a hide/show feature.
          • Added a general "tooltip" feature for achievements.

          v2.0.2 - 10/15/20

          • Branches are now dynamic (they can be functions).
          • Fixed a crash related to offline time.
          • Fixed links being too wide.

          v2.0.1 - 10/15/20

          • Fixed side layers appearing multiple times.

          v2.0: The Pinnacle of Achievement Mountain - 10/15/20

          • Added progress bars, which are highly customizable and can be horizontal or vertical!
          • Added "side layers", displayed smaller and off to the side, and don't get reset by default. They can be used for global achievements and statistics. Speaking of which...
          • Added achievements!
          • Added clickables, a more generalized variant of buyables.
          • Almost every value in layer data can be either a function or a constant value!
          • Added support for multiple completions of challenges.
          • Added "none" prestige type, which removes the need for any other prestige-related features.
          • The points display and other gui elements stay at the top of the screen when the tree scrolls.
          • Added getter/setter functions for the amounts and effects of most Big Features
          • Moved modInfo to game.js, added a spot in modInfo for a Discord link, changelog link. Also added a separate mod version from the TMT version in VERSION.
          • Tree structure is based on layer data, no index.html editing is needed.
          • Tmp does not need to be manually updated.
          • You don't have to have the same amount of upgrades in every row (and challs and buyables)
          • "unlocked" is optional for all Big Components (defaults to true).
          • All displays will update correctly.
          • Changelog is no longer in index.html at all.
          • Generation of Points now happens in the main game loop
          • Changed the reset functions to make keeping things easier
          • Renamed many things to increase readability (see the list in the link below)
          • Improved documentation based on feedback

          v1.3.5:

          • Completely automated convertToDecimal, now you never have to worry about it again.
          • Branches can be defined without a color id. But they can also use hex values for color ids!
          • Created a tutorial for getting started with TMT and Github.
          • Page title is now automatically taken from mod name.

          v1.3.4 - 10/8/20

          • Added "midsection" feature to add things to a tab's layout while still keeping the standard layout.
          • Fix for being able to buy more buyables than you should.

          v1.3.3 - 10/7/20

          • Fix for the "order of operations" issue in temp.

          v1.3.1 - 10/7/20

          • Added custom CSS and tooltips for Layer Nodes.
          • Added custom CSS for upgrades, buyables, milestones, and challenges, both individually and layer-wide.
          • You can now use HTML in most display text!
          • You can now make milestones unlockable and not display immediately.
          • Fixed importing saves, and issue with upgrades not appearing, and probably more.
          • Optional "name" layer feature, used in confirmation messages.

          v1.3: Tabception... ception! - 10/7/20

          • Added subtabs! And also a Micro-tab component to let you make smaller subtab-esque areas anywhere.
          • Added a "custom" prestige formula type, and a number of features to support it.
          • Added points/sec display (can be disabled).
          • Added h-line, v-line and image-display components, plus components for individual upgrades, challenges, and milestones.
          • Added upgEffect, buyableEffect, and challEffect functions.
          • Added "hide completed challenges" setting.
          • Moved old changelogs to a separate place.
          • Fixed hasMilestone and incr_order.
          • Static layers now show the currency amount needed for the next one if you can buy max.

          v1.2.4 - 10/4/20

          • Layers are now highlighted if you can buy an upgrade, and a new feature, shouldNotify, lets you make it highlight other ways.
          • Fixed bugs with hasUpg, hasChall, hasMilestone, and inChallenge.
          • Changed the sample code to use the above functions for convenience.

          v1.2.3 - 10/3/20

          • Added a row component, which displays a list of objects in a row.
          • Added a column component, which displays a list of objects in a column (useful within a row).
          • Changed blanks to have a customizable width and height.

          v1.2: This Changes Everything! - 10/3/20

          • Many layer features can now be static values or functions. (This made some formats change, which will break old things)
          • You can now use the "this" keyword, to make code easier to transfer when making new layers.
          • Also added "this.layer", which is the current layer's name, and works on existing subfeatures (e.g. individual upgrades) as well! Subfeatures also have "this.id".
          • Fixed a big save issue. If you use a unique mod id, your save will never conflict with other mods.
          • Added a configurable offline time limit in modinfo at the top of index.html. (default 1 hour)
          • Added a few minor features, and updated the docs with new information.

          v1.1.1:

          • You can define hotkeys directly from layer config.

          v1.1: Enhanced Edition

          • Added "Buyables", which can function like Space Buildings or Enhancers.
          • Custom CSS can now be used on any component! Make the third argument an object with CSS parameters.
          • Lots of minor good things.

          v1.0:

          • First release.
          ',79),o=[n];function d(r,s,h,u,c,v){return l(),i("div",null,o)}const f=e(t,[["render",d]]);export{m as __pageData,f as default}; diff --git a/assets/public_lit_changelog.md.cb7c37fd.lean.js b/assets/public_lit_changelog.md.a5b1cbe9.lean.js similarity index 98% rename from assets/public_lit_changelog.md.cb7c37fd.lean.js rename to assets/public_lit_changelog.md.a5b1cbe9.lean.js index 7a8ebfbbc..be2626858 100644 --- a/assets/public_lit_changelog.md.cb7c37fd.lean.js +++ b/assets/public_lit_changelog.md.a5b1cbe9.lean.js @@ -1 +1 @@ -import{_ as e,c as i,o as l,a}from"./app.a576d425.js";const m=JSON.parse('{"title":"The Modding Tree changelog:","description":"","frontmatter":{},"headers":[{"level":2,"title":"v2.\u03C0: Incrementally Updated - 2/5/21","slug":"v2-\u03C0-incrementally-updated-2-5-21","link":"#v2-\u03C0-incrementally-updated-2-5-21","children":[]},{"level":2,"title":"v2.3.5 - 12/21/20","slug":"v2-3-5-12-21-20","link":"#v2-3-5-12-21-20","children":[]},{"level":2,"title":"v2.3.4 - 12/16/20","slug":"v2-3-4-12-16-20","link":"#v2-3-4-12-16-20","children":[]},{"level":2,"title":"v2.3.3 - 12/13/20","slug":"v2-3-3-12-13-20","link":"#v2-3-3-12-13-20","children":[]},{"level":2,"title":"v2.3.2 - 12/13/20","slug":"v2-3-2-12-13-20","link":"#v2-3-2-12-13-20","children":[]},{"level":2,"title":"v2.3.1 - 12/12/20","slug":"v2-3-1-12-12-20","link":"#v2-3-1-12-12-20","children":[]},{"level":2,"title":"v2.3: Cooler and Newer Edition - 12/10/20","slug":"v2-3-cooler-and-newer-edition-12-10-20","link":"#v2-3-cooler-and-newer-edition-12-10-20","children":[{"level":3,"title":"v2.2.8 - 12/03/20","slug":"v2-2-8-12-03-20","link":"#v2-2-8-12-03-20","children":[]},{"level":3,"title":"v2.2.7 - 11/30/20","slug":"v2-2-7-11-30-20","link":"#v2-2-7-11-30-20","children":[]},{"level":3,"title":"v2.2.6 - 11/30/20","slug":"v2-2-6-11-30-20","link":"#v2-2-6-11-30-20","children":[]},{"level":3,"title":"v2.2.5 - 11/29/20","slug":"v2-2-5-11-29-20","link":"#v2-2-5-11-29-20","children":[]},{"level":3,"title":"v2.2.4 - 11/28/20","slug":"v2-2-4-11-28-20","link":"#v2-2-4-11-28-20","children":[]},{"level":3,"title":"v2.2.3 - 11/28/20","slug":"v2-2-3-11-28-20","link":"#v2-2-3-11-28-20","children":[]},{"level":3,"title":"v2.2.2 - 11/22/20","slug":"v2-2-2-11-22-20","link":"#v2-2-2-11-22-20","children":[]},{"level":3,"title":"v2.2.1 - 11/7/20","slug":"v2-2-1-11-7-20","link":"#v2-2-1-11-7-20","children":[]}]},{"level":2,"title":"v2.2: Uprooted - 11/7/20","slug":"v2-2-uprooted-11-7-20","link":"#v2-2-uprooted-11-7-20","children":[{"level":3,"title":"v2.1.4 - 10/25/20","slug":"v2-1-4-10-25-20","link":"#v2-1-4-10-25-20","children":[]},{"level":3,"title":"v2.1.3.1 - 10/21/20","slug":"v2-1-3-1-10-21-20","link":"#v2-1-3-1-10-21-20","children":[]},{"level":3,"title":"v2.1.3 - 10/21/20","slug":"v2-1-3-10-21-20","link":"#v2-1-3-10-21-20","children":[]},{"level":3,"title":"v2.1.2 - 10/19/20","slug":"v2-1-2-10-19-20","link":"#v2-1-2-10-19-20","children":[]},{"level":3,"title":"v2.1.1 - 10/17/20","slug":"v2-1-1-10-17-20","link":"#v2-1-1-10-17-20","children":[]}]},{"level":2,"title":"v2.1: We should have thought of this sooner! - 10/17/20","slug":"v2-1-we-should-have-thought-of-this-sooner-10-17-20","link":"#v2-1-we-should-have-thought-of-this-sooner-10-17-20","children":[{"level":3,"title":"v2.0.5 - 10/16/20","slug":"v2-0-5-10-16-20","link":"#v2-0-5-10-16-20","children":[]},{"level":3,"title":"v2.0.4 - 10/16/20","slug":"v2-0-4-10-16-20","link":"#v2-0-4-10-16-20","children":[]},{"level":3,"title":"v2.0.3 - 10/16/20","slug":"v2-0-3-10-16-20","link":"#v2-0-3-10-16-20","children":[]},{"level":3,"title":"v2.0.2 - 10/15/20","slug":"v2-0-2-10-15-20","link":"#v2-0-2-10-15-20","children":[]},{"level":3,"title":"v2.0.1 - 10/15/20","slug":"v2-0-1-10-15-20","link":"#v2-0-1-10-15-20","children":[]}]},{"level":2,"title":"v2.0: The Pinnacle of Achievement Mountain - 10/15/20","slug":"v2-0-the-pinnacle-of-achievement-mountain-10-15-20","link":"#v2-0-the-pinnacle-of-achievement-mountain-10-15-20","children":[{"level":3,"title":"v1.3.5:","slug":"v1-3-5","link":"#v1-3-5","children":[]},{"level":3,"title":"v1.3.4 - 10/8/20","slug":"v1-3-4-10-8-20","link":"#v1-3-4-10-8-20","children":[]},{"level":3,"title":"v1.3.3 - 10/7/20","slug":"v1-3-3-10-7-20","link":"#v1-3-3-10-7-20","children":[]},{"level":3,"title":"v1.3.1 - 10/7/20","slug":"v1-3-1-10-7-20","link":"#v1-3-1-10-7-20","children":[]}]},{"level":2,"title":"v1.3: Tabception... ception! - 10/7/20","slug":"v1-3-tabception-ception-10-7-20","link":"#v1-3-tabception-ception-10-7-20","children":[{"level":3,"title":"v1.2.4 - 10/4/20","slug":"v1-2-4-10-4-20","link":"#v1-2-4-10-4-20","children":[]},{"level":3,"title":"v1.2.3 - 10/3/20","slug":"v1-2-3-10-3-20","link":"#v1-2-3-10-3-20","children":[]}]},{"level":2,"title":"v1.2: This Changes Everything! - 10/3/20","slug":"v1-2-this-changes-everything-10-3-20","link":"#v1-2-this-changes-everything-10-3-20","children":[{"level":3,"title":"v1.1.1:","slug":"v1-1-1","link":"#v1-1-1","children":[]}]},{"level":2,"title":"v1.1: Enhanced Edition","slug":"v1-1-enhanced-edition","link":"#v1-1-enhanced-edition","children":[]},{"level":2,"title":"v1.0:","slug":"v1-0","link":"#v1-0","children":[]}],"relativePath":"public/lit/changelog.md","lastUpdated":null}'),t={name:"public/lit/changelog.md"},n=a("",79),o=[n];function d(r,s,h,u,c,v){return l(),i("div",null,o)}const f=e(t,[["render",d]]);export{m as __pageData,f as default}; +import{_ as e,c as i,o as l,a}from"./app.9bfeb8de.js";const m=JSON.parse('{"title":"The Modding Tree changelog:","description":"","frontmatter":{},"headers":[{"level":2,"title":"v2.\u03C0: Incrementally Updated - 2/5/21","slug":"v2-\u03C0-incrementally-updated-2-5-21","link":"#v2-\u03C0-incrementally-updated-2-5-21","children":[]},{"level":2,"title":"v2.3.5 - 12/21/20","slug":"v2-3-5-12-21-20","link":"#v2-3-5-12-21-20","children":[]},{"level":2,"title":"v2.3.4 - 12/16/20","slug":"v2-3-4-12-16-20","link":"#v2-3-4-12-16-20","children":[]},{"level":2,"title":"v2.3.3 - 12/13/20","slug":"v2-3-3-12-13-20","link":"#v2-3-3-12-13-20","children":[]},{"level":2,"title":"v2.3.2 - 12/13/20","slug":"v2-3-2-12-13-20","link":"#v2-3-2-12-13-20","children":[]},{"level":2,"title":"v2.3.1 - 12/12/20","slug":"v2-3-1-12-12-20","link":"#v2-3-1-12-12-20","children":[]},{"level":2,"title":"v2.3: Cooler and Newer Edition - 12/10/20","slug":"v2-3-cooler-and-newer-edition-12-10-20","link":"#v2-3-cooler-and-newer-edition-12-10-20","children":[{"level":3,"title":"v2.2.8 - 12/03/20","slug":"v2-2-8-12-03-20","link":"#v2-2-8-12-03-20","children":[]},{"level":3,"title":"v2.2.7 - 11/30/20","slug":"v2-2-7-11-30-20","link":"#v2-2-7-11-30-20","children":[]},{"level":3,"title":"v2.2.6 - 11/30/20","slug":"v2-2-6-11-30-20","link":"#v2-2-6-11-30-20","children":[]},{"level":3,"title":"v2.2.5 - 11/29/20","slug":"v2-2-5-11-29-20","link":"#v2-2-5-11-29-20","children":[]},{"level":3,"title":"v2.2.4 - 11/28/20","slug":"v2-2-4-11-28-20","link":"#v2-2-4-11-28-20","children":[]},{"level":3,"title":"v2.2.3 - 11/28/20","slug":"v2-2-3-11-28-20","link":"#v2-2-3-11-28-20","children":[]},{"level":3,"title":"v2.2.2 - 11/22/20","slug":"v2-2-2-11-22-20","link":"#v2-2-2-11-22-20","children":[]},{"level":3,"title":"v2.2.1 - 11/7/20","slug":"v2-2-1-11-7-20","link":"#v2-2-1-11-7-20","children":[]}]},{"level":2,"title":"v2.2: Uprooted - 11/7/20","slug":"v2-2-uprooted-11-7-20","link":"#v2-2-uprooted-11-7-20","children":[{"level":3,"title":"v2.1.4 - 10/25/20","slug":"v2-1-4-10-25-20","link":"#v2-1-4-10-25-20","children":[]},{"level":3,"title":"v2.1.3.1 - 10/21/20","slug":"v2-1-3-1-10-21-20","link":"#v2-1-3-1-10-21-20","children":[]},{"level":3,"title":"v2.1.3 - 10/21/20","slug":"v2-1-3-10-21-20","link":"#v2-1-3-10-21-20","children":[]},{"level":3,"title":"v2.1.2 - 10/19/20","slug":"v2-1-2-10-19-20","link":"#v2-1-2-10-19-20","children":[]},{"level":3,"title":"v2.1.1 - 10/17/20","slug":"v2-1-1-10-17-20","link":"#v2-1-1-10-17-20","children":[]}]},{"level":2,"title":"v2.1: We should have thought of this sooner! - 10/17/20","slug":"v2-1-we-should-have-thought-of-this-sooner-10-17-20","link":"#v2-1-we-should-have-thought-of-this-sooner-10-17-20","children":[{"level":3,"title":"v2.0.5 - 10/16/20","slug":"v2-0-5-10-16-20","link":"#v2-0-5-10-16-20","children":[]},{"level":3,"title":"v2.0.4 - 10/16/20","slug":"v2-0-4-10-16-20","link":"#v2-0-4-10-16-20","children":[]},{"level":3,"title":"v2.0.3 - 10/16/20","slug":"v2-0-3-10-16-20","link":"#v2-0-3-10-16-20","children":[]},{"level":3,"title":"v2.0.2 - 10/15/20","slug":"v2-0-2-10-15-20","link":"#v2-0-2-10-15-20","children":[]},{"level":3,"title":"v2.0.1 - 10/15/20","slug":"v2-0-1-10-15-20","link":"#v2-0-1-10-15-20","children":[]}]},{"level":2,"title":"v2.0: The Pinnacle of Achievement Mountain - 10/15/20","slug":"v2-0-the-pinnacle-of-achievement-mountain-10-15-20","link":"#v2-0-the-pinnacle-of-achievement-mountain-10-15-20","children":[{"level":3,"title":"v1.3.5:","slug":"v1-3-5","link":"#v1-3-5","children":[]},{"level":3,"title":"v1.3.4 - 10/8/20","slug":"v1-3-4-10-8-20","link":"#v1-3-4-10-8-20","children":[]},{"level":3,"title":"v1.3.3 - 10/7/20","slug":"v1-3-3-10-7-20","link":"#v1-3-3-10-7-20","children":[]},{"level":3,"title":"v1.3.1 - 10/7/20","slug":"v1-3-1-10-7-20","link":"#v1-3-1-10-7-20","children":[]}]},{"level":2,"title":"v1.3: Tabception... ception! - 10/7/20","slug":"v1-3-tabception-ception-10-7-20","link":"#v1-3-tabception-ception-10-7-20","children":[{"level":3,"title":"v1.2.4 - 10/4/20","slug":"v1-2-4-10-4-20","link":"#v1-2-4-10-4-20","children":[]},{"level":3,"title":"v1.2.3 - 10/3/20","slug":"v1-2-3-10-3-20","link":"#v1-2-3-10-3-20","children":[]}]},{"level":2,"title":"v1.2: This Changes Everything! - 10/3/20","slug":"v1-2-this-changes-everything-10-3-20","link":"#v1-2-this-changes-everything-10-3-20","children":[{"level":3,"title":"v1.1.1:","slug":"v1-1-1","link":"#v1-1-1","children":[]}]},{"level":2,"title":"v1.1: Enhanced Edition","slug":"v1-1-enhanced-edition","link":"#v1-1-enhanced-edition","children":[]},{"level":2,"title":"v1.0:","slug":"v1-0","link":"#v1-0","children":[]}],"relativePath":"public/lit/changelog.md","lastUpdated":null}'),t={name:"public/lit/changelog.md"},n=a("",79),o=[n];function d(r,s,h,u,c,v){return l(),i("div",null,o)}const f=e(t,[["render",d]]);export{m as __pageData,f as default}; diff --git a/assets/public_lit_docs_!general-info.md.471f7f7d.js b/assets/public_lit_docs_!general-info.md.a99bbb3e.js similarity index 99% rename from assets/public_lit_docs_!general-info.md.471f7f7d.js rename to assets/public_lit_docs_!general-info.md.a99bbb3e.js index 110a04061..ff1e0e3b5 100644 --- a/assets/public_lit_docs_!general-info.md.471f7f7d.js +++ b/assets/public_lit_docs_!general-info.md.a99bbb3e.js @@ -1 +1 @@ -import{_ as e,c as a,o as t,a as o}from"./app.a576d425.js";const p=JSON.parse('{"title":"The-Modding-Tree","description":"","frontmatter":{},"headers":[{"level":2,"title":"Table of Contents","slug":"table-of-contents","link":"#table-of-contents","children":[{"level":3,"title":"General","slug":"general","link":"#general","children":[]},{"level":3,"title":"Common components","slug":"common-components","link":"#common-components","children":[]},{"level":3,"title":"Other components and features","slug":"other-components-and-features","link":"#other-components-and-features","children":[]}]}],"relativePath":"public/lit/docs/!general-info.md","lastUpdated":null}'),n={name:"public/lit/docs/!general-info.md"},r=o('

          The-Modding-Tree

          The main way to add content is through creating layers. You can either add a layer directly in the layers object in layerSupport.js, or declare it in another file and register it by calling addLayer(layername, layerdata). There is an example layer registration in layers.js showing the recommended method. It is just an example and can be freely deleted. You can also use it as a reference or a base for your own layers.

          The first thing you need to do is fill out the modInfo object at the top of mod.js to set your mod's name, ID (a string), and other information. A unique modId will prevent your mod's saves from conflicting with other mods. Note that changing this after people have started playing will reset their saves.

          Most of the time, you won't need to dive deep into the code to create things, but you still can if you really want to, for example to add new Vue components in v.js.

          The Modding Tree uses break_eternity.js to store large values. This means that many numbers are Decimal objects, and must be treated differently. For example, you have to use new Decimal(x) to create a Decimal value instead of a plain number, and perform operations on them by calling functions. e.g, instead of x = x + y, use x = x.add(y). Keep in mind this also applies to comparison operators, which should be replaced with calling the .gt, .gte, .lt, .lte, .eq, and .neq functions. See the break_eternity.js docs for more details on working with Decimal values.

          Almost all values can be either a constant value, or a dynamic value. Dynamic values are defined by putting a function that returns what the value should be at any given time.

          All display text can use basic HTML elements (But you can't use most Vue features there).

          While reading this documentation, the following key will be used when describing features:

          • No label: This is required and the game may crash if it isn't included.
          • sometimes required: This is may be required, depending on other things in the layer.
          • optional: You can leave this out if you don't intend to use that feature for the layer.
          • assigned automagically: This value will be set automatically and override any value you set.
          • deprecated: This feature is not recommended to be used anymore, and may be removed in future versions of TMT.

          Table of Contents

          General

          • Getting Started: Getting your own copy of the code set up with Github Desktop.
          • Main mod info: How to set up general things for your mod in mod.js.
          • Basic layer breakdown: Breaking down the components of a layer with minimal features.
          • Layer features: Explanations of all of the different properties that you can give a layer.
          • Custom Tab Layouts: An optional way to give your tabs a different layout. You can even create entirely new components to use.
          • Custom game layouts: You can get rid of the tree tab, add buttons and other things to the tree, or even customize the tab's layout like a layer tab.
          • Updating TMT: Using Github Desktop to update your mod's version of TMT.

          Common components

          • Upgrades: How to create upgrades for a layer.
          • Milestones: How to create milestones for a layer.
          • Buyables: Create rebuyable upgrades for your layer (with the option to make them respec-able). Can be used to make Enhancers or Space Buildings.
          • Clickables: A more generalized variant of buyables, for any kind of thing that is sometimes clickable. Between these and Buyables, you can do just about anything.

          Other components and features

          • Challenges: How to create challenges for a layer.
          • Bars: Display some information as a progress bar, gauge, or similar. They are highly customizable, and can be horizontal and vertical as well.
          • Subtabs and Microtabs: Create subtabs for your tabs, as well as "microtab" components that you can put inside the tabs. You can even use them to embed a layer inside another layer!
          • Achievements: How to create achievements for a layer (or for the whole game).
          • Infoboxes: Boxes containing text that can be shown or hidden.
          • Trees: Make your own trees. You can make non-layer button nodes too!
          ',16),i=[r];function s(l,d,h,c,u,m){return t(),a("div",null,i)}const y=e(n,[["render",s]]);export{p as __pageData,y as default}; +import{_ as e,c as a,o as t,a as o}from"./app.9bfeb8de.js";const p=JSON.parse('{"title":"The-Modding-Tree","description":"","frontmatter":{},"headers":[{"level":2,"title":"Table of Contents","slug":"table-of-contents","link":"#table-of-contents","children":[{"level":3,"title":"General","slug":"general","link":"#general","children":[]},{"level":3,"title":"Common components","slug":"common-components","link":"#common-components","children":[]},{"level":3,"title":"Other components and features","slug":"other-components-and-features","link":"#other-components-and-features","children":[]}]}],"relativePath":"public/lit/docs/!general-info.md","lastUpdated":null}'),n={name:"public/lit/docs/!general-info.md"},r=o('

          The-Modding-Tree

          The main way to add content is through creating layers. You can either add a layer directly in the layers object in layerSupport.js, or declare it in another file and register it by calling addLayer(layername, layerdata). There is an example layer registration in layers.js showing the recommended method. It is just an example and can be freely deleted. You can also use it as a reference or a base for your own layers.

          The first thing you need to do is fill out the modInfo object at the top of mod.js to set your mod's name, ID (a string), and other information. A unique modId will prevent your mod's saves from conflicting with other mods. Note that changing this after people have started playing will reset their saves.

          Most of the time, you won't need to dive deep into the code to create things, but you still can if you really want to, for example to add new Vue components in v.js.

          The Modding Tree uses break_eternity.js to store large values. This means that many numbers are Decimal objects, and must be treated differently. For example, you have to use new Decimal(x) to create a Decimal value instead of a plain number, and perform operations on them by calling functions. e.g, instead of x = x + y, use x = x.add(y). Keep in mind this also applies to comparison operators, which should be replaced with calling the .gt, .gte, .lt, .lte, .eq, and .neq functions. See the break_eternity.js docs for more details on working with Decimal values.

          Almost all values can be either a constant value, or a dynamic value. Dynamic values are defined by putting a function that returns what the value should be at any given time.

          All display text can use basic HTML elements (But you can't use most Vue features there).

          While reading this documentation, the following key will be used when describing features:

          • No label: This is required and the game may crash if it isn't included.
          • sometimes required: This is may be required, depending on other things in the layer.
          • optional: You can leave this out if you don't intend to use that feature for the layer.
          • assigned automagically: This value will be set automatically and override any value you set.
          • deprecated: This feature is not recommended to be used anymore, and may be removed in future versions of TMT.

          Table of Contents

          General

          • Getting Started: Getting your own copy of the code set up with Github Desktop.
          • Main mod info: How to set up general things for your mod in mod.js.
          • Basic layer breakdown: Breaking down the components of a layer with minimal features.
          • Layer features: Explanations of all of the different properties that you can give a layer.
          • Custom Tab Layouts: An optional way to give your tabs a different layout. You can even create entirely new components to use.
          • Custom game layouts: You can get rid of the tree tab, add buttons and other things to the tree, or even customize the tab's layout like a layer tab.
          • Updating TMT: Using Github Desktop to update your mod's version of TMT.

          Common components

          • Upgrades: How to create upgrades for a layer.
          • Milestones: How to create milestones for a layer.
          • Buyables: Create rebuyable upgrades for your layer (with the option to make them respec-able). Can be used to make Enhancers or Space Buildings.
          • Clickables: A more generalized variant of buyables, for any kind of thing that is sometimes clickable. Between these and Buyables, you can do just about anything.

          Other components and features

          • Challenges: How to create challenges for a layer.
          • Bars: Display some information as a progress bar, gauge, or similar. They are highly customizable, and can be horizontal and vertical as well.
          • Subtabs and Microtabs: Create subtabs for your tabs, as well as "microtab" components that you can put inside the tabs. You can even use them to embed a layer inside another layer!
          • Achievements: How to create achievements for a layer (or for the whole game).
          • Infoboxes: Boxes containing text that can be shown or hidden.
          • Trees: Make your own trees. You can make non-layer button nodes too!
          ',16),i=[r];function s(l,d,h,c,u,m){return t(),a("div",null,i)}const y=e(n,[["render",s]]);export{p as __pageData,y as default}; diff --git a/assets/public_lit_docs_!general-info.md.471f7f7d.lean.js b/assets/public_lit_docs_!general-info.md.a99bbb3e.lean.js similarity index 92% rename from assets/public_lit_docs_!general-info.md.471f7f7d.lean.js rename to assets/public_lit_docs_!general-info.md.a99bbb3e.lean.js index f966ee839..0be1a5589 100644 --- a/assets/public_lit_docs_!general-info.md.471f7f7d.lean.js +++ b/assets/public_lit_docs_!general-info.md.a99bbb3e.lean.js @@ -1 +1 @@ -import{_ as e,c as a,o as t,a as o}from"./app.a576d425.js";const p=JSON.parse('{"title":"The-Modding-Tree","description":"","frontmatter":{},"headers":[{"level":2,"title":"Table of Contents","slug":"table-of-contents","link":"#table-of-contents","children":[{"level":3,"title":"General","slug":"general","link":"#general","children":[]},{"level":3,"title":"Common components","slug":"common-components","link":"#common-components","children":[]},{"level":3,"title":"Other components and features","slug":"other-components-and-features","link":"#other-components-and-features","children":[]}]}],"relativePath":"public/lit/docs/!general-info.md","lastUpdated":null}'),n={name:"public/lit/docs/!general-info.md"},r=o("",16),i=[r];function s(l,d,h,c,u,m){return t(),a("div",null,i)}const y=e(n,[["render",s]]);export{p as __pageData,y as default}; +import{_ as e,c as a,o as t,a as o}from"./app.9bfeb8de.js";const p=JSON.parse('{"title":"The-Modding-Tree","description":"","frontmatter":{},"headers":[{"level":2,"title":"Table of Contents","slug":"table-of-contents","link":"#table-of-contents","children":[{"level":3,"title":"General","slug":"general","link":"#general","children":[]},{"level":3,"title":"Common components","slug":"common-components","link":"#common-components","children":[]},{"level":3,"title":"Other components and features","slug":"other-components-and-features","link":"#other-components-and-features","children":[]}]}],"relativePath":"public/lit/docs/!general-info.md","lastUpdated":null}'),n={name:"public/lit/docs/!general-info.md"},r=o("",16),i=[r];function s(l,d,h,c,u,m){return t(),a("div",null,i)}const y=e(n,[["render",s]]);export{p as __pageData,y as default}; diff --git a/assets/public_lit_docs_achievements.md.ca9b928e.js b/assets/public_lit_docs_achievements.md.17232b52.js similarity index 98% rename from assets/public_lit_docs_achievements.md.ca9b928e.js rename to assets/public_lit_docs_achievements.md.17232b52.js index e759099b0..6a3151b6d 100644 --- a/assets/public_lit_docs_achievements.md.ca9b928e.js +++ b/assets/public_lit_docs_achievements.md.17232b52.js @@ -1,4 +1,4 @@ -import{_ as e,c as t,o as a,a as s}from"./app.a576d425.js";const y=JSON.parse('{"title":"Achievements","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/achievements.md","lastUpdated":null}'),n={name:"public/lit/docs/achievements.md"},o=s(`

          Achievements

          Achievements are awarded to the player when they meet a certain goal, and optionally give some benefit. Currently they are pretty basic, but additional features will be added later to help.

          You can make global achievements by putting them in a side layer by making its row equal to "side" instead of a number.

          Useful functions for dealing with achievements and implementing their effects:

          • hasAchievement(layer, id): determine if the player has the Achievement.
          • achievementEffect(layer, id): Returns the current effects of the achievement, if any.

          Achievements should be formatted like this:

          js
          achievements: {
          +import{_ as e,c as t,o as a,a as s}from"./app.9bfeb8de.js";const y=JSON.parse('{"title":"Achievements","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/achievements.md","lastUpdated":null}'),n={name:"public/lit/docs/achievements.md"},o=s(`

          Achievements

          Achievements are awarded to the player when they meet a certain goal, and optionally give some benefit. Currently they are pretty basic, but additional features will be added later to help.

          You can make global achievements by putting them in a side layer by making its row equal to "side" instead of a number.

          Useful functions for dealing with achievements and implementing their effects:

          • hasAchievement(layer, id): determine if the player has the Achievement.
          • achievementEffect(layer, id): Returns the current effects of the achievement, if any.

          Achievements should be formatted like this:

          js
          achievements: {
               rows: # of rows,
               cols: # of columns,
               11: {
          diff --git a/assets/public_lit_docs_achievements.md.ca9b928e.lean.js b/assets/public_lit_docs_achievements.md.17232b52.lean.js
          similarity index 83%
          rename from assets/public_lit_docs_achievements.md.ca9b928e.lean.js
          rename to assets/public_lit_docs_achievements.md.17232b52.lean.js
          index 2c0e50642..2c1041841 100644
          --- a/assets/public_lit_docs_achievements.md.ca9b928e.lean.js
          +++ b/assets/public_lit_docs_achievements.md.17232b52.lean.js
          @@ -1 +1 @@
          -import{_ as e,c as t,o as a,a as s}from"./app.a576d425.js";const y=JSON.parse('{"title":"Achievements","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/achievements.md","lastUpdated":null}'),n={name:"public/lit/docs/achievements.md"},o=s("",11),l=[o];function i(p,r,c,h,d,u){return a(),t("div",null,l)}const v=e(n,[["render",i]]);export{y as __pageData,v as default};
          +import{_ as e,c as t,o as a,a as s}from"./app.9bfeb8de.js";const y=JSON.parse('{"title":"Achievements","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/achievements.md","lastUpdated":null}'),n={name:"public/lit/docs/achievements.md"},o=s("",11),l=[o];function i(p,r,c,h,d,u){return a(),t("div",null,l)}const v=e(n,[["render",i]]);export{y as __pageData,v as default};
          diff --git a/assets/public_lit_docs_bars.md.f547241c.js b/assets/public_lit_docs_bars.md.9bf52d6a.js
          similarity index 98%
          rename from assets/public_lit_docs_bars.md.f547241c.js
          rename to assets/public_lit_docs_bars.md.9bf52d6a.js
          index 8d3430cfb..e21388f58 100644
          --- a/assets/public_lit_docs_bars.md.f547241c.js
          +++ b/assets/public_lit_docs_bars.md.9bf52d6a.js
          @@ -1,4 +1,4 @@
          -import{_ as s,c as a,o as n,a as e}from"./app.a576d425.js";const u=JSON.parse('{"title":"Bars","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/bars.md","lastUpdated":null}'),t={name:"public/lit/docs/bars.md"},o=e(`

          Bars

          Bars let you display information in a more direct way. It can be a progress bar, health bar, capacity gauge, or anything else.

          Bars are defined like other Big Features:

          js
          bars: {
          +import{_ as s,c as a,o as n,a as e}from"./app.9bfeb8de.js";const u=JSON.parse('{"title":"Bars","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/bars.md","lastUpdated":null}'),t={name:"public/lit/docs/bars.md"},o=e(`

          Bars

          Bars let you display information in a more direct way. It can be a progress bar, health bar, capacity gauge, or anything else.

          Bars are defined like other Big Features:

          js
          bars: {
               bigBar: {
                   direction: RIGHT,
                   width: 200,
          diff --git a/assets/public_lit_docs_bars.md.f547241c.lean.js b/assets/public_lit_docs_bars.md.9bf52d6a.lean.js
          similarity index 82%
          rename from assets/public_lit_docs_bars.md.f547241c.lean.js
          rename to assets/public_lit_docs_bars.md.9bf52d6a.lean.js
          index 5717b2498..4139b7627 100644
          --- a/assets/public_lit_docs_bars.md.f547241c.lean.js
          +++ b/assets/public_lit_docs_bars.md.9bf52d6a.lean.js
          @@ -1 +1 @@
          -import{_ as s,c as a,o as n,a as e}from"./app.a576d425.js";const u=JSON.parse('{"title":"Bars","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/bars.md","lastUpdated":null}'),t={name:"public/lit/docs/bars.md"},o=e("",6),l=[o];function p(r,i,c,y,d,F){return n(),a("div",null,l)}const b=s(t,[["render",p]]);export{u as __pageData,b as default};
          +import{_ as s,c as a,o as n,a as e}from"./app.9bfeb8de.js";const u=JSON.parse('{"title":"Bars","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/bars.md","lastUpdated":null}'),t={name:"public/lit/docs/bars.md"},o=e("",6),l=[o];function p(r,i,c,y,d,F){return n(),a("div",null,l)}const b=s(t,[["render",p]]);export{u as __pageData,b as default};
          diff --git a/assets/public_lit_docs_basic-layer-breakdown.md.3f238e7f.js b/assets/public_lit_docs_basic-layer-breakdown.md.de8695ed.js
          similarity index 99%
          rename from assets/public_lit_docs_basic-layer-breakdown.md.3f238e7f.js
          rename to assets/public_lit_docs_basic-layer-breakdown.md.de8695ed.js
          index 70415d4c2..374761927 100644
          --- a/assets/public_lit_docs_basic-layer-breakdown.md.3f238e7f.js
          +++ b/assets/public_lit_docs_basic-layer-breakdown.md.de8695ed.js
          @@ -1,4 +1,4 @@
          -import{_ as s,c as n,o as a,a as l}from"./app.a576d425.js";const A=JSON.parse('{"title":"Basic layer breakdown","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/basic-layer-breakdown.md","lastUpdated":null}'),o={name:"public/lit/docs/basic-layer-breakdown.md"},p=l(`

          Basic layer breakdown

          This is a very minimal layer with minimal features. Most things will require additional features.

          js
          addLayer("p", {
          +import{_ as s,c as n,o as a,a as l}from"./app.9bfeb8de.js";const A=JSON.parse('{"title":"Basic layer breakdown","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/basic-layer-breakdown.md","lastUpdated":null}'),o={name:"public/lit/docs/basic-layer-breakdown.md"},p=l(`

          Basic layer breakdown

          This is a very minimal layer with minimal features. Most things will require additional features.

          js
          addLayer("p", {
               startData() { return {                  // startData is a function that returns default data for a layer. 
                   unlocked: true,                     // You can add more variables here to add them to your layer.
                   points: new Decimal(0),             // "points" is the internal name for the main resource of the layer.
          diff --git a/assets/public_lit_docs_basic-layer-breakdown.md.3f238e7f.lean.js b/assets/public_lit_docs_basic-layer-breakdown.md.de8695ed.lean.js
          similarity index 84%
          rename from assets/public_lit_docs_basic-layer-breakdown.md.3f238e7f.lean.js
          rename to assets/public_lit_docs_basic-layer-breakdown.md.de8695ed.lean.js
          index ee2f24782..0d194598d 100644
          --- a/assets/public_lit_docs_basic-layer-breakdown.md.3f238e7f.lean.js
          +++ b/assets/public_lit_docs_basic-layer-breakdown.md.de8695ed.lean.js
          @@ -1 +1 @@
          -import{_ as s,c as n,o as a,a as l}from"./app.a576d425.js";const A=JSON.parse('{"title":"Basic layer breakdown","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/basic-layer-breakdown.md","lastUpdated":null}'),o={name:"public/lit/docs/basic-layer-breakdown.md"},p=l("",3),e=[p];function t(r,c,y,F,D,i){return a(),n("div",null,e)}const u=s(o,[["render",t]]);export{A as __pageData,u as default};
          +import{_ as s,c as n,o as a,a as l}from"./app.9bfeb8de.js";const A=JSON.parse('{"title":"Basic layer breakdown","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/basic-layer-breakdown.md","lastUpdated":null}'),o={name:"public/lit/docs/basic-layer-breakdown.md"},p=l("",3),e=[p];function t(r,c,y,F,D,i){return a(),n("div",null,e)}const u=s(o,[["render",t]]);export{A as __pageData,u as default};
          diff --git a/assets/public_lit_docs_buyables.md.0b2481b9.js b/assets/public_lit_docs_buyables.md.8a9beb14.js
          similarity index 99%
          rename from assets/public_lit_docs_buyables.md.0b2481b9.js
          rename to assets/public_lit_docs_buyables.md.8a9beb14.js
          index b6fd64cbd..29074a51f 100644
          --- a/assets/public_lit_docs_buyables.md.0b2481b9.js
          +++ b/assets/public_lit_docs_buyables.md.8a9beb14.js
          @@ -1,4 +1,4 @@
          -import{_ as s,c as a,o as n,a as l}from"./app.a576d425.js";const h=JSON.parse('{"title":"Buyables","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/buyables.md","lastUpdated":null}'),o={name:"public/lit/docs/buyables.md"},e=l(`

          Buyables

          Buyables are usually things that can be bought multiple times with scaling costs. If you set a respec function, the player can reset the purchases to get their currency back.

          The amount of a buyable owned is a Decimal.

          Useful functions for dealing with buyables and implementing their effects:

          • getBuyableAmount(layer, id): get the amount of the buyable the player has
          • setBuyableAmount(layer, id, amount): set the amount of the buyable the player has
          • buyableEffect(layer, id): Returns the current effects of the buyable, if any.

          Buyables should be formatted like this:

          js
          buyables: {
          +import{_ as s,c as a,o as n,a as l}from"./app.9bfeb8de.js";const h=JSON.parse('{"title":"Buyables","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/buyables.md","lastUpdated":null}'),o={name:"public/lit/docs/buyables.md"},e=l(`

          Buyables

          Buyables are usually things that can be bought multiple times with scaling costs. If you set a respec function, the player can reset the purchases to get their currency back.

          The amount of a buyable owned is a Decimal.

          Useful functions for dealing with buyables and implementing their effects:

          • getBuyableAmount(layer, id): get the amount of the buyable the player has
          • setBuyableAmount(layer, id, amount): set the amount of the buyable the player has
          • buyableEffect(layer, id): Returns the current effects of the buyable, if any.

          Buyables should be formatted like this:

          js
          buyables: {
               rows: # of rows,
               cols: # of columns,
               11: {
          diff --git a/assets/public_lit_docs_buyables.md.0b2481b9.lean.js b/assets/public_lit_docs_buyables.md.8a9beb14.lean.js
          similarity index 83%
          rename from assets/public_lit_docs_buyables.md.0b2481b9.lean.js
          rename to assets/public_lit_docs_buyables.md.8a9beb14.lean.js
          index 1c71042cf..f5bb5610b 100644
          --- a/assets/public_lit_docs_buyables.md.0b2481b9.lean.js
          +++ b/assets/public_lit_docs_buyables.md.8a9beb14.lean.js
          @@ -1 +1 @@
          -import{_ as s,c as a,o as n,a as l}from"./app.a576d425.js";const h=JSON.parse('{"title":"Buyables","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/buyables.md","lastUpdated":null}'),o={name:"public/lit/docs/buyables.md"},e=l("",12),t=[e];function p(r,c,y,i,F,u){return n(),a("div",null,t)}const b=s(o,[["render",p]]);export{h as __pageData,b as default};
          +import{_ as s,c as a,o as n,a as l}from"./app.9bfeb8de.js";const h=JSON.parse('{"title":"Buyables","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/buyables.md","lastUpdated":null}'),o={name:"public/lit/docs/buyables.md"},e=l("",12),t=[e];function p(r,c,y,i,F,u){return n(),a("div",null,t)}const b=s(o,[["render",p]]);export{h as __pageData,b as default};
          diff --git a/assets/public_lit_docs_challenges.md.858da2b8.js b/assets/public_lit_docs_challenges.md.841c1bd9.js
          similarity index 99%
          rename from assets/public_lit_docs_challenges.md.858da2b8.js
          rename to assets/public_lit_docs_challenges.md.841c1bd9.js
          index 558769823..0e06d7d81 100644
          --- a/assets/public_lit_docs_challenges.md.858da2b8.js
          +++ b/assets/public_lit_docs_challenges.md.841c1bd9.js
          @@ -1,4 +1,4 @@
          -import{_ as e,c as s,o as n,a}from"./app.a576d425.js";const d=JSON.parse('{"title":"Challenges","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/challenges.md","lastUpdated":null}'),l={name:"public/lit/docs/challenges.md"},t=a(`

          Challenges

          Challenges can have fully customizable win conditions. Useful functions for dealing with Challenges and implementing their effects:

          • inChallenge(layer, id): determine if the player is in a given challenge (or another challenge on the same layer that counts as this one).
          • hasChallenge(layer, id): determine if the player has completed the challenge.
          • challengeCompletions(layer, id): determine how many times the player completed the challenge.
          • challengeEffect(layer, id): Returns the current effects of the challenge, if any.

          Challenges are stored in the following format:

          js
          challenges: {
          +import{_ as e,c as s,o as n,a}from"./app.9bfeb8de.js";const d=JSON.parse('{"title":"Challenges","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/challenges.md","lastUpdated":null}'),l={name:"public/lit/docs/challenges.md"},t=a(`

          Challenges

          Challenges can have fully customizable win conditions. Useful functions for dealing with Challenges and implementing their effects:

          • inChallenge(layer, id): determine if the player is in a given challenge (or another challenge on the same layer that counts as this one).
          • hasChallenge(layer, id): determine if the player has completed the challenge.
          • challengeCompletions(layer, id): determine how many times the player completed the challenge.
          • challengeEffect(layer, id): Returns the current effects of the challenge, if any.

          Challenges are stored in the following format:

          js
          challenges: {
               rows: # of rows,
               cols: # of columns,
               11: {
          diff --git a/assets/public_lit_docs_challenges.md.858da2b8.lean.js b/assets/public_lit_docs_challenges.md.841c1bd9.lean.js
          similarity index 83%
          rename from assets/public_lit_docs_challenges.md.858da2b8.lean.js
          rename to assets/public_lit_docs_challenges.md.841c1bd9.lean.js
          index 0b2955f23..387498bf0 100644
          --- a/assets/public_lit_docs_challenges.md.858da2b8.lean.js
          +++ b/assets/public_lit_docs_challenges.md.841c1bd9.lean.js
          @@ -1 +1 @@
          -import{_ as e,c as s,o as n,a}from"./app.a576d425.js";const d=JSON.parse('{"title":"Challenges","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/challenges.md","lastUpdated":null}'),l={name:"public/lit/docs/challenges.md"},t=a("",10),o=[t];function i(r,p,c,h,u,y){return n(),s("div",null,o)}const f=e(l,[["render",i]]);export{d as __pageData,f as default};
          +import{_ as e,c as s,o as n,a}from"./app.9bfeb8de.js";const d=JSON.parse('{"title":"Challenges","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/challenges.md","lastUpdated":null}'),l={name:"public/lit/docs/challenges.md"},t=a("",10),o=[t];function i(r,p,c,h,u,y){return n(),s("div",null,o)}const f=e(l,[["render",i]]);export{d as __pageData,f as default};
          diff --git a/assets/public_lit_docs_clickables.md.3187e173.js b/assets/public_lit_docs_clickables.md.bff73686.js
          similarity index 98%
          rename from assets/public_lit_docs_clickables.md.3187e173.js
          rename to assets/public_lit_docs_clickables.md.bff73686.js
          index 3bd44ff28..dfb7abc2a 100644
          --- a/assets/public_lit_docs_clickables.md.3187e173.js
          +++ b/assets/public_lit_docs_clickables.md.bff73686.js
          @@ -1,4 +1,4 @@
          -import{_ as e,c as s,o as a,a as t}from"./app.a576d425.js";const b=JSON.parse('{"title":"Clickables","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/clickables.md","lastUpdated":null}'),l={name:"public/lit/docs/clickables.md"},n=t(`

          Clickables

          Clickables are any kind of thing that you can click for an effect. They're a more generalized version of Buyables.

          DO NOT USE THESE TO MAKE THINGS THAT YOU CLICK REPEATEDLY FOR A BONUS BECAUSE THOSE ARE AWFUL.

          There are several differences between the two. One is that a buyable's saved data is its amount as a Decimal, while Clickables store a "state" which can be a number or string, but not Decimal, array, or object). Buyables have a number of extra features which you can see on their page. Clickables also have a smaller default size.

          Useful functions for dealing with achievements and implementing their effects:

          • getClickableState(layer, id): get the state of the clickable the player has
          • setClickableState(layer, id, state): set the state of the buyable the player has
          • clickableEffect(layer, id): Returns the current effects of the clickable, if any.

          Clickables should be formatted like this:

          js
          clickables: {
          +import{_ as e,c as s,o as a,a as t}from"./app.9bfeb8de.js";const b=JSON.parse('{"title":"Clickables","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/clickables.md","lastUpdated":null}'),l={name:"public/lit/docs/clickables.md"},n=t(`

          Clickables

          Clickables are any kind of thing that you can click for an effect. They're a more generalized version of Buyables.

          DO NOT USE THESE TO MAKE THINGS THAT YOU CLICK REPEATEDLY FOR A BONUS BECAUSE THOSE ARE AWFUL.

          There are several differences between the two. One is that a buyable's saved data is its amount as a Decimal, while Clickables store a "state" which can be a number or string, but not Decimal, array, or object). Buyables have a number of extra features which you can see on their page. Clickables also have a smaller default size.

          Useful functions for dealing with achievements and implementing their effects:

          • getClickableState(layer, id): get the state of the clickable the player has
          • setClickableState(layer, id, state): set the state of the buyable the player has
          • clickableEffect(layer, id): Returns the current effects of the clickable, if any.

          Clickables should be formatted like this:

          js
          clickables: {
               rows: # of rows,
               cols: # of columns,
               11: {
          diff --git a/assets/public_lit_docs_clickables.md.3187e173.lean.js b/assets/public_lit_docs_clickables.md.bff73686.lean.js
          similarity index 83%
          rename from assets/public_lit_docs_clickables.md.3187e173.lean.js
          rename to assets/public_lit_docs_clickables.md.bff73686.lean.js
          index 0e5e91e49..88be8aacd 100644
          --- a/assets/public_lit_docs_clickables.md.3187e173.lean.js
          +++ b/assets/public_lit_docs_clickables.md.bff73686.lean.js
          @@ -1 +1 @@
          -import{_ as e,c as s,o as a,a as t}from"./app.a576d425.js";const b=JSON.parse('{"title":"Clickables","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/clickables.md","lastUpdated":null}'),l={name:"public/lit/docs/clickables.md"},n=t("",12),o=[n];function i(c,p,r,u,h,y){return a(),s("div",null,o)}const f=e(l,[["render",i]]);export{b as __pageData,f as default};
          +import{_ as e,c as s,o as a,a as t}from"./app.9bfeb8de.js";const b=JSON.parse('{"title":"Clickables","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/clickables.md","lastUpdated":null}'),l={name:"public/lit/docs/clickables.md"},n=t("",12),o=[n];function i(c,p,r,u,h,y){return a(),s("div",null,o)}const f=e(l,[["render",i]]);export{b as __pageData,f as default};
          diff --git a/assets/public_lit_docs_custom-tab-layouts.md.387df476.js b/assets/public_lit_docs_custom-tab-layouts.md.31deefcc.js
          similarity index 99%
          rename from assets/public_lit_docs_custom-tab-layouts.md.387df476.js
          rename to assets/public_lit_docs_custom-tab-layouts.md.31deefcc.js
          index 991bb2723..1ce5a8e1e 100644
          --- a/assets/public_lit_docs_custom-tab-layouts.md.387df476.js
          +++ b/assets/public_lit_docs_custom-tab-layouts.md.31deefcc.js
          @@ -1,4 +1,4 @@
          -import{_ as s,c as a,o,a as n}from"./app.a576d425.js";const h=JSON.parse('{"title":"Custom tab layouts","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/custom-tab-layouts.md","lastUpdated":null}'),t={name:"public/lit/docs/custom-tab-layouts.md"},e=n(`

          Custom tab layouts

          Note: If you are using subtabs, tabFormat is used differently, but you still use the same format within each subtabs. See here for more on subtabs.

          Custom tab layouts can be used to do basically anything in a tab window, especially combined with the "style" layer feature. The tabFormat feature is an array of things, like this:

          js
          tabFormat: [
          +import{_ as s,c as a,o,a as n}from"./app.9bfeb8de.js";const h=JSON.parse('{"title":"Custom tab layouts","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/custom-tab-layouts.md","lastUpdated":null}'),t={name:"public/lit/docs/custom-tab-layouts.md"},e=n(`

          Custom tab layouts

          Note: If you are using subtabs, tabFormat is used differently, but you still use the same format within each subtabs. See here for more on subtabs.

          Custom tab layouts can be used to do basically anything in a tab window, especially combined with the "style" layer feature. The tabFormat feature is an array of things, like this:

          js
          tabFormat: [
               "main-display",
               ["prestige-button", function() { return "Melt your points into " }],
               "blank",
          diff --git a/assets/public_lit_docs_custom-tab-layouts.md.387df476.lean.js b/assets/public_lit_docs_custom-tab-layouts.md.31deefcc.lean.js
          similarity index 84%
          rename from assets/public_lit_docs_custom-tab-layouts.md.387df476.lean.js
          rename to assets/public_lit_docs_custom-tab-layouts.md.31deefcc.lean.js
          index 9f4cf4805..b76a705a2 100644
          --- a/assets/public_lit_docs_custom-tab-layouts.md.387df476.lean.js
          +++ b/assets/public_lit_docs_custom-tab-layouts.md.31deefcc.lean.js
          @@ -1 +1 @@
          -import{_ as s,c as a,o,a as n}from"./app.a576d425.js";const h=JSON.parse('{"title":"Custom tab layouts","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/custom-tab-layouts.md","lastUpdated":null}'),t={name:"public/lit/docs/custom-tab-layouts.md"},e=n("",9),l=[e];function p(r,c,i,y,D,u){return o(),a("div",null,l)}const d=s(t,[["render",p]]);export{h as __pageData,d as default};
          +import{_ as s,c as a,o,a as n}from"./app.9bfeb8de.js";const h=JSON.parse('{"title":"Custom tab layouts","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/custom-tab-layouts.md","lastUpdated":null}'),t={name:"public/lit/docs/custom-tab-layouts.md"},e=n("",9),l=[e];function p(r,c,i,y,D,u){return o(),a("div",null,l)}const d=s(t,[["render",p]]);export{h as __pageData,d as default};
          diff --git a/assets/public_lit_docs_getting-started.md.7dc6e45d.js b/assets/public_lit_docs_getting-started.md.38cf00c8.js
          similarity index 98%
          rename from assets/public_lit_docs_getting-started.md.7dc6e45d.js
          rename to assets/public_lit_docs_getting-started.md.38cf00c8.js
          index 38c062b98..b2cc84127 100644
          --- a/assets/public_lit_docs_getting-started.md.7dc6e45d.js
          +++ b/assets/public_lit_docs_getting-started.md.38cf00c8.js
          @@ -1 +1 @@
          -import{_ as e,c as t,o,a as i}from"./app.a576d425.js";const y=JSON.parse('{"title":"Getting started","description":"","frontmatter":{},"headers":[{"level":2,"title":"Getting set up with Github Desktop, Visual Studio Code, and The Modding Tree:","slug":"getting-set-up-with-github-desktop-visual-studio-code-and-the-modding-tree","link":"#getting-set-up-with-github-desktop-visual-studio-code-and-the-modding-tree","children":[{"level":3,"title":"Using your repository","slug":"using-your-repository","link":"#using-your-repository","children":[]}]}],"relativePath":"public/lit/docs/getting-started.md","lastUpdated":null}'),a={name:"public/lit/docs/getting-started.md"},n=i('

          Getting started

          Welcome to The Modding Tree!

          Using the Modding Tree, at its simplest level, just requires getting a copy of it onto your computer. However, if you do it the right way, it will help in many ways.

          Don't let the word "Github" scare you away. It's actually much easier to use than most people think, especially because most people use it the hard way. The key is Github Desktop, which lets you do everything you need to, without even touching the command line.

          The benefits of using Github:

          • It makes it much, much easier to update The Modding Tree.
          • You can share your work without any extra effort using githack, or with a bit more effort, set up a github.io site.
          • It lets you undo changes to your code, and to have multiple versions of it.
          • It lets you collaborate with other people, if you want to.

          Getting set up with Github Desktop, Visual Studio Code, and The Modding Tree:

          1. Install Github Desktop and Visual Studio Code.

          2. Make a Github account. You can handle this on your own.

          3. Log in on your browser, and go back to The Modding Tree page. At the top right, there should be a button that says "fork". Click on it, and then on your username. You now have your own fork, or copy, of The Modding Tree.

          4. Open Github Desktop and log in. Ignore everything else and choose "clone a repository". A "repository" is basically a "Github project", like The Modding Tree. "Cloning" is downloading a copy of the repository to your computer.

          5. Look for The Modding Tree in the list of repositiories (it should be the only one) and click "clone".

          6. Select that you're using it for your own purposes, and click continue. It will download the files and handle everything.

          Using your repository

          1. Click on "show in explorer/finder" to the right, and then open the index.html file in the folder. The page should open up on your browser. This will let you view and test your project locally!

          2. To edit your project, click "open in VSCode" in Github Desktop.

          3. Open mod.js in VSCode, and look at the top part where it has a "modInfo" object. Fill in your mod's name to whatever you want, and change the id as well. (It can be any string value, and it's used to determine where the savefile is. Make it something that's probably unique, and don't change it again later or else it'll effectively wipe existing saves)

          4. Save mod.js, and then reload index.html in your browser. The title on the tab, as well as on the info page, will now be updated! You can reload the page every time you change the code to test it quickly and easily.

          5. Go back to Github Desktop. It's time to save your changes into the git system by making a "commit". This basically saves your work and creates a snapshot of what your code looks like at this moment, allowing you to look back at it later.

          6. At the bottom right corner, add a summary of your changes, and then click "commit to master".

          7. Finally, at the top middle, click "push origin" to push your changes out onto the online repository.

          8. You can view your project on line, or share it with others, by going to https://raw.githack.com/[YOUR-GITHUB-USERNAME]/The-Modding-Tree/master/index.html

          And now, you have successfully used Github! You can look at the documentation to see how The Modding Tree's system works and to make your mod a reality.

          ',11),r=[n];function s(l,h,u,d,p,c){return o(),t("div",null,r)}const m=e(a,[["render",s]]);export{y as __pageData,m as default}; +import{_ as e,c as t,o,a as i}from"./app.9bfeb8de.js";const y=JSON.parse('{"title":"Getting started","description":"","frontmatter":{},"headers":[{"level":2,"title":"Getting set up with Github Desktop, Visual Studio Code, and The Modding Tree:","slug":"getting-set-up-with-github-desktop-visual-studio-code-and-the-modding-tree","link":"#getting-set-up-with-github-desktop-visual-studio-code-and-the-modding-tree","children":[{"level":3,"title":"Using your repository","slug":"using-your-repository","link":"#using-your-repository","children":[]}]}],"relativePath":"public/lit/docs/getting-started.md","lastUpdated":null}'),a={name:"public/lit/docs/getting-started.md"},n=i('

          Getting started

          Welcome to The Modding Tree!

          Using the Modding Tree, at its simplest level, just requires getting a copy of it onto your computer. However, if you do it the right way, it will help in many ways.

          Don't let the word "Github" scare you away. It's actually much easier to use than most people think, especially because most people use it the hard way. The key is Github Desktop, which lets you do everything you need to, without even touching the command line.

          The benefits of using Github:

          • It makes it much, much easier to update The Modding Tree.
          • You can share your work without any extra effort using githack, or with a bit more effort, set up a github.io site.
          • It lets you undo changes to your code, and to have multiple versions of it.
          • It lets you collaborate with other people, if you want to.

          Getting set up with Github Desktop, Visual Studio Code, and The Modding Tree:

          1. Install Github Desktop and Visual Studio Code.

          2. Make a Github account. You can handle this on your own.

          3. Log in on your browser, and go back to The Modding Tree page. At the top right, there should be a button that says "fork". Click on it, and then on your username. You now have your own fork, or copy, of The Modding Tree.

          4. Open Github Desktop and log in. Ignore everything else and choose "clone a repository". A "repository" is basically a "Github project", like The Modding Tree. "Cloning" is downloading a copy of the repository to your computer.

          5. Look for The Modding Tree in the list of repositiories (it should be the only one) and click "clone".

          6. Select that you're using it for your own purposes, and click continue. It will download the files and handle everything.

          Using your repository

          1. Click on "show in explorer/finder" to the right, and then open the index.html file in the folder. The page should open up on your browser. This will let you view and test your project locally!

          2. To edit your project, click "open in VSCode" in Github Desktop.

          3. Open mod.js in VSCode, and look at the top part where it has a "modInfo" object. Fill in your mod's name to whatever you want, and change the id as well. (It can be any string value, and it's used to determine where the savefile is. Make it something that's probably unique, and don't change it again later or else it'll effectively wipe existing saves)

          4. Save mod.js, and then reload index.html in your browser. The title on the tab, as well as on the info page, will now be updated! You can reload the page every time you change the code to test it quickly and easily.

          5. Go back to Github Desktop. It's time to save your changes into the git system by making a "commit". This basically saves your work and creates a snapshot of what your code looks like at this moment, allowing you to look back at it later.

          6. At the bottom right corner, add a summary of your changes, and then click "commit to master".

          7. Finally, at the top middle, click "push origin" to push your changes out onto the online repository.

          8. You can view your project on line, or share it with others, by going to https://raw.githack.com/[YOUR-GITHUB-USERNAME]/The-Modding-Tree/master/index.html

          And now, you have successfully used Github! You can look at the documentation to see how The Modding Tree's system works and to make your mod a reality.

          ',11),r=[n];function s(l,h,u,d,p,c){return o(),t("div",null,r)}const m=e(a,[["render",s]]);export{y as __pageData,m as default}; diff --git a/assets/public_lit_docs_getting-started.md.7dc6e45d.lean.js b/assets/public_lit_docs_getting-started.md.38cf00c8.lean.js similarity index 92% rename from assets/public_lit_docs_getting-started.md.7dc6e45d.lean.js rename to assets/public_lit_docs_getting-started.md.38cf00c8.lean.js index 893c1a6d5..9120461a1 100644 --- a/assets/public_lit_docs_getting-started.md.7dc6e45d.lean.js +++ b/assets/public_lit_docs_getting-started.md.38cf00c8.lean.js @@ -1 +1 @@ -import{_ as e,c as t,o,a as i}from"./app.a576d425.js";const y=JSON.parse('{"title":"Getting started","description":"","frontmatter":{},"headers":[{"level":2,"title":"Getting set up with Github Desktop, Visual Studio Code, and The Modding Tree:","slug":"getting-set-up-with-github-desktop-visual-studio-code-and-the-modding-tree","link":"#getting-set-up-with-github-desktop-visual-studio-code-and-the-modding-tree","children":[{"level":3,"title":"Using your repository","slug":"using-your-repository","link":"#using-your-repository","children":[]}]}],"relativePath":"public/lit/docs/getting-started.md","lastUpdated":null}'),a={name:"public/lit/docs/getting-started.md"},n=i("",11),r=[n];function s(l,h,u,d,p,c){return o(),t("div",null,r)}const m=e(a,[["render",s]]);export{y as __pageData,m as default}; +import{_ as e,c as t,o,a as i}from"./app.9bfeb8de.js";const y=JSON.parse('{"title":"Getting started","description":"","frontmatter":{},"headers":[{"level":2,"title":"Getting set up with Github Desktop, Visual Studio Code, and The Modding Tree:","slug":"getting-set-up-with-github-desktop-visual-studio-code-and-the-modding-tree","link":"#getting-set-up-with-github-desktop-visual-studio-code-and-the-modding-tree","children":[{"level":3,"title":"Using your repository","slug":"using-your-repository","link":"#using-your-repository","children":[]}]}],"relativePath":"public/lit/docs/getting-started.md","lastUpdated":null}'),a={name:"public/lit/docs/getting-started.md"},n=i("",11),r=[n];function s(l,h,u,d,p,c){return o(),t("div",null,r)}const m=e(a,[["render",s]]);export{y as __pageData,m as default}; diff --git a/assets/public_lit_docs_infoboxes.md.2fa00fa8.js b/assets/public_lit_docs_infoboxes.md.bf64f36f.js similarity index 98% rename from assets/public_lit_docs_infoboxes.md.2fa00fa8.js rename to assets/public_lit_docs_infoboxes.md.bf64f36f.js index 381e5404a..a382e8b39 100644 --- a/assets/public_lit_docs_infoboxes.md.2fa00fa8.js +++ b/assets/public_lit_docs_infoboxes.md.bf64f36f.js @@ -1,4 +1,4 @@ -import{_ as s,c as o,o as a,a as n}from"./app.a576d425.js";const b=JSON.parse('{"title":"Infoboxes","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/infoboxes.md","lastUpdated":null}'),e={name:"public/lit/docs/infoboxes.md"},t=n(`

          Infoboxes

          Infoboxes are good for displaying "lore", or story elements, as well as for explaining complicated things.

          In the default tab layout, the first infobox will be displayed at the very top of the tab.

          Infoboxes are defined like other Big Features:

          js
          infoboxes: {
          +import{_ as s,c as o,o as a,a as n}from"./app.9bfeb8de.js";const b=JSON.parse('{"title":"Infoboxes","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/infoboxes.md","lastUpdated":null}'),e={name:"public/lit/docs/infoboxes.md"},t=n(`

          Infoboxes

          Infoboxes are good for displaying "lore", or story elements, as well as for explaining complicated things.

          In the default tab layout, the first infobox will be displayed at the very top of the tab.

          Infoboxes are defined like other Big Features:

          js
          infoboxes: {
               lore: {
                   title: "foo",
                   body() { return "bar" },
          diff --git a/assets/public_lit_docs_infoboxes.md.2fa00fa8.lean.js b/assets/public_lit_docs_infoboxes.md.bf64f36f.lean.js
          similarity index 83%
          rename from assets/public_lit_docs_infoboxes.md.2fa00fa8.lean.js
          rename to assets/public_lit_docs_infoboxes.md.bf64f36f.lean.js
          index 7d398fb13..eb281fc39 100644
          --- a/assets/public_lit_docs_infoboxes.md.2fa00fa8.lean.js
          +++ b/assets/public_lit_docs_infoboxes.md.bf64f36f.lean.js
          @@ -1 +1 @@
          -import{_ as s,c as o,o as a,a as n}from"./app.a576d425.js";const b=JSON.parse('{"title":"Infoboxes","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/infoboxes.md","lastUpdated":null}'),e={name:"public/lit/docs/infoboxes.md"},t=n("",7),l=[t];function p(r,i,c,y,d,F){return a(),o("div",null,l)}const h=s(e,[["render",p]]);export{b as __pageData,h as default};
          +import{_ as s,c as o,o as a,a as n}from"./app.9bfeb8de.js";const b=JSON.parse('{"title":"Infoboxes","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/infoboxes.md","lastUpdated":null}'),e={name:"public/lit/docs/infoboxes.md"},t=n("",7),l=[t];function p(r,i,c,y,d,F){return a(),o("div",null,l)}const h=s(e,[["render",p]]);export{b as __pageData,h as default};
          diff --git a/assets/public_lit_docs_layer-features.md.15cfeafa.js b/assets/public_lit_docs_layer-features.md.59361922.js
          similarity index 99%
          rename from assets/public_lit_docs_layer-features.md.15cfeafa.js
          rename to assets/public_lit_docs_layer-features.md.59361922.js
          index 8c6d34eff..6d54e715c 100644
          --- a/assets/public_lit_docs_layer-features.md.15cfeafa.js
          +++ b/assets/public_lit_docs_layer-features.md.59361922.js
          @@ -1,4 +1,4 @@
          -import{_ as e,c as t,o as a,a as s}from"./app.a576d425.js";const f=JSON.parse('{"title":"Layer Features","description":"","frontmatter":{},"headers":[{"level":2,"title":"Layer Definition features","slug":"layer-definition-features","link":"#layer-definition-features","children":[]},{"level":2,"title":"Big features (all optional)","slug":"big-features-all-optional","link":"#big-features-all-optional","children":[]},{"level":2,"title":"Prestige formula features","slug":"prestige-formula-features","link":"#prestige-formula-features","children":[]},{"level":2,"title":"Other prestige-related features","slug":"other-prestige-related-features","link":"#other-prestige-related-features","children":[]},{"level":2,"title":"Tree/node features","slug":"tree-node-features","link":"#tree-node-features","children":[]},{"level":2,"title":"Other features","slug":"other-features","link":"#other-features","children":[]},{"level":2,"title":"Custom Prestige type","slug":"custom-prestige-type","link":"#custom-prestige-type","children":[]}],"relativePath":"public/lit/docs/layer-features.md","lastUpdated":null}'),o={name:"public/lit/docs/layer-features.md"},n=s(`

          Layer Features

          This is a more comprehensive list of established features to add to layers. You can add more freely, if you want to have other functions or values associated with your layer. These have special functionality, though.

          You can make almost any value dynamic by using a function in its place, including all display strings and styling/color features.

          Layer Definition features

          • layer: assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar to access the saved value. It makes copying code to new layers easier. It is also assigned to all upgrades and buyables and such.

          • name: optional. used in reset confirmations (and the default infobox title). If absent, it just uses the layer's id.

          • startData(): A function to return the default save data for this layer. Add any variables you have to it. Make sure to use Decimal values rather than normal numbers.

            Standard values: - Required: - unlocked: a bool determining if this layer is unlocked or not - points: a Decimal, the main currency for the layer - Optional: - total: A Decimal, tracks total amount of main prestige currency. Always tracked, but only shown if you add it here. - best: A Decimal, tracks highest amount of main prestige currency. Always tracked, but only shown if you add it here. - unlockOrder: used to keep track of relevant layers unlocked before this one. - resetTime: A number, time since this layer was last prestiged (or reset by another layer)

          • color: A color associated with this layer, used in many places. (A string in hex format with a #)

          • row: The row of the layer, starting at 0. This affects where the node appears on the standard tree, and which resets affect the layer.

            Using "side" instead of a number will cause the layer to appear off to the side as a smaller node (useful for achievements and statistics). Side layers are not affected by resets unless you add a doReset to them.

          • displayRow: OVERRIDE Changes where the layer node appears without changing where it is in the reset order.

          • resource: Name of the main currency you gain by resetting on this layer.

          • effect(): optional. A function that calculates and returns the current values of any bonuses inherent to the main currency. Can return a value or an object containing multiple values. You will also have to implement the effect where it is applied.

          • effectDescription: optional. A function that returns a description of this effect. If the text stays constant, it can just be a string.

          • layerShown(): optional, A function returning a bool which determines if this layer's node should be visible on the tree. It can also return "ghost", which will hide the layer, but its node will still take up space in the tree. Defaults to true.

          • hotkeys: optional. An array containing information on any hotkeys associated with this layer:

            js
            hotkeys: [
            +import{_ as e,c as t,o as a,a as s}from"./app.9bfeb8de.js";const f=JSON.parse('{"title":"Layer Features","description":"","frontmatter":{},"headers":[{"level":2,"title":"Layer Definition features","slug":"layer-definition-features","link":"#layer-definition-features","children":[]},{"level":2,"title":"Big features (all optional)","slug":"big-features-all-optional","link":"#big-features-all-optional","children":[]},{"level":2,"title":"Prestige formula features","slug":"prestige-formula-features","link":"#prestige-formula-features","children":[]},{"level":2,"title":"Other prestige-related features","slug":"other-prestige-related-features","link":"#other-prestige-related-features","children":[]},{"level":2,"title":"Tree/node features","slug":"tree-node-features","link":"#tree-node-features","children":[]},{"level":2,"title":"Other features","slug":"other-features","link":"#other-features","children":[]},{"level":2,"title":"Custom Prestige type","slug":"custom-prestige-type","link":"#custom-prestige-type","children":[]}],"relativePath":"public/lit/docs/layer-features.md","lastUpdated":null}'),o={name:"public/lit/docs/layer-features.md"},n=s(`

            Layer Features

            This is a more comprehensive list of established features to add to layers. You can add more freely, if you want to have other functions or values associated with your layer. These have special functionality, though.

            You can make almost any value dynamic by using a function in its place, including all display strings and styling/color features.

            Layer Definition features

            • layer: assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar to access the saved value. It makes copying code to new layers easier. It is also assigned to all upgrades and buyables and such.

            • name: optional. used in reset confirmations (and the default infobox title). If absent, it just uses the layer's id.

            • startData(): A function to return the default save data for this layer. Add any variables you have to it. Make sure to use Decimal values rather than normal numbers.

              Standard values: - Required: - unlocked: a bool determining if this layer is unlocked or not - points: a Decimal, the main currency for the layer - Optional: - total: A Decimal, tracks total amount of main prestige currency. Always tracked, but only shown if you add it here. - best: A Decimal, tracks highest amount of main prestige currency. Always tracked, but only shown if you add it here. - unlockOrder: used to keep track of relevant layers unlocked before this one. - resetTime: A number, time since this layer was last prestiged (or reset by another layer)

            • color: A color associated with this layer, used in many places. (A string in hex format with a #)

            • row: The row of the layer, starting at 0. This affects where the node appears on the standard tree, and which resets affect the layer.

              Using "side" instead of a number will cause the layer to appear off to the side as a smaller node (useful for achievements and statistics). Side layers are not affected by resets unless you add a doReset to them.

            • displayRow: OVERRIDE Changes where the layer node appears without changing where it is in the reset order.

            • resource: Name of the main currency you gain by resetting on this layer.

            • effect(): optional. A function that calculates and returns the current values of any bonuses inherent to the main currency. Can return a value or an object containing multiple values. You will also have to implement the effect where it is applied.

            • effectDescription: optional. A function that returns a description of this effect. If the text stays constant, it can just be a string.

            • layerShown(): optional, A function returning a bool which determines if this layer's node should be visible on the tree. It can also return "ghost", which will hide the layer, but its node will still take up space in the tree. Defaults to true.

            • hotkeys: optional. An array containing information on any hotkeys associated with this layer:

              js
              hotkeys: [
                   {
                       key: "p", // What the hotkey button is. Use uppercase if it's combined with shift, or "ctrl+x" for holding down ctrl.
                       description: "p: reset your points for prestige points", // The description of the hotkey that is displayed in the game's How To Play tab
              diff --git a/assets/public_lit_docs_layer-features.md.15cfeafa.lean.js b/assets/public_lit_docs_layer-features.md.59361922.lean.js
              similarity index 95%
              rename from assets/public_lit_docs_layer-features.md.15cfeafa.lean.js
              rename to assets/public_lit_docs_layer-features.md.59361922.lean.js
              index 19cfaad6a..293ffaf37 100644
              --- a/assets/public_lit_docs_layer-features.md.15cfeafa.lean.js
              +++ b/assets/public_lit_docs_layer-features.md.59361922.lean.js
              @@ -1 +1 @@
              -import{_ as e,c as t,o as a,a as s}from"./app.a576d425.js";const f=JSON.parse('{"title":"Layer Features","description":"","frontmatter":{},"headers":[{"level":2,"title":"Layer Definition features","slug":"layer-definition-features","link":"#layer-definition-features","children":[]},{"level":2,"title":"Big features (all optional)","slug":"big-features-all-optional","link":"#big-features-all-optional","children":[]},{"level":2,"title":"Prestige formula features","slug":"prestige-formula-features","link":"#prestige-formula-features","children":[]},{"level":2,"title":"Other prestige-related features","slug":"other-prestige-related-features","link":"#other-prestige-related-features","children":[]},{"level":2,"title":"Tree/node features","slug":"tree-node-features","link":"#tree-node-features","children":[]},{"level":2,"title":"Other features","slug":"other-features","link":"#other-features","children":[]},{"level":2,"title":"Custom Prestige type","slug":"custom-prestige-type","link":"#custom-prestige-type","children":[]}],"relativePath":"public/lit/docs/layer-features.md","lastUpdated":null}'),o={name:"public/lit/docs/layer-features.md"},n=s("",19),r=[n];function l(i,p,c,u,h,d){return a(),t("div",null,r)}const g=e(o,[["render",l]]);export{f as __pageData,g as default};
              +import{_ as e,c as t,o as a,a as s}from"./app.9bfeb8de.js";const f=JSON.parse('{"title":"Layer Features","description":"","frontmatter":{},"headers":[{"level":2,"title":"Layer Definition features","slug":"layer-definition-features","link":"#layer-definition-features","children":[]},{"level":2,"title":"Big features (all optional)","slug":"big-features-all-optional","link":"#big-features-all-optional","children":[]},{"level":2,"title":"Prestige formula features","slug":"prestige-formula-features","link":"#prestige-formula-features","children":[]},{"level":2,"title":"Other prestige-related features","slug":"other-prestige-related-features","link":"#other-prestige-related-features","children":[]},{"level":2,"title":"Tree/node features","slug":"tree-node-features","link":"#tree-node-features","children":[]},{"level":2,"title":"Other features","slug":"other-features","link":"#other-features","children":[]},{"level":2,"title":"Custom Prestige type","slug":"custom-prestige-type","link":"#custom-prestige-type","children":[]}],"relativePath":"public/lit/docs/layer-features.md","lastUpdated":null}'),o={name:"public/lit/docs/layer-features.md"},n=s("",19),r=[n];function l(i,p,c,u,h,d){return a(),t("div",null,r)}const g=e(o,[["render",l]]);export{f as __pageData,g as default};
              diff --git a/assets/public_lit_docs_main-mod-info.md.fae12359.js b/assets/public_lit_docs_main-mod-info.md.1d72d9fb.js
              similarity index 99%
              rename from assets/public_lit_docs_main-mod-info.md.fae12359.js
              rename to assets/public_lit_docs_main-mod-info.md.1d72d9fb.js
              index 24f85509d..8645ea1ce 100644
              --- a/assets/public_lit_docs_main-mod-info.md.fae12359.js
              +++ b/assets/public_lit_docs_main-mod-info.md.1d72d9fb.js
              @@ -1,4 +1,4 @@
              -import{_ as s,c as e,o as a,a as n}from"./app.a576d425.js";const f=JSON.parse('{"title":"mod.js","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/main-mod-info.md","lastUpdated":null}'),t={name:"public/lit/docs/main-mod-info.md"},o=n(`

              mod.js

              All of the non-layer code and data that you're likely to edit is here in mod.js! Everything in mod.js will not be altered by updates, besides the addition of new things.

              Here's a breakdown of what's in it:

              • modInfo is where most of the basic configuration for the mod is. It contains:

                • name: The name of your mod. (a string)

                • id: The id for your mod, a unique string that is used to determine savefile location. Setting it is important!

                • author: The name of the author, displayed in the info tab.

                • pointsName: This changes what is displayed instead of "points" for the main currency. (It does not affect it in the code.)

                • discordName, discordLink: If you have a Discord server or other discussion place, you can add a link to it.

                  "discordName" is the text on the link, and "discordLink" is the url of an invite. If you're using a Discord invite, please make sure it's set to never expire.

                • offlineLimit: The maximum amount of offline time that the player can accumulate, in hours. Any extra time is lost. (a number)

                  This is useful because most of these mods are fast-paced enough that too much offline time ruins the balance, such as the time in between updates. That is why I suggest developers disable offline time on their own savefile.

                • initialStartPoints: A Decimal for the amount of points a new player should start with.

              • VERSION is used to describe the current version of your mod. It contains:

                • num: The mod's version number, displayed at the top right of the tree tab.
                • name: The version's name, displayed alongside the number in the info tab.
              • changelog is the HTML displayed in the changelog tab.

              • doNotCallTheseFunctionsEveryTick is very important. TMT calls every function anywhere in "layers" every tick to store the result, unless specifically told not to. Functions that have are used to do an action need to be identified. "Official" functions (those in the documentation) are all fine, but if you make any new ones, add their names to this array.

              js
              // (The ones here are examples, all official functions are already taken care of)
              +import{_ as s,c as e,o as a,a as n}from"./app.9bfeb8de.js";const f=JSON.parse('{"title":"mod.js","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/main-mod-info.md","lastUpdated":null}'),t={name:"public/lit/docs/main-mod-info.md"},o=n(`

              mod.js

              All of the non-layer code and data that you're likely to edit is here in mod.js! Everything in mod.js will not be altered by updates, besides the addition of new things.

              Here's a breakdown of what's in it:

              • modInfo is where most of the basic configuration for the mod is. It contains:

                • name: The name of your mod. (a string)

                • id: The id for your mod, a unique string that is used to determine savefile location. Setting it is important!

                • author: The name of the author, displayed in the info tab.

                • pointsName: This changes what is displayed instead of "points" for the main currency. (It does not affect it in the code.)

                • discordName, discordLink: If you have a Discord server or other discussion place, you can add a link to it.

                  "discordName" is the text on the link, and "discordLink" is the url of an invite. If you're using a Discord invite, please make sure it's set to never expire.

                • offlineLimit: The maximum amount of offline time that the player can accumulate, in hours. Any extra time is lost. (a number)

                  This is useful because most of these mods are fast-paced enough that too much offline time ruins the balance, such as the time in between updates. That is why I suggest developers disable offline time on their own savefile.

                • initialStartPoints: A Decimal for the amount of points a new player should start with.

              • VERSION is used to describe the current version of your mod. It contains:

                • num: The mod's version number, displayed at the top right of the tree tab.
                • name: The version's name, displayed alongside the number in the info tab.
              • changelog is the HTML displayed in the changelog tab.

              • doNotCallTheseFunctionsEveryTick is very important. TMT calls every function anywhere in "layers" every tick to store the result, unless specifically told not to. Functions that have are used to do an action need to be identified. "Official" functions (those in the documentation) are all fine, but if you make any new ones, add their names to this array.

              js
              // (The ones here are examples, all official functions are already taken care of)
               var doNotCallTheseFunctionsEveryTick = ["doReset", "buy", "onPurchase", "blowUpEverything"]
               
              • getStartPoints(): A function to determine the amount of points the player starts with after a reset. (returns a Decimal value)

              • canGenPoints(): A function returning a boolean for if points should be generated. Use this if you want an upgrade to unlock generating points.

              • getPointGen(): A function that calculates your points per second. Anything that affects your point gain should go into the calculation here.

              • addedPlayerData(): A function that returns any non-layer-related data that you want to be added to the save data and "player" object.

              js
              function addedPlayerData() { return {
               	weather: "Yes",
              diff --git a/assets/public_lit_docs_main-mod-info.md.fae12359.lean.js b/assets/public_lit_docs_main-mod-info.md.1d72d9fb.lean.js
              similarity index 83%
              rename from assets/public_lit_docs_main-mod-info.md.fae12359.lean.js
              rename to assets/public_lit_docs_main-mod-info.md.1d72d9fb.lean.js
              index 9c805fc6c..48a47332c 100644
              --- a/assets/public_lit_docs_main-mod-info.md.fae12359.lean.js
              +++ b/assets/public_lit_docs_main-mod-info.md.1d72d9fb.lean.js
              @@ -1 +1 @@
              -import{_ as s,c as e,o as a,a as n}from"./app.a576d425.js";const f=JSON.parse('{"title":"mod.js","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/main-mod-info.md","lastUpdated":null}'),t={name:"public/lit/docs/main-mod-info.md"},o=n("",10),l=[o];function i(p,r,c,u,d,h){return a(),e("div",null,l)}const m=s(t,[["render",i]]);export{f as __pageData,m as default};
              +import{_ as s,c as e,o as a,a as n}from"./app.9bfeb8de.js";const f=JSON.parse('{"title":"mod.js","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/main-mod-info.md","lastUpdated":null}'),t={name:"public/lit/docs/main-mod-info.md"},o=n("",10),l=[o];function i(p,r,c,u,d,h){return a(),e("div",null,l)}const m=s(t,[["render",i]]);export{f as __pageData,m as default};
              diff --git a/assets/public_lit_docs_milestones.md.d148d9eb.js b/assets/public_lit_docs_milestones.md.d9f4b140.js
              similarity index 98%
              rename from assets/public_lit_docs_milestones.md.d148d9eb.js
              rename to assets/public_lit_docs_milestones.md.d9f4b140.js
              index 8e9e2666e..91df037d8 100644
              --- a/assets/public_lit_docs_milestones.md.d148d9eb.js
              +++ b/assets/public_lit_docs_milestones.md.d9f4b140.js
              @@ -1,4 +1,4 @@
              -import{_ as s,c as e,o as n,a}from"./app.a576d425.js";const F=JSON.parse('{"title":"Milestones","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/milestones.md","lastUpdated":null}'),t={name:"public/lit/docs/milestones.md"},o=a(`

              Milestones

              Milestones are awarded to the player when they meet a certain goal, and give some benefit. Milestones should be formatted like this:

              js
              milestones: {
              +import{_ as s,c as e,o as n,a}from"./app.9bfeb8de.js";const F=JSON.parse('{"title":"Milestones","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/milestones.md","lastUpdated":null}'),t={name:"public/lit/docs/milestones.md"},o=a(`

              Milestones

              Milestones are awarded to the player when they meet a certain goal, and give some benefit. Milestones should be formatted like this:

              js
              milestones: {
                   0: {
                       requirementDescription: "123 waffles",
                       effectDescription: "blah",
              diff --git a/assets/public_lit_docs_milestones.md.d148d9eb.lean.js b/assets/public_lit_docs_milestones.md.d9f4b140.lean.js
              similarity index 83%
              rename from assets/public_lit_docs_milestones.md.d148d9eb.lean.js
              rename to assets/public_lit_docs_milestones.md.d9f4b140.lean.js
              index f98c0127b..15cccca8a 100644
              --- a/assets/public_lit_docs_milestones.md.d148d9eb.lean.js
              +++ b/assets/public_lit_docs_milestones.md.d9f4b140.lean.js
              @@ -1 +1 @@
              -import{_ as s,c as e,o as n,a}from"./app.a576d425.js";const F=JSON.parse('{"title":"Milestones","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/milestones.md","lastUpdated":null}'),t={name:"public/lit/docs/milestones.md"},o=a("",7),l=[o];function p(i,r,c,u,d,h){return n(),e("div",null,l)}const g=s(t,[["render",p]]);export{F as __pageData,g as default};
              +import{_ as s,c as e,o as n,a}from"./app.9bfeb8de.js";const F=JSON.parse('{"title":"Milestones","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/milestones.md","lastUpdated":null}'),t={name:"public/lit/docs/milestones.md"},o=a("",7),l=[o];function p(i,r,c,u,d,h){return n(),e("div",null,l)}const g=s(t,[["render",p]]);export{F as __pageData,g as default};
              diff --git a/assets/public_lit_docs_subtabs-and-microtabs.md.64d0692d.js b/assets/public_lit_docs_subtabs-and-microtabs.md.07a92c3c.js
              similarity index 99%
              rename from assets/public_lit_docs_subtabs-and-microtabs.md.64d0692d.js
              rename to assets/public_lit_docs_subtabs-and-microtabs.md.07a92c3c.js
              index be579c8ee..6405e1b96 100644
              --- a/assets/public_lit_docs_subtabs-and-microtabs.md.64d0692d.js
              +++ b/assets/public_lit_docs_subtabs-and-microtabs.md.07a92c3c.js
              @@ -1,4 +1,4 @@
              -import{_ as s,c as a,o as n,a as o}from"./app.a576d425.js";const D=JSON.parse('{"title":"Subtabs and Microtabs","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/subtabs-and-microtabs.md","lastUpdated":null}'),t={name:"public/lit/docs/subtabs-and-microtabs.md"},l=o(`

              Subtabs and Microtabs

              Subtabs are separate sections of a tab that you can view by selecting one at the top of the tab. Microtabs are smaller areas that function in much the same way. You can also embed layers inside of subtabs/microtabs.

              Subtabs are defined by using the tab format like this, where each element of tabFormat is given the name of that subtab:

              js
              tabFormat: {
              +import{_ as s,c as a,o as n,a as o}from"./app.9bfeb8de.js";const D=JSON.parse('{"title":"Subtabs and Microtabs","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/subtabs-and-microtabs.md","lastUpdated":null}'),t={name:"public/lit/docs/subtabs-and-microtabs.md"},l=o(`

              Subtabs and Microtabs

              Subtabs are separate sections of a tab that you can view by selecting one at the top of the tab. Microtabs are smaller areas that function in much the same way. You can also embed layers inside of subtabs/microtabs.

              Subtabs are defined by using the tab format like this, where each element of tabFormat is given the name of that subtab:

              js
              tabFormat: {
                   "Main tab": {
                       content: [tab format things],
                       *subtab features*
              diff --git a/assets/public_lit_docs_subtabs-and-microtabs.md.64d0692d.lean.js b/assets/public_lit_docs_subtabs-and-microtabs.md.07a92c3c.lean.js
              similarity index 84%
              rename from assets/public_lit_docs_subtabs-and-microtabs.md.64d0692d.lean.js
              rename to assets/public_lit_docs_subtabs-and-microtabs.md.07a92c3c.lean.js
              index 5e74c2e94..8bc9039bc 100644
              --- a/assets/public_lit_docs_subtabs-and-microtabs.md.64d0692d.lean.js
              +++ b/assets/public_lit_docs_subtabs-and-microtabs.md.07a92c3c.lean.js
              @@ -1 +1 @@
              -import{_ as s,c as a,o as n,a as o}from"./app.a576d425.js";const D=JSON.parse('{"title":"Subtabs and Microtabs","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/subtabs-and-microtabs.md","lastUpdated":null}'),t={name:"public/lit/docs/subtabs-and-microtabs.md"},l=o("",9),e=[l];function p(r,c,i,F,y,u){return n(),a("div",null,e)}const h=s(t,[["render",p]]);export{D as __pageData,h as default};
              +import{_ as s,c as a,o as n,a as o}from"./app.9bfeb8de.js";const D=JSON.parse('{"title":"Subtabs and Microtabs","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/subtabs-and-microtabs.md","lastUpdated":null}'),t={name:"public/lit/docs/subtabs-and-microtabs.md"},l=o("",9),e=[l];function p(r,c,i,F,y,u){return n(),a("div",null,e)}const h=s(t,[["render",p]]);export{D as __pageData,h as default};
              diff --git a/assets/public_lit_docs_trees-and-tree-customization.md.4825432f.js b/assets/public_lit_docs_trees-and-tree-customization.md.4afa4175.js
              similarity index 99%
              rename from assets/public_lit_docs_trees-and-tree-customization.md.4825432f.js
              rename to assets/public_lit_docs_trees-and-tree-customization.md.4afa4175.js
              index d732bf6ea..04515fd4c 100644
              --- a/assets/public_lit_docs_trees-and-tree-customization.md.4825432f.js
              +++ b/assets/public_lit_docs_trees-and-tree-customization.md.4afa4175.js
              @@ -1,4 +1,4 @@
              -import{_ as e,c as t,o,a}from"./app.a576d425.js";const D=JSON.parse('{"title":"Trees and tree customization","description":"","frontmatter":{},"headers":[{"level":2,"title":"layoutInfo","slug":"layoutinfo","link":"#layoutinfo","children":[]},{"level":2,"title":"Trees","slug":"trees","link":"#trees","children":[]},{"level":2,"title":"Nodes","slug":"nodes","link":"#nodes","children":[]}],"relativePath":"public/lit/docs/trees-and-tree-customization.md","lastUpdated":null}'),s={name:"public/lit/docs/trees-and-tree-customization.md"},n=a(`

              Trees and tree customization

              If you want to have something beyond the standard tree on the left tab, you can do that in tree.js. You can change the layout of the tree, including making non-layer nodes, change it into something other than a tree, or hide the left tab altogether. This also introduces the "tree" component, which can be used in your layers as well.

              layoutInfo

              The most important part is layoutInfo, containing:

              • startTab: The id of the default tab to show on the left at the start.
              • showTree: True if the tree tab should be shown at the start of the game. (The other tab will fill the whole page)
              • treeLayout: If present, overrides the tree layout and places nodes as you describe instead (explained in the next section).

              Additionally, if you want the main layout to not be a tree, you can edit the "tree-tab" layer at the bottom of tree.js to modify it just like a normal layer's tab. You can even switch between left tabs, using showNavTab(layer) to make that layer appear on the left.

              Trees

              The tree component is defined as an array of arrays of names of layers or nodes to show in the tree. They work just like layers/ nodes in the main tree (but branches between nodes will only work on the first node if you have duplicates.)

              Here is an example tree:

              js
              [["p"],
              +import{_ as e,c as t,o,a}from"./app.9bfeb8de.js";const D=JSON.parse('{"title":"Trees and tree customization","description":"","frontmatter":{},"headers":[{"level":2,"title":"layoutInfo","slug":"layoutinfo","link":"#layoutinfo","children":[]},{"level":2,"title":"Trees","slug":"trees","link":"#trees","children":[]},{"level":2,"title":"Nodes","slug":"nodes","link":"#nodes","children":[]}],"relativePath":"public/lit/docs/trees-and-tree-customization.md","lastUpdated":null}'),s={name:"public/lit/docs/trees-and-tree-customization.md"},n=a(`

              Trees and tree customization

              If you want to have something beyond the standard tree on the left tab, you can do that in tree.js. You can change the layout of the tree, including making non-layer nodes, change it into something other than a tree, or hide the left tab altogether. This also introduces the "tree" component, which can be used in your layers as well.

              layoutInfo

              The most important part is layoutInfo, containing:

              • startTab: The id of the default tab to show on the left at the start.
              • showTree: True if the tree tab should be shown at the start of the game. (The other tab will fill the whole page)
              • treeLayout: If present, overrides the tree layout and places nodes as you describe instead (explained in the next section).

              Additionally, if you want the main layout to not be a tree, you can edit the "tree-tab" layer at the bottom of tree.js to modify it just like a normal layer's tab. You can even switch between left tabs, using showNavTab(layer) to make that layer appear on the left.

              Trees

              The tree component is defined as an array of arrays of names of layers or nodes to show in the tree. They work just like layers/ nodes in the main tree (but branches between nodes will only work on the first node if you have duplicates.)

              Here is an example tree:

              js
              [["p"],
                ["left", "blank", "right", "blank"]
                ["a", "b", "blank", "c", "weirdButton"]]
               

              Nodes

              Nodes are non-layer buttons that can go in trees. They are defined similarly to layers, but with addNode instead of addLayer.

              Features:

              • color: optional, The node's color. (A string in hex format with a #)

              • symbol: optional The text on the button (The id capitalized by default)

              • canClick(): Returns true if the player can click the node. ()

              • onClick(): The function called when the node is clicked.

              • layerShown(): optional, A function returning a bool which determines if this node should be visible. It can also return "ghost", which will hide the layer, but its node will still take up space in its tree.

              • branches: optional. An array of layer/node ids. On a tree, a line will appear from this node to all of the nodes in the list. Alternatively, an entry in the array can be a 2-element array consisting of the id and a color value. The color value can either be a string with a hex color code, or a number from 1-3 (theme-affected colors).

              • nodeStyle: optional. A CSS object, where the keys are CSS attributes, which styles this node on the tree.

              • tooltip() / tooltipLocked(): optional. Functions that return text, which is the tooltip for the node when the layer is unlocked or locked, respectively. By default the tooltips behave the same as in the original Prestige Tree.

              • row: optional, the row that this node appears in (for the default tree).

              • position: optional, Determines the horizontal position of the layer in its row in a default tree. By default, it uses the id, and layers/nodes are sorted in alphabetical order.

              `,14),l=[n];function r(i,p,c,h,d,u){return o(),t("div",null,l)}const f=e(s,[["render",r]]);export{D as __pageData,f as default}; diff --git a/assets/public_lit_docs_trees-and-tree-customization.md.4825432f.lean.js b/assets/public_lit_docs_trees-and-tree-customization.md.4afa4175.lean.js similarity index 90% rename from assets/public_lit_docs_trees-and-tree-customization.md.4825432f.lean.js rename to assets/public_lit_docs_trees-and-tree-customization.md.4afa4175.lean.js index 03fe8f0d4..39a2c7383 100644 --- a/assets/public_lit_docs_trees-and-tree-customization.md.4825432f.lean.js +++ b/assets/public_lit_docs_trees-and-tree-customization.md.4afa4175.lean.js @@ -1 +1 @@ -import{_ as e,c as t,o,a}from"./app.a576d425.js";const D=JSON.parse('{"title":"Trees and tree customization","description":"","frontmatter":{},"headers":[{"level":2,"title":"layoutInfo","slug":"layoutinfo","link":"#layoutinfo","children":[]},{"level":2,"title":"Trees","slug":"trees","link":"#trees","children":[]},{"level":2,"title":"Nodes","slug":"nodes","link":"#nodes","children":[]}],"relativePath":"public/lit/docs/trees-and-tree-customization.md","lastUpdated":null}'),s={name:"public/lit/docs/trees-and-tree-customization.md"},n=a("",14),l=[n];function r(i,p,c,h,d,u){return o(),t("div",null,l)}const f=e(s,[["render",r]]);export{D as __pageData,f as default}; +import{_ as e,c as t,o,a}from"./app.9bfeb8de.js";const D=JSON.parse('{"title":"Trees and tree customization","description":"","frontmatter":{},"headers":[{"level":2,"title":"layoutInfo","slug":"layoutinfo","link":"#layoutinfo","children":[]},{"level":2,"title":"Trees","slug":"trees","link":"#trees","children":[]},{"level":2,"title":"Nodes","slug":"nodes","link":"#nodes","children":[]}],"relativePath":"public/lit/docs/trees-and-tree-customization.md","lastUpdated":null}'),s={name:"public/lit/docs/trees-and-tree-customization.md"},n=a("",14),l=[n];function r(i,p,c,h,d,u){return o(),t("div",null,l)}const f=e(s,[["render",r]]);export{D as __pageData,f as default}; diff --git a/assets/public_lit_docs_updating-tmt.md.8bc0cda6.js b/assets/public_lit_docs_updating-tmt.md.3cdc68a8.js similarity index 96% rename from assets/public_lit_docs_updating-tmt.md.8bc0cda6.js rename to assets/public_lit_docs_updating-tmt.md.3cdc68a8.js index 0899f0b9d..a2746b7c1 100644 --- a/assets/public_lit_docs_updating-tmt.md.8bc0cda6.js +++ b/assets/public_lit_docs_updating-tmt.md.3cdc68a8.js @@ -1 +1 @@ -import{_ as t,c as e,o,a}from"./app.a576d425.js";const m=JSON.parse('{"title":"Updating The Modding Tree","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/updating-tmt.md","lastUpdated":null}'),i={name:"public/lit/docs/updating-tmt.md"},n=a('

              Updating The Modding Tree

              This tutorial assumes that you have used the Getting Started Tutorial, and are using Github Desktop and VSCode for your mod.

              Here's what you have to do when there's a TMT update:

              1. Look at the changelog. It will warn you if the update will break anything or require any changes. Decide if you want to try to update.

              2. Open Github Desktop, and at the top middle, click "fetch origin". This will make Github Desktop get information about the update.

              3. Click where it says "current branch: master" at the top middle, and at the bottom of the thing that appears, click "choose a branch to merge into master".

              4. Select upstream/master. It will likely say there are conflicts, but you have tools to resolve them. Click "Merge upstream/master into master".

              5. A conflict happens when the things you're trying to merge have both made changes in the same place. Click "open in Visual Studio Code" next to the first file.

              6. Scroll down through the file, and look for the parts highlighted in red and green. One of these is your code, and the other is some code that will be modified by the update. Do your best to try to edit things to keep the updated changes, but keep your content.

              7. Continue to do this for all remaining changes.

              8. Do any other changes required by the update, run the game, fix issues, etc.

              ',4),r=[n];function h(d,s,l,p,u,c){return o(),e("div",null,r)}const _=t(i,[["render",h]]);export{m as __pageData,_ as default}; +import{_ as t,c as e,o,a}from"./app.9bfeb8de.js";const m=JSON.parse('{"title":"Updating The Modding Tree","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/updating-tmt.md","lastUpdated":null}'),i={name:"public/lit/docs/updating-tmt.md"},n=a('

              Updating The Modding Tree

              This tutorial assumes that you have used the Getting Started Tutorial, and are using Github Desktop and VSCode for your mod.

              Here's what you have to do when there's a TMT update:

              1. Look at the changelog. It will warn you if the update will break anything or require any changes. Decide if you want to try to update.

              2. Open Github Desktop, and at the top middle, click "fetch origin". This will make Github Desktop get information about the update.

              3. Click where it says "current branch: master" at the top middle, and at the bottom of the thing that appears, click "choose a branch to merge into master".

              4. Select upstream/master. It will likely say there are conflicts, but you have tools to resolve them. Click "Merge upstream/master into master".

              5. A conflict happens when the things you're trying to merge have both made changes in the same place. Click "open in Visual Studio Code" next to the first file.

              6. Scroll down through the file, and look for the parts highlighted in red and green. One of these is your code, and the other is some code that will be modified by the update. Do your best to try to edit things to keep the updated changes, but keep your content.

              7. Continue to do this for all remaining changes.

              8. Do any other changes required by the update, run the game, fix issues, etc.

              ',4),r=[n];function h(d,s,l,p,u,c){return o(),e("div",null,r)}const _=t(i,[["render",h]]);export{m as __pageData,_ as default}; diff --git a/assets/public_lit_docs_updating-tmt.md.8bc0cda6.lean.js b/assets/public_lit_docs_updating-tmt.md.3cdc68a8.lean.js similarity index 84% rename from assets/public_lit_docs_updating-tmt.md.8bc0cda6.lean.js rename to assets/public_lit_docs_updating-tmt.md.3cdc68a8.lean.js index 19211e752..7231130a6 100644 --- a/assets/public_lit_docs_updating-tmt.md.8bc0cda6.lean.js +++ b/assets/public_lit_docs_updating-tmt.md.3cdc68a8.lean.js @@ -1 +1 @@ -import{_ as t,c as e,o,a}from"./app.a576d425.js";const m=JSON.parse('{"title":"Updating The Modding Tree","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/updating-tmt.md","lastUpdated":null}'),i={name:"public/lit/docs/updating-tmt.md"},n=a("",4),r=[n];function h(d,s,l,p,u,c){return o(),e("div",null,r)}const _=t(i,[["render",h]]);export{m as __pageData,_ as default}; +import{_ as t,c as e,o,a}from"./app.9bfeb8de.js";const m=JSON.parse('{"title":"Updating The Modding Tree","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/updating-tmt.md","lastUpdated":null}'),i={name:"public/lit/docs/updating-tmt.md"},n=a("",4),r=[n];function h(d,s,l,p,u,c){return o(),e("div",null,r)}const _=t(i,[["render",h]]);export{m as __pageData,_ as default}; diff --git a/assets/public_lit_docs_upgrades.md.9c2674ea.js b/assets/public_lit_docs_upgrades.md.45e6f45b.js similarity index 99% rename from assets/public_lit_docs_upgrades.md.9c2674ea.js rename to assets/public_lit_docs_upgrades.md.45e6f45b.js index d171fbfda..d0cef3f0d 100644 --- a/assets/public_lit_docs_upgrades.md.9c2674ea.js +++ b/assets/public_lit_docs_upgrades.md.45e6f45b.js @@ -1,4 +1,4 @@ -import{_ as e,c as s,o as a,a as n}from"./app.a576d425.js";const g=JSON.parse('{"title":"Upgrades","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/upgrades.md","lastUpdated":null}'),t={name:"public/lit/docs/upgrades.md"},o=n(`

              Upgrades

              Useful functions for dealing with Upgrades and implementing their effects:

              • hasUpgrade(layer, id): determine if the player has the upgrade
              • upgradeEffect(layer, id): Returns the current effects of the upgrade, if any
              • buyUpgrade(layer, id): Buys an upgrade directly (if affordable)

              Hint: Basic point gain is calculated in mod.js's "getPointGen" function.

              Upgrades are stored in the following format:

              js
              upgrades: {
              +import{_ as e,c as s,o as a,a as n}from"./app.9bfeb8de.js";const g=JSON.parse('{"title":"Upgrades","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/upgrades.md","lastUpdated":null}'),t={name:"public/lit/docs/upgrades.md"},o=n(`

              Upgrades

              Useful functions for dealing with Upgrades and implementing their effects:

              • hasUpgrade(layer, id): determine if the player has the upgrade
              • upgradeEffect(layer, id): Returns the current effects of the upgrade, if any
              • buyUpgrade(layer, id): Buys an upgrade directly (if affordable)

              Hint: Basic point gain is calculated in mod.js's "getPointGen" function.

              Upgrades are stored in the following format:

              js
              upgrades: {
                   rows: # of rows,
                   cols: # of columns,
                   11: {
              diff --git a/assets/public_lit_docs_upgrades.md.9c2674ea.lean.js b/assets/public_lit_docs_upgrades.md.45e6f45b.lean.js
              similarity index 83%
              rename from assets/public_lit_docs_upgrades.md.9c2674ea.lean.js
              rename to assets/public_lit_docs_upgrades.md.45e6f45b.lean.js
              index 9583ef2d6..a8ab95b53 100644
              --- a/assets/public_lit_docs_upgrades.md.9c2674ea.lean.js
              +++ b/assets/public_lit_docs_upgrades.md.45e6f45b.lean.js
              @@ -1 +1 @@
              -import{_ as e,c as s,o as a,a as n}from"./app.a576d425.js";const g=JSON.parse('{"title":"Upgrades","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/upgrades.md","lastUpdated":null}'),t={name:"public/lit/docs/upgrades.md"},o=n("",13),l=[o];function r(p,i,c,u,d,y){return a(),s("div",null,l)}const f=e(t,[["render",r]]);export{g as __pageData,f as default};
              +import{_ as e,c as s,o as a,a as n}from"./app.9bfeb8de.js";const g=JSON.parse('{"title":"Upgrades","description":"","frontmatter":{},"headers":[],"relativePath":"public/lit/docs/upgrades.md","lastUpdated":null}'),t={name:"public/lit/docs/upgrades.md"},o=n("",13),l=[o];function r(p,i,c,u,d,y){return a(),s("div",null,l)}const f=e(t,[["render",r]]);export{g as __pageData,f as default};
              diff --git a/guide-to-incrementals/index.html b/guide-to-incrementals/index.html
              index 456475d40..5278c53c3 100644
              --- a/guide-to-incrementals/index.html
              +++ b/guide-to-incrementals/index.html
              @@ -6,8 +6,8 @@
                   Introduction | The Paper Pilot
                   
                   
              -    
              -    
              +    
              +    
                   
                   
                 
              @@ -18,8 +18,8 @@
                 
                 
                   
              Skip to content
              On this page

              Introduction

              This is a comprehensive guide to Incremental Games, a genre of video games. It will explore defining the genre, why it's appealing, and how to design and build your own incremental game. Along the way will be interactive examples, snippets from other creators, and relevant material to contextualize everything.

              Note: This is an incomplete document. I want to keep adding opinions and opposing views from other incremental games developers, and add interactive examples to illustrate various points regarding game design and balancing. Consider this a living document - and see the changelog at the end.

              Who am I?

              That's a good question! What authority do I have to be making this site? I haven't made the best incremental games, nor the most incremental games, certainly not the most popular ones either. I do have some formal education in game development, know a lot of incremental game devs, as well as other game devs, and an interest in ludology, classifying genres, etc. I've also made a couple of incremental games myself.

              If you have any additional questions about my credentials or anything on this site, feel free to contact me: I'm "The Paper Pilot" on most social media. You'll probably get a response fastest via my discord server, or if you just want to suggest changes to the website you can click the "Edit this page" link present on every single page.

              - - + + \ No newline at end of file diff --git a/guide-to-incrementals/ludology/appeal-developers/index.html b/guide-to-incrementals/ludology/appeal-developers/index.html index 9d5b32601..a22ade5dd 100644 --- a/guide-to-incrementals/ludology/appeal-developers/index.html +++ b/guide-to-incrementals/ludology/appeal-developers/index.html @@ -6,8 +6,8 @@ The Paper Pilot | The Paper Pilot - - + + @@ -18,8 +18,8 @@ - - + + \ No newline at end of file diff --git a/guide-to-incrementals/ludology/appeal-gamers/index.html b/guide-to-incrementals/ludology/appeal-gamers/index.html index fcae9aafa..10730c84a 100644 --- a/guide-to-incrementals/ludology/appeal-gamers/index.html +++ b/guide-to-incrementals/ludology/appeal-gamers/index.html @@ -6,8 +6,8 @@ The Paper Pilot | The Paper Pilot - - + + @@ -18,8 +18,8 @@ - - + + \ No newline at end of file diff --git a/guide-to-incrementals/ludology/content/index.html b/guide-to-incrementals/ludology/content/index.html index a43125a86..e48ba3a62 100644 --- a/guide-to-incrementals/ludology/content/index.html +++ b/guide-to-incrementals/ludology/content/index.html @@ -6,8 +6,8 @@ The Paper Pilot | The Paper Pilot - - + + @@ -18,8 +18,8 @@ - - + + \ No newline at end of file diff --git a/guide-to-incrementals/ludology/definition/index.html b/guide-to-incrementals/ludology/definition/index.html index 0b34bd4d4..acf51bf79 100644 --- a/guide-to-incrementals/ludology/definition/index.html +++ b/guide-to-incrementals/ludology/definition/index.html @@ -6,8 +6,8 @@ Defining the Genre | The Paper Pilot - - + + @@ -18,8 +18,8 @@
              Skip to content
              On this page

              Defining the Genre

              Video games are placed into genres for a variety of reasons. They can give a mental shorthand to set the player's expectations up, they can help a game market itself by its similarities to other, already popular games, and honestly, people just love categorization for its own sake. For this guide, it's important to define the genre so it is clear what games it's even talking about.

              This poses a problem. "Incremental" is a horribly vague way to define games. Most games have numbers going up in some form or another. We need a more specific definition - similar to how "strategy" can't just mean any game with any amount of strategy because that would be most games. What specifically differentiates incremental games from the rest?

              "Incremental" implies it's a genre defined by a game mechanic, but all those game mechanics it could imply exist in many other games. Having a skill tree or upgrades doesn't make you incremental, and if a reset mechanic is all it takes then every roguelite would be an incremental as well. So clearly there's more to it than that - what makes an incremental an incremental?

              I'd like to go over a couple of popular suggestions I've seen on defining the genre here. I have my personal preferences and will state them here, but I don't think there's a truly perfect answer here.

              Disclaimer: I mostly play incremental games on my computer, and my definitions will be heavily biased towards the games I'm familiar with.

              Incrementals vs Idlers vs Clickers

              Oftentimes people refer to this genre as idle games and/or clicker games. You'll even find a trend of oxymoronic game titles that contain both terms. "Incremental games" is the umbrella term both those terms fall under. However, I'd like to argue that not only is it better to just use the term "incremental games", but calling them "idle games" or "clicker games" is wrong. Almost universally, these terms are used interchangeably to refer to the same kind of game, where you start the game click spamming and eventually automate the process. Frankly, that kind of game deserves neither title, and the incremental games genre has trended away from ever requiring click spamming, as it's a bad mechanic, anyways.

              While these games do span a spectrum of how active it requires you to be, and sorting games by that metric can be useful for those looking for a particular experience, the borders of when an incremental game counts as an "idler" is too blurry for the term to be useful. "Incremental games" may not be a great descriptive term for the genre (hence this many thousands of words long page on defining what the genre even is), but it's strictly better than calling them "idler" or "clicker" games. This guide will always use the term "incremental games" unless quoting someone else, as it is the term you typically see on all modern games in the genre.

              Incrementals as Parodies

              Let's start with one of the most interesting definitions of incremental games. Incremental games appear to be distilled versions of games or genres, "revealing" the naked game design at the core of these games or genres not unlike how parodies comment upon their source material.

              To understand what that means, think of how a casino uses skinner boxes to emotionally manipulate its customers to keep playing, but "dressing" up the skinner box with tons of stimuli to hide that ultimately the goal is to manipulate you to keep coming back. The idea that incremental games are parodies means taking the stance that at some level all games are similarly manipulating you, giving dopamine rewards in a way that manipulates you to keep playing while not necessarily giving you any value or fulfillment. Incremental games, then, are any games that plainly display the skinner box, and the manipulative core of the game, at the forefront of the experience.

              This "undressing" tends to go hand in hand with a reduced focus on aesthetics, often just printing the game state directly to the screen as text. This makes incremental games much easier to develop, particularly for those with programming skills but not art skills, but that's a tangent for why Incremental Games appeal to Developers.

              Before I continue, I'd like to make my stance clear that I love games and incremental games, and do not think they should be considered inherently bad or manipulative with the above logic. Skinner boxes are just a way of manipulating behavior via rewards. The games are still fun - that's the reward! I'd believe the real criticism here is that it is "empty fun", or "empty dopamine", that doesn't offer any additional value or sense of fulfillment. I don't think that's inherently bad in moderation, although it can become a problem if the game is manipulating you for profit-seeking, or if you play the game to the detriment of the other parts of your life. While incremental games can be fun and even healthy in certain contexts, they can exacerbate video game addiction moreso than other genres. If you feel like playing incremental games is taking priority over other things in your life, or manipulating your sleep schedule, it may be prudent to seek help. See r/StopGaming for resources.

              Another interpretation of incremental games as parodies comes from several mainstream incremental games that are also parodies of capitalism, such as cookie clicker and adventure capitalist. It's a very common framework for incremental games to portray the ever-increasing numbers as an insatiable hunger for resources, like the ones observed within capitalism. Therefore, these games are used as evidence that the genre as a whole is about parody and commentary.

              Popular videos on incremental games that portray the genre as parodies are Why Idle games make good satire, and how it was ruined. and Bad Game Design - Clicker Games. You may also be interested in this response to the latter video from a fan of incremental games: BadGood Game Design - Clicker Games.

              I think that this definition ultimately ascribes a motive to the genre as a whole that only happens to apply to some of the more mainstream titles. There certainly are incremental games commenting on different things, including the genre itself as in the case of The Prestige Tree Classic, The Ascension Tree, or Omega Layers, but certainly not all. And of course, not all games that comment on something or parody something are incremental games! Additionally, a very large majority of incremental games are mobile games using these manipulative strategies to get players to spend as much money as possible - hell, Adventure Capitalist is ostensibly a critique on capitalism but features microtransactions and gameplay that manipulates you into buying them! These profit-seeking incremental games certainly belong within the genre but are hardly parodies when they too use manipulation to serve their interests. Also, from my own anecdotal experience, those who use this definition seem to do so from a fairly surface-level familiarity with the genre, and often in the context of criticizing the genre or the fans thereof.

              Incrementals as NGU

              Another broad definition often used is that incremental games are games where the focus of the game is "numbers going up". This definition proposes that other genres simply use increasing numbers as a means to an end, but incremental games uniquely only care about the numbers themselves going up. Put another way, it implies there should be no narrative justification for the numbers going up other than "why shouldn't they be going up?"

              While this definition is common because it feels easy to understand, it is difficult to formally define. Often phrases are used to describe games using this framework, such as having an "exaggerated sense of progression" or "big" numbers. These terms are vague and don't demonstrate an actual threshold between non-incrementals and incrementals. Most games have a sense of progression, so when is it "exaggerated"? How big are "big" numbers? Most notably, RPGs that are typically not considered incrementals will often pass this definition.

              Additionally, a lot of incrementals tend to have some theme guiding the gameplay, or at least the names of mechanics. This makes the line blurred between when numbers are going up for their own sake versus for a contextual reason. I believe this point is best illustrated that, while most RPGs are not considered incremental games, there is a sub-genre of "incremental RPGs" that typically relates to RPGs that perform combat automatically. This definition of incremental games does not support RPGs and "incremental RPGs" being on distinct sides of the line if the only difference between them is manual vs automatic combat.

              Incrementals as Strategies

              This is a rarer interpretation, but there are similarities between incremental games and strategy games, implying incrementals might just be a sub-genre of strategy games. By this approach, incremental games would be defined by their relation to strategy games, and how they involve player strategy. Incremental games are often large optimization problems - above all else, the actual gameplay the player is performing is deciding what to do next. The consequences of wrong decisions are typically more lenient in incremental games - such as just not making optimal progress - but they certainly get complex.

              So if we accept the premise that incrementals could fall under strategy, we still need to define what makes a strategy game an incremental versus some other strategy sub-genre. This is a bit tricky due to one particular sub-genre of strategy games: Factory Builders.

              Factory builders, such as Factorio or Satisfactory, are games about gaining ever increasing resources, optimizing production, and expanding more and more. That... sounds pretty similar, doesn't it? In fact, there's been some debate on whether factory builders would fall under the "incremental" umbrella. I think it's safe to say the two are certainly related, and probably have quite a bit of overlap in playerbase.

              Roguelites as Incrementals?

              Earlier on, I mentioned reset mechanics shouldn't be used in the definition because that could make all roguelites incrementals... But what if it does? A lot of incrementals can be described as games with a strong sense of progression, often with layers of meta-progression. Roguelites fit that bill to a T. What would make roguelites not incremental? I honestly don't think there's a good explanation here, but many fans of incremental games will state they do believe the two genres to be unrelated, even if there's a significant overlap between their player bases due to having similar appealing traits.

              At this point, it'd be appropriate to consider what part of the definition of roguelites precludes them from also being incrementals, but that reveals a new problem: What are roguelites? They're usually defined as rogue_likes with meta-progression, but that just pushes the problem back a step: Incrementals aren't the only genre to have difficulties defining themselves, it seems! Roguelikes are another genre where the community argues over the formal definition of their genre, although that means we can borrow from their process of coming to a consensus, and maybe come across a viable definition for incremental games.

              The Berlin Interpretation

              By far the most popular way of defining roguelikes is the "Berlin Interpretation", which acknowledged the diversity of games within the genre and argued the definition should not be based on any ideals about what the genre ought to be, but rather defined by "its canon". They argued there are a handful of games that can be used to define the canon for roguelikes, and from those games, a list of factors can be derived to determine a game's "roguelikeness". The more factors a game has, the more of a roguelike it is. This strategy is very lenient, allowing a game to not present any specific factor so long as it shows enough, and accounts for the blurriness of any genre definition by not explicitly stating how many factors a game must have to qualify as a definite roguelike.

              I believe this strategy for defining genres can be applied to other genres as well. A handful of games can be argued to be the incremental games canon, and a list of factors derived from them can be used to judge any game based on its "incrementalness". I'll propose such a canon and list of factors here, but by no means should it be considered the end-all-be-all.

              Note: The "Temple of the roguelike", an authority within the genre, has since replaced the Berlin Interpretation with a new set of factors here: https://blog.roguetemple.com/what-is-a-traditional-roguelike/

              The Incremental Games Canon

              Alright, time to get controversial. Up til now, I've been trying my best to stay objective and analytical, but now it's time to start making some opinionated decisions. Here is a list of games I think could justifiably make up an Incremental Games Canon:

              I chose a variety of games here, biasing towards newer games, purposefully to avoid making a narrow or "traditional" definition. The genre is growing and shouldn't be constrained by the traits of the early popular titles. A lot of these could easily be replaced with other games that are mechanically congruent, so ultimately I'm sure if you asked 10 people for their canon list you'd just get 10 different answers, but I think this should sufficiently allow us to determine what factors make a game have higher "incrementalness".

              The Paradigm Shift

              The Paradigm Shift is probably the highest possible value factor for an incremental. It's so common that for a while people referred to incrementals that exhibit this trait as "unfolding" games, to the point of trying to replace the term incremental due to their popularity. Paradigm shifts refer to when the gameplay significantly changes. There are too many examples to list here, but notably, every single reset mechanic is typically going to be a paradigm shift. Examples of games with paradigm shifts that aren't tied to reset mechanics include Universal Paperclips and A Dark Room.

              There are many reasons for the appeal of paradigm shifts. Oftentimes each mechanic builds on top of the existing mechanics, increasing the complexity of the game in steps so the player can follow along. They provide a sense of mystery, with the player anticipating what will happen next. They shake up the gameplay before it gets too stale - allowing the game to entertain for longer before the illusion of content dissipates. Of the canon games selected above, I would argue every single one contains a paradigm shift (although I could see someone disagreeing with that statement wrt Increlution).

              I should take a moment to say that while I'm hyping up this specific factor, we cannot just reduce the genre definition to "does it have paradigm shifts". Many games have paradigm shifts that are not incremental, so it's just an indicator of incrementalness. Additionally, it can become quite hard to determine how large of a shift is a "paradigm" shift. Take, for example, any game with a skill tree. In some games, each skill node might have a large impact on how you play with the game, and qualify as a paradigm shift for some players. In other games, each skill node might just be a small percentage modifier on some stat that doesn't really impact much more than a slight bias towards an already established mechanic that's newly buffed. Every single canon game may show that it's common amongst incremental games, but could just as easily indicate that they're common in games in general.

              High-Value Factors

              I won't take as long to discuss the high and low-value factors, as you've already seen most of them brought up earlier on this page. As a reminder, a game does NOT need all of these to be an incremental game, but these are factors that each indicate a strong possibility the game is an incremental, so having several of these means they probably are. These factors apply to most of the canon incremental games.

              "Pure UI" Display. Incrementals typically have a textual presentation of the game state - there isn't a visual representation of the entities within the game. The interface is closer to what would be just the UI of a game in another genre or the control panel of a plane. If there is a visual representation, the player is often still interacting with non-diegetic game elements.

              Reduced Consequences. Incrementals tend to have reduced repurcussions for misplaying. They very rarely have fail states, where often the largest consequence is simply not progressing - never losing progress.

              Optimization Problems. The predominant gameplay of incrementals is typically solving optimization problems, from deciding which purchase to save up for to reasoning and deciding between different mutually exclusive options the game presents.

              Resource Management. Incrementals tend to have a lot of resources within the game to keep track of.

              Low-Value Factors

              These are low-value factors, meaning they aren't as strongly correlated with incremental games. Incremental games may have none of these, and non-incrementals may have several of these - if a game only has low-value factors, they're probably not an incremental.

              Fast Numeric Growth. Numbers in incremental games tend to grow faster than in other genres. There are more instances of superlinear growth. The larger the numbers get, the stronger of a signal this factor is.

              Automation. As an incremental game progresses, the player often no longer has to deal with earlier mechanics, by having them either happen automatically or otherwise be replaced with an alternative that requires less player interaction.

              Goal-Oriented. Incrementals are often heavily reliant on extrinsic motivation to guide the player. Typically this is through some sort of in-game goal to work towards, such as a certain amount of a resource being required to unlock or purchase something new.

              Waiting is a Mechanic. In incremental games, the player may come across times where there is no action they can take, and the game will progress automatically instead. The player must wait for some amount of this automatic progress to occur before they can resume interaction with the game.

              Are Roguelites Incrementals?

              Having made our variation of the Berlin Interpretation for incremental games, we can compare it to the Berlin Interpretation to determine if there's enough overlap that any game that "passes" the Berlin Interpretation would also pass the incremental variant. That is to say, whether any roguelite would also be considered an incremental game.

              The meta-progression of an incremental game could arguably be considered a paradigm shift, and certainly adds some resource management. Goal-oriented would probably also apply. I think anything other than those would be a stretch, and in my opinion that just isn't enough to qualify. To be totally honest, I was never expecting to conclude otherwise though 😉

              Sub-Genres

              There are some trends in incremental games that go beyond just being a commonly used mechanic, such that they deeply affect the rest of the game design. These trends can be used to determine sub-genres within the incremental games umbrella:

              • Cultivation RPGs are a genre of games, books, and anime popular in China that center around being in a fantasy world with characters getting stronger over time. While few of them get translated into English, a fan of incremental games may find the available games interesting.
              - - + + \ No newline at end of file diff --git a/hashmap.json b/hashmap.json index ab942a07f..32b1ca14a 100644 --- a/hashmap.json +++ b/hashmap.json @@ -1 +1 @@ -{"guide-to-incrementals_index.md":"da67c4dd","guide-to-incrementals_ludology_appeal-developers.md":"005a3b47","guide-to-incrementals_ludology_appeal-gamers.md":"1941e23d","guide-to-incrementals_ludology_content.md":"4c4f3543","guide-to-incrementals_ludology_definition.md":"cdcec89a","index.md":"fdd76977","projects_babble_index.md":"75ea61ee","projects_citadel_index.md":"aa08898c","projects_dice_index.md":"5311cd9a","projects_index.md":"c8d3f066","projects_optispeech_index.md":"8f367a68","projects_vecs_index.md":"d11dedb4","public_gamedevtree_2.0-format-changes.md":"447c1832","public_gamedevtree_readme.md":"a20d0a16","public_gamedevtree_changelog.md":"77d8af60","public_gamedevtree_docs_!general-info.md":"a23875ce","public_gamedevtree_docs_achievements.md":"6dd68dae","public_gamedevtree_docs_bars.md":"3acff572","public_gamedevtree_docs_basic-layer-breakdown.md":"86e5c20b","public_gamedevtree_docs_buyables.md":"5db9eaa6","public_gamedevtree_docs_challenges.md":"45577e9f","public_gamedevtree_docs_clickables.md":"e3b0c6fe","public_gamedevtree_docs_custom-tab-layouts.md":"1ea1b7b9","public_gamedevtree_docs_getting-started.md":"bb68ff20","public_gamedevtree_docs_infoboxes.md":"ef434fbf","public_gamedevtree_docs_layer-features.md":"4567b331","public_gamedevtree_docs_main-mod-info.md":"4b087535","public_gamedevtree_docs_milestones.md":"7d661bce","public_gamedevtree_docs_subtabs-and-microtabs.md":"60a1852e","public_gamedevtree_docs_updating-tmt.md":"f6459ce1","public_gamedevtree_docs_upgrades.md":"799f28d0","public_kronos_old things_2.0-format-changes.md":"0dd3e9ad","public_kronos_readme.md":"ecc49558","public_kronos_changelog.md":"01d7b07d","public_kronos_docs_!general-info.md":"e82f5cd3","public_kronos_docs_achievements.md":"9dd93db1","public_kronos_docs_bars.md":"7a2fdc93","public_kronos_docs_basic-layer-breakdown.md":"41933053","public_kronos_docs_buyables.md":"76e7a5af","public_kronos_docs_challenges.md":"c5401b51","public_kronos_docs_clickables.md":"948c09c1","public_kronos_docs_custom-tab-layouts.md":"82768ae7","public_kronos_docs_getting-started.md":"ebf2428d","public_kronos_docs_grids.md":"d18ed46e","public_kronos_docs_infoboxes.md":"29623ec4","public_kronos_docs_layer-features.md":"718ce31d","public_kronos_docs_main-mod-info.md":"05ec401c","public_kronos_docs_milestones.md":"0e514a5c","public_kronos_docs_particles.md":"7b063d3e","public_kronos_docs_subtabs-and-microtabs.md":"93ca2268","public_kronos_docs_trees-and-tree-customization.md":"dde81eb2","public_kronos_docs_updating-tmt.md":"042ac945","public_kronos_docs_upgrades.md":"75a2743b","public_lit_old things_2.0-format-changes.md":"972bc545","public_lit_readme.md":"8aaa72fa","public_lit_changelog.md":"cb7c37fd","public_lit_docs_!general-info.md":"471f7f7d","public_lit_docs_achievements.md":"ca9b928e","public_lit_docs_bars.md":"f547241c","public_lit_docs_basic-layer-breakdown.md":"3f238e7f","public_lit_docs_buyables.md":"0b2481b9","public_lit_docs_challenges.md":"858da2b8","public_lit_docs_clickables.md":"3187e173","public_lit_docs_custom-tab-layouts.md":"387df476","public_lit_docs_getting-started.md":"7dc6e45d","public_lit_docs_infoboxes.md":"2fa00fa8","public_lit_docs_layer-features.md":"15cfeafa","public_lit_docs_main-mod-info.md":"fae12359","public_lit_docs_milestones.md":"d148d9eb","public_lit_docs_subtabs-and-microtabs.md":"64d0692d","public_lit_docs_trees-and-tree-customization.md":"4825432f","public_lit_docs_updating-tmt.md":"8bc0cda6","public_lit_docs_upgrades.md":"9c2674ea"} +{"guide-to-incrementals_index.md":"01643183","guide-to-incrementals_ludology_appeal-developers.md":"2e6312d0","guide-to-incrementals_ludology_appeal-gamers.md":"c0319ea4","guide-to-incrementals_ludology_content.md":"d8a8c68c","guide-to-incrementals_ludology_definition.md":"effc1cd4","index.md":"c05fb4a0","projects_babble_index.md":"db4edec9","projects_citadel_index.md":"ce7d0618","projects_dice_index.md":"c23997d0","projects_index.md":"6cef1a12","projects_optispeech_index.md":"45da3222","projects_vecs_index.md":"40b7a9dc","public_gamedevtree_2.0-format-changes.md":"7cfcce8b","public_gamedevtree_readme.md":"49de9ca0","public_gamedevtree_changelog.md":"7503a901","public_gamedevtree_docs_!general-info.md":"9545d5e0","public_gamedevtree_docs_achievements.md":"bdb26d53","public_gamedevtree_docs_bars.md":"d1e4a476","public_gamedevtree_docs_basic-layer-breakdown.md":"2c1c7779","public_gamedevtree_docs_buyables.md":"3e42223a","public_gamedevtree_docs_challenges.md":"ba285646","public_gamedevtree_docs_clickables.md":"a79f34e0","public_gamedevtree_docs_custom-tab-layouts.md":"3eccc09f","public_gamedevtree_docs_getting-started.md":"6c2239cf","public_gamedevtree_docs_infoboxes.md":"0e07c96e","public_gamedevtree_docs_layer-features.md":"9c5507fe","public_gamedevtree_docs_main-mod-info.md":"166d6aee","public_gamedevtree_docs_milestones.md":"c8e0174f","public_gamedevtree_docs_subtabs-and-microtabs.md":"1d829b17","public_gamedevtree_docs_updating-tmt.md":"cde46630","public_gamedevtree_docs_upgrades.md":"c79ac790","public_kronos_old things_2.0-format-changes.md":"8d55c7ef","public_kronos_readme.md":"7ff4927f","public_kronos_changelog.md":"8fbfea45","public_kronos_docs_!general-info.md":"82616e2a","public_kronos_docs_achievements.md":"bf4e3304","public_kronos_docs_bars.md":"475709df","public_kronos_docs_basic-layer-breakdown.md":"7754454e","public_kronos_docs_buyables.md":"3875aedf","public_kronos_docs_challenges.md":"0712c330","public_kronos_docs_clickables.md":"f12083e3","public_kronos_docs_custom-tab-layouts.md":"cf36269b","public_kronos_docs_getting-started.md":"59f6b8e5","public_kronos_docs_grids.md":"19b800f2","public_kronos_docs_infoboxes.md":"d589fa70","public_kronos_docs_layer-features.md":"abda9a85","public_kronos_docs_main-mod-info.md":"a3be0116","public_kronos_docs_milestones.md":"63041a6e","public_kronos_docs_particles.md":"9405e742","public_kronos_docs_subtabs-and-microtabs.md":"a6c47048","public_kronos_docs_trees-and-tree-customization.md":"4ffd8021","public_kronos_docs_updating-tmt.md":"aa800528","public_kronos_docs_upgrades.md":"666bb565","public_lit_old things_2.0-format-changes.md":"ea048463","public_lit_readme.md":"b961fe43","public_lit_changelog.md":"a5b1cbe9","public_lit_docs_!general-info.md":"a99bbb3e","public_lit_docs_achievements.md":"17232b52","public_lit_docs_bars.md":"9bf52d6a","public_lit_docs_basic-layer-breakdown.md":"de8695ed","public_lit_docs_buyables.md":"8a9beb14","public_lit_docs_challenges.md":"841c1bd9","public_lit_docs_clickables.md":"bff73686","public_lit_docs_custom-tab-layouts.md":"31deefcc","public_lit_docs_getting-started.md":"38cf00c8","public_lit_docs_infoboxes.md":"bf64f36f","public_lit_docs_layer-features.md":"59361922","public_lit_docs_main-mod-info.md":"1d72d9fb","public_lit_docs_milestones.md":"d9f4b140","public_lit_docs_subtabs-and-microtabs.md":"07a92c3c","public_lit_docs_trees-and-tree-customization.md":"4afa4175","public_lit_docs_updating-tmt.md":"3cdc68a8","public_lit_docs_upgrades.md":"45e6f45b"} diff --git a/index.html b/index.html index 81c90967e..dbe696035 100644 --- a/index.html +++ b/index.html @@ -6,8 +6,8 @@ The Paper Pilot | The Paper Pilot - - + + @@ -18,8 +18,8 @@
              Skip to content

              The Paper Pilot

              I'm Anthony, or The Paper Pilot, and I make fun games and tools!

              - - + + \ No newline at end of file diff --git a/projects/babble/index.html b/projects/babble/index.html index 4a96cf605..b8c4a68a8 100644 --- a/projects/babble/index.html +++ b/projects/babble/index.html @@ -6,8 +6,8 @@ Babble Buds | The Paper Pilot - - + + @@ -17,9 +17,9 @@ -
              Skip to content
              On this page

              Babble Buds

              Babble Buds Homepage

              Source Code:

              Babble buds is a free, open-source virtual puppet show software. It is heavily based on the non-public software called "Puppet Pals", used in URealms Live. The software is written in javascript using React, a rendering library called PIXI.js, and electron.

              Users can create puppets with different faces for different emotions, and then use the puppet on a stage where you and other users can each make your respective puppets move, change emotions, and "babble" at each other. The stage has a green screen feature and can be popped out, which gives the users tons of possibilities in terms of using the program for a role-playing live stream, faux video chatting with friends, game development, or whatever else you want!

              Users can connect to the public server and create private rooms so that they and their friends can see each other's puppets and use the software however they please. For the security conscious, you can also use the server's source code to self-host your private server.

              Babble Buds Screenshot

              Engine

              The engine originally made to make the Babble Buds program was separated into a separate engine called babble.js, so that projects created in Babble Buds can be used in other projects. For example, a game can create puppets in Babble Buds and then use them for cutscenes or player agency inside of the game. Additionally, it has been ported to C# (called babble.cs) for use with Unity, for the same kinds of purposes. You can check out Tower Offense for a pixi.js game using Babble Buds puppets for the cutscenes, or Dice Armor for a unity game using Babble Buds puppets for the cutscenes.

              Babble Movie Maker

              Babble Movie Maker is a cutscene editor for Babble Buds puppets. You open a babble buds project in it, and you can add actors to a stage and have them move and change expressions, etc., on a timeline. You can then use the cutscene in a game using babble.js or babble.cs, or export the cutscene into a video file. There is even support for defining custom commands with custom fields, so that if you've expanded upon the default actions provided in babble.js or babble.cs, you can still use Movie Maker to create your cutscenes.

              Babble MM Screenshot

              - - +
              Skip to content
              On this page

              Babble Buds

              Babble Buds Homepage

              Source Code:

              Babble buds is a free, open-source virtual puppet show software. It is heavily based on the non-public software called "Puppet Pals", used in URealms Live. The software is written in javascript using React, a rendering library called PIXI.js, and electron.

              Users can create puppets with different faces for different emotions, and then use the puppet on a stage where you and other users can each make your respective puppets move, change emotions, and "babble" at each other. The stage has a green screen feature and can be popped out, which gives the users tons of possibilities in terms of using the program for a role-playing live stream, faux video chatting with friends, game development, or whatever else you want!

              Users can connect to the public server and create private rooms so that they and their friends can see each other's puppets and use the software however they please. For the security conscious, you can also use the server's source code to self-host your private server.

              Babble Buds Screenshot

              Engine

              The engine originally made to make the Babble Buds program was separated into a separate engine called babble.js, so that projects created in Babble Buds can be used in other projects. For example, a game can create puppets in Babble Buds and then use them for cutscenes or player agency inside of the game. Additionally, it has been ported to C# (called babble.cs) for use with Unity, for the same kinds of purposes. You can check out Tower Offense for a pixi.js game using Babble Buds puppets for the cutscenes, or Dice Armor for a unity game using Babble Buds puppets for the cutscenes.

              Babble Movie Maker

              Babble Movie Maker is a cutscene editor for Babble Buds puppets. You open a babble buds project in it, and you can add actors to a stage and have them move and change expressions, etc., on a timeline. You can then use the cutscene in a game using babble.js or babble.cs, or export the cutscene into a video file. There is even support for defining custom commands with custom fields, so that if you've expanded upon the default actions provided in babble.js or babble.cs, you can still use Movie Maker to create your cutscenes.

              Babble MM Screenshot

              + + \ No newline at end of file diff --git a/projects/citadel/index.html b/projects/citadel/index.html index 55e4b0404..a6ee4d75d 100644 --- a/projects/citadel/index.html +++ b/projects/citadel/index.html @@ -6,8 +6,8 @@ Capture the Citadel | The Paper Pilot - - + + @@ -17,9 +17,9 @@ -
              Skip to content
              On this page

              Capture the Citadel

              A 3D VR re-envisioning of a Slay the Spire-style game by Anthony Lawn and Grant Barbee for their VR class in college's final project.

              For more details, visit Grant's page on the game.

              Screenshot

              - - +
              Skip to content
              On this page

              Capture the Citadel

              A 3D VR re-envisioning of a Slay the Spire-style game by Anthony Lawn and Grant Barbee for their VR class in college's final project.

              For more details, visit Grant's page on the game.

              Screenshot

              + + \ No newline at end of file diff --git a/projects/dice/index.html b/projects/dice/index.html index 9710a94ef..21c399357 100644 --- a/projects/dice/index.html +++ b/projects/dice/index.html @@ -6,8 +6,8 @@ Dice Armor | The Paper Pilot - - + + @@ -17,9 +17,9 @@ -
              Skip to content
              On this page

              Dice Armor

              Download Here

              Dice Armor is a game that started development as a semester-long project by a team of nine: a producer, a creative director, a narrative writer, an artist, two programmers, and 3 game designers. The information here is about my contributions as the lead programmer over the semester because I can show off stuff like the editor scripts I wrote. I was doing everything from interface coding, editor scripts, integrating Babble Buds, and of course, everything related to the gameplay itself. To date I'm still the lead programmer for the game; for more up-to-date information on the current state of the game please visit the official site.

              The build available here was created for showing off at the end of the semester, and as such has some buttons present to make the game easier to skip parts of the game to see all the content: You start with all the dice in the game already in the shop, there's a button to give yourself free money to buy these dice with, and in the duel, there are buttons to force a win or a loss, which can be used to skip the tutorial (not recommended for first-time players).

              Tutorial

              Dice Armor is a dice dueling game. Players can use abilities, flip dice, and attack each other to win in a dice game that puts chance into the hands of the players. This is what the dueling scene looks like, with a tutorial cutscene happening on top to guide the player through the basics. Also, all the dice are constructed dynamically, using quaternion math to figure out the placement of each component relative to the face it is going on. The die in the middle has one of the player' and opponents' portraits on each of its sides.

              Editors

              For many of the objects I've created, I've made scriptable objects so that game designers can add and modify them easily. Additionally, I would create custom inspectors for the objects to help make them as easy to understand and edit as possible. The opponent's artificial intelligence is made up of many strategies, in a prioritized list. When it is the opponents' turn they go through each strategy and check if they can be run, and if so then the opponent performs the strategy and starts back over at the top of the list of strategies. The + sign under the list of strategies opens an organized dropdown of all the various strategies.

              Simulator

              In addition to custom inspector code, I've created new tools for the editor for our game designers to use. This is a duel simulator that will take two opponents and simulate an arbitrary number of duels between them, and output the results and summarize them for you, much much quicker than manually going through the duels, even with an absurdly high timeScale. This will become incredibly useful in making balance changes and testing new dice against existing sets. This is a screenshot of it in edit mode, but in play mode it removes the "Dueling Managers" field and will use whatever the current duel balance settings are, allowing for the GDs to test freely in play mode without worrying about undoing all their changes afterward.

              Cutscene

              I created the Babble Buds puppet editor and ported the rendering library I wrote for it to C# so it could be used in Unity. Dice Armor has a full campaign using cutscenes made using the Babble Buds cutscene editor, taking advantage of its support for custom commands and fields to control things like talking, giving the player dice and money, starting duels, and controlling player progression through the story.

              Action Wheel

              When a cutscene ends, its final command is to either start a duel or set the next cutscene in the story. In the latter case, there is an additional field for what to call the next cutscene, and what location it takes place. The cutscene is then added to the player's save file, and when they visit the city locations are greyed out until they have at least one action to do there. Each location has a dynamically populated action wheel with a custom range of acceptable angles.

              Shop

              The dice shop is dynamically populated by a list of dice available to the player, which can be changed during cutscenes, and is checked against the dice owned by the player to generate sold-out indicators. On the left, the player can choose to filter the options down to a single dice effect, which also updates the "Buy All" button to buy only all the dice in the current filter.

              Inventory

              The inventory works most the same as the shop, but for equipping dice. It also allows you to drag individual dice or entire sets to the equipped dice glyph. While dragging it will highlight all the slots the new dice will be equipped into.

              Dice Rolling

              The dice rolling uses the physics engine and detects once the dice have stopped moving, then determines which side is face up based on which of the normals is closest to straight up. It flags the die as cocked if that smallest angle is above a threshold. The dice sink into the table when not rolling to not interfere with any dice that are rolling.

              Missile Storm

              During certain events like winning the game or having the face of a die broken, the players' portraits will flash an emotion for a second. After winning, a random living die from the winning player is chosen to play their "finisher move", a flashy and dramatic effect to end the game. Shown is the arcane mechana's finisher, "Missile Storm".

              - - +
              Skip to content
              On this page

              Dice Armor

              Download Here

              Dice Armor is a game that started development as a semester-long project by a team of nine: a producer, a creative director, a narrative writer, an artist, two programmers, and 3 game designers. The information here is about my contributions as the lead programmer over the semester because I can show off stuff like the editor scripts I wrote. I was doing everything from interface coding, editor scripts, integrating Babble Buds, and of course, everything related to the gameplay itself. To date I'm still the lead programmer for the game; for more up-to-date information on the current state of the game please visit the official site.

              The build available here was created for showing off at the end of the semester, and as such has some buttons present to make the game easier to skip parts of the game to see all the content: You start with all the dice in the game already in the shop, there's a button to give yourself free money to buy these dice with, and in the duel, there are buttons to force a win or a loss, which can be used to skip the tutorial (not recommended for first-time players).

              Tutorial

              Dice Armor is a dice dueling game. Players can use abilities, flip dice, and attack each other to win in a dice game that puts chance into the hands of the players. This is what the dueling scene looks like, with a tutorial cutscene happening on top to guide the player through the basics. Also, all the dice are constructed dynamically, using quaternion math to figure out the placement of each component relative to the face it is going on. The die in the middle has one of the player' and opponents' portraits on each of its sides.

              Editors

              For many of the objects I've created, I've made scriptable objects so that game designers can add and modify them easily. Additionally, I would create custom inspectors for the objects to help make them as easy to understand and edit as possible. The opponent's artificial intelligence is made up of many strategies, in a prioritized list. When it is the opponents' turn they go through each strategy and check if they can be run, and if so then the opponent performs the strategy and starts back over at the top of the list of strategies. The + sign under the list of strategies opens an organized dropdown of all the various strategies.

              Simulator

              In addition to custom inspector code, I've created new tools for the editor for our game designers to use. This is a duel simulator that will take two opponents and simulate an arbitrary number of duels between them, and output the results and summarize them for you, much much quicker than manually going through the duels, even with an absurdly high timeScale. This will become incredibly useful in making balance changes and testing new dice against existing sets. This is a screenshot of it in edit mode, but in play mode it removes the "Dueling Managers" field and will use whatever the current duel balance settings are, allowing for the GDs to test freely in play mode without worrying about undoing all their changes afterward.

              Cutscene

              I created the Babble Buds puppet editor and ported the rendering library I wrote for it to C# so it could be used in Unity. Dice Armor has a full campaign using cutscenes made using the Babble Buds cutscene editor, taking advantage of its support for custom commands and fields to control things like talking, giving the player dice and money, starting duels, and controlling player progression through the story.

              Action Wheel

              When a cutscene ends, its final command is to either start a duel or set the next cutscene in the story. In the latter case, there is an additional field for what to call the next cutscene, and what location it takes place. The cutscene is then added to the player's save file, and when they visit the city locations are greyed out until they have at least one action to do there. Each location has a dynamically populated action wheel with a custom range of acceptable angles.

              Shop

              The dice shop is dynamically populated by a list of dice available to the player, which can be changed during cutscenes, and is checked against the dice owned by the player to generate sold-out indicators. On the left, the player can choose to filter the options down to a single dice effect, which also updates the "Buy All" button to buy only all the dice in the current filter.

              Inventory

              The inventory works most the same as the shop, but for equipping dice. It also allows you to drag individual dice or entire sets to the equipped dice glyph. While dragging it will highlight all the slots the new dice will be equipped into.

              Dice Rolling

              The dice rolling uses the physics engine and detects once the dice have stopped moving, then determines which side is face up based on which of the normals is closest to straight up. It flags the die as cocked if that smallest angle is above a threshold. The dice sink into the table when not rolling to not interfere with any dice that are rolling.

              Missile Storm

              During certain events like winning the game or having the face of a die broken, the players' portraits will flash an emotion for a second. After winning, a random living die from the winning player is chosen to play their "finisher move", a flashy and dramatic effect to end the game. Shown is the arcane mechana's finisher, "Missile Storm".

              + + \ No newline at end of file diff --git a/projects/index.html b/projects/index.html index 4ee28b1f0..6c141be1e 100644 --- a/projects/index.html +++ b/projects/index.html @@ -6,8 +6,8 @@ Projects | The Paper Pilot - - + + @@ -17,9 +17,9 @@ -
              Skip to content
              On this page

              Games!

              I make games regularly! Check them out in the sidebar or on my itch.io page.

              Profectus!

              I contributed to a modding framework called The Modding Tree and then made Profectus as an alternative that gives developers more control. Profectus is a game engine for the web that uses TS and Vue.

              V-ecs!

              V-ecs (pronounced "Vex") is a Vulkan-based engine I made for making highly moddable games and tools in Lua centered around the ECS design pattern and a work-stealing job system.

              OptiSpeech!

              I led a team updating a legacy Unity project for research on speech therapy to use a modern version with a focus on extensibility to facilitate future maintenance and features.

              Babble Buds!

              Babble Buds is a free, open-source virtual puppet show engine I made for various platforms including HTLM5 and Unity, as well as an accompanying electron-based puppet editor and multiplayer stage.

              Dice Armor

              I was the lead programmer on a team of nine creating this game in a semester-long college course. I programmed all the gameplay systems as well as incorporated Babble Buds for the cutscenes and tutorial.

              Capture the Citadel

              A 3D VR re-envisioning of a Slay the Spire-style game by Anthony Lawn and Grant Barbee.

              - - +
              Skip to content
              On this page

              Games!

              I make games regularly! Check them out in the sidebar or on my itch.io page.

              Profectus!

              I contributed to a modding framework called The Modding Tree and then made Profectus as an alternative that gives developers more control. Profectus is a game engine for the web that uses TS and Vue.

              V-ecs!

              V-ecs (pronounced "Vex") is a Vulkan-based engine I made for making highly moddable games and tools in Lua centered around the ECS design pattern and a work-stealing job system.

              OptiSpeech!

              I led a team updating a legacy Unity project for research on speech therapy to use a modern version with a focus on extensibility to facilitate future maintenance and features.

              Babble Buds!

              Babble Buds is a free, open-source virtual puppet show engine I made for various platforms including HTLM5 and Unity, as well as an accompanying electron-based puppet editor and multiplayer stage.

              Dice Armor

              I was the lead programmer on a team of nine creating this game in a semester-long college course. I programmed all the gameplay systems as well as incorporated Babble Buds for the cutscenes and tutorial.

              Capture the Citadel

              A 3D VR re-envisioning of a Slay the Spire-style game by Anthony Lawn and Grant Barbee.

              + + \ No newline at end of file diff --git a/projects/optispeech/index.html b/projects/optispeech/index.html index 5f4d29df9..42904ed38 100644 --- a/projects/optispeech/index.html +++ b/projects/optispeech/index.html @@ -6,8 +6,8 @@ OptiSpeech | The Paper Pilot - - + + @@ -17,9 +17,9 @@ -
              Skip to content
              On this page

              OptiSpeech

              The Optispeech project involves designing and testing a real-time tongue model that can be viewed in a transparent head while a subject talks — for the purposes of treating speech errors and teaching foreign language sounds. This work has been conducted in partnership with Vulintus and with support from the National Institutes of Health (NIH). The UT Dallas Speech Production Lab is currently updating the program to use updated versions of Unity and adding support for more features and hardware.

              System Architecture

              This video shows a talker with WAVE sensors placed on the tongue hitting a virtual target sphere located at the alveolar ridge. When an alveolar consonant is hit (e.g., /s/, /n/, /d/) the sphere changes color from red to green.

              This video shows an American talker learning a novel sound not found in English. When the post-alveolar consonant is hit, the target sphere changes color from red to green. Here, the NDI WAVE system serves as input.

              The program is being updated by a team in the UT Dallas Speech Production Lab led by Anthony Lawn, so the program uses a more modern version of Unity, has an easier-to-use interface, can more easily support new features, and can connect to additional EMA systems, namely the Carstens AG501.

              New Interface

              In addition, the program now includes documentation and unit tests to improve program stability and maintainability going forward.

              Documentation

              Unit Tests

              - - +
              Skip to content
              On this page

              OptiSpeech

              The Optispeech project involves designing and testing a real-time tongue model that can be viewed in a transparent head while a subject talks — for the purposes of treating speech errors and teaching foreign language sounds. This work has been conducted in partnership with Vulintus and with support from the National Institutes of Health (NIH). The UT Dallas Speech Production Lab is currently updating the program to use updated versions of Unity and adding support for more features and hardware.

              System Architecture

              This video shows a talker with WAVE sensors placed on the tongue hitting a virtual target sphere located at the alveolar ridge. When an alveolar consonant is hit (e.g., /s/, /n/, /d/) the sphere changes color from red to green.

              This video shows an American talker learning a novel sound not found in English. When the post-alveolar consonant is hit, the target sphere changes color from red to green. Here, the NDI WAVE system serves as input.

              The program is being updated by a team in the UT Dallas Speech Production Lab led by Anthony Lawn, so the program uses a more modern version of Unity, has an easier-to-use interface, can more easily support new features, and can connect to additional EMA systems, namely the Carstens AG501.

              New Interface

              In addition, the program now includes documentation and unit tests to improve program stability and maintainability going forward.

              Documentation

              Unit Tests

              + + \ No newline at end of file diff --git a/projects/vecs/index.html b/projects/vecs/index.html index 14e743642..1279c332d 100644 --- a/projects/vecs/index.html +++ b/projects/vecs/index.html @@ -6,8 +6,8 @@ V-ecs | The Paper Pilot - - + + @@ -17,9 +17,9 @@ -
              Skip to content
              On this page

              V-ecs

              V-ecs Screenshot

              V-ecs (pronounced "Vex") is a Vulkan-based engine I made for making highly moddable games and tools in Lua centered around the ECS design pattern and a work-stealing job system.

              The engine works with "worlds", which are collections of systems and renderers. The engine comes with several worlds using systems and renderers I made, including a voxel world, an incremental game, and some test scenes. All of these include systems to render the fps as well as show a debug console by typing the grave key (`). The default world is a title screen that detects any worlds in the "worlds" folder and displays a button for each of them.

              Debug Menu

              The original plans were to eventually put it on the steam workshop so people could more easily share their creations amongst each other, but I never became happy enough with the performance of the engine - the parallelization of the lua code involved a lot of overhead that severely limited performance.

              Instead, I made a couple of worlds by myself - an infinite procedurally generated voxel world, a simple incremental game, and a more complex incremental game I call "Sands of Time".

              Sands of Time

              - - +
              Skip to content
              On this page

              V-ecs

              V-ecs Screenshot

              V-ecs (pronounced "Vex") is a Vulkan-based engine I made for making highly moddable games and tools in Lua centered around the ECS design pattern and a work-stealing job system.

              The engine works with "worlds", which are collections of systems and renderers. The engine comes with several worlds using systems and renderers I made, including a voxel world, an incremental game, and some test scenes. All of these include systems to render the fps as well as show a debug console by typing the grave key (`). The default world is a title screen that detects any worlds in the "worlds" folder and displays a button for each of them.

              Debug Menu

              The original plans were to eventually put it on the steam workshop so people could more easily share their creations amongst each other, but I never became happy enough with the performance of the engine - the parallelization of the lua code involved a lot of overhead that severely limited performance.

              Instead, I made a couple of worlds by myself - an infinite procedurally generated voxel world, a simple incremental game, and a more complex incremental game I call "Sands of Time".

              Sands of Time

              + + \ No newline at end of file diff --git a/public/gamedevtree/2.0-format-changes/index.html b/public/gamedevtree/2.0-format-changes/index.html index fa27c9bee..b329571d2 100644 --- a/public/gamedevtree/2.0-format-changes/index.html +++ b/public/gamedevtree/2.0-format-changes/index.html @@ -6,8 +6,8 @@ 2.0 format changes | The Paper Pilot - - + + @@ -18,8 +18,8 @@
              Skip to content
              On this page

              2.0 format changes

              • Temp format is changed from temp.something[layer] to temp[layer].something, for consistency
              • Challenges are now saved as an object with the amount of completions in each spot. (This will break saves.)
              • effectDisplay in Challenges and Upgrades no longer takes an argument, and neither does effect for Buyables
              • Buyable cost can take an argument for amount of buyables, but it needs to function if no argument is supplied (it should do the cost for the next purchase).
              • Generation of Points now happens in the main game loop (not in a layer update function), enabled by canGenPoints in game.js.
              • Changed fullLayerReset to layerDataReset, which takes an array of names of values to keep

              In addition, many names were changed, mostly expanding abbreviations:

              All instances of:

              • chall -> challenge
              • unl -> unlocked
              • upg -> upgrade (besides CSS)
              • amt -> amount
              • desc -> description
              • resCeil -> roundUpCost
              • order -> unlockOrder
              • incr_order -> increaseUnlockOrder

              Challenges:

              • desc -> challengeDescription
              • reward -> rewardDescription
              • effect -> rewardEffect
              • effectDisplay -> rewardDisplay
              • active -> challengeActive
              - - + + \ No newline at end of file diff --git a/public/gamedevtree/README/index.html b/public/gamedevtree/README/index.html index 83bc856a3..8788c3b0d 100644 --- a/public/gamedevtree/README/index.html +++ b/public/gamedevtree/README/index.html @@ -6,8 +6,8 @@ The-Modding-Tree | The Paper Pilot - - + + @@ -18,8 +18,8 @@
              Skip to content
              On this page

              The-Modding-Tree

              A modified version of The Prestige Tree that is much easier to mod. It still requires programming knowledge, but it's mostly pretty easy things and copy/pasting.

              Look here for a tutorial on getting started with modding with TMT

              You can look in the documentation for more information on how it all works, or look at the code in layers.js to see what it all looks like.

              - - + + \ No newline at end of file diff --git a/public/gamedevtree/changelog/index.html b/public/gamedevtree/changelog/index.html index 51aee9c7b..3e821e446 100644 --- a/public/gamedevtree/changelog/index.html +++ b/public/gamedevtree/changelog/index.html @@ -6,8 +6,8 @@ The Game Dev Tree changelog: | The Paper Pilot - - + + @@ -18,8 +18,8 @@
              Skip to content
              On this page

              The Game Dev Tree changelog:

              v1.0.4 Version Bump [rebalanced,debuggedx3] - 2020-11-09

              • Fixed refactorings 2, 3, and 4 not actually affecting productivity

              v1.0.3 Version Bump [rebalanced,debuggedx2] - 2020-11-08

              • Fixed API milestone 4 not working

              v1.0.2 Version Bump [rebalanced,debugged] - 2020-11-08

              • Fixed tree lines being hidden after hitting "keepGoing" in the victory screen

              v1.0.1 Version Bump [rebalanced] - 2020-11-08

              • Buffed several TAs

              v1.0 Version Bump - 2020-11-08

              • Finished row 4
              • Added colored text to lore
              • Fixed some visual bugs with milestones
              • Probably other stuff lol its been a week

              v0.2.3 Stylish - 2020-10-30

              • Re-styled basically everything
              • Added favicon
              • Added header bar
              • Added changelog

              v0.2.2 Row 3 - 2020-10-22

              • Removed debug statement
              • Moved milestones in F layer beneath the buyables

              v0.2.1 Row 3 - 2020-10-21

              • Fixed layers hiding
              • Fixed typos/minor issues
              • Fixed S layer being highlighted before you can unlock the layer

              v0.2 Row 3 - 2020-10-21

              • Implemented row 3

              v0.1.1 Cash Influx [rebalanced] - 2020-10-19

              • Fixed notification issue
              • Rebalanced to make early game faster and late game slower
              • Fixed other minor issues

              v0.1 Cash Influx - 2020-10-19

              • Implemented row 2

              v0.0 Initial Commit - 2020-10-18

              • Implemented row 1
              - - + + \ No newline at end of file diff --git a/public/gamedevtree/docs/!general-info/index.html b/public/gamedevtree/docs/!general-info/index.html index dcd84abad..214c1f0a8 100644 --- a/public/gamedevtree/docs/!general-info/index.html +++ b/public/gamedevtree/docs/!general-info/index.html @@ -6,8 +6,8 @@ The-Modding-Tree | The Paper Pilot - - + + @@ -18,8 +18,8 @@
              Skip to content
              On this page

              The-Modding-Tree

              The main way to add content is through creating layers. You can either add a layer directly in the layers object in layersSupportjs, or declare it in another file and then do "addLayer(layername, layerdata)" (good for breaking things up into smaller files). The existing layers are just examples and can be freely deleted. You can also use them as references and a base for your own layers.

              The first thing you need to do is to edit the modInfo at the top of game.js to set your modID (a string). A unique modId will prevent your mod's saves from conflicting with other mods.

              Most of the time, you won't need to dive deep into the code to create things, but you still can if you really want to.

              The Modding Tree uses break_eternity.js to store large values. This means that many numbers are Decimal objects, and must be treated differently. For example, you have to use new Decimal(x) to create a Decimal value instead of a plain number, and perform operations on them by calling functions. e.g, instead of x = x + y, use x = x.add(y).

              Almost all values can be either a constant value, or a dynamic value. Dynamic values are defined by putting a function that returns what the value should be at any given time.

              All display text can be basic HTML instead (But you can't use most Vue features there).

              Table of Contents:

              General:

              • Getting Started: Getting your own copy of the code set up with Github Desktop.
              • Main mod info: How to set up general things for your mod in mod.js.
              • Basic layer breakdown: Breaking down the components of a layer with minimal features.
              • Layer features: Explanations of all of the different properties that you can give a layer.
              • Custom Tab Layouts: An optional way to give your tabs a different layout. You can even create entirely new components to use.
              • Updating TMT: Using Github Desktop to update your mod's version of TMT.

              Common components

              • Upgrades: How to create upgrades for a layer.
              • Milestones: How to create milestones for a layer.
              • Buyables: Create rebuyable upgrades for your layer (with the option to make them respec-able). Can be used to make Enhancers or Space Buildings.
              • Clickables: A more generalized variant of buyables, for any kind of thing that is sometimes clickable. Between these and Buyables, you can do just about anything.

              Other components

              • Challenges: How to create challenges for a layer.
              • Bars: Display some information as a progress bar, gague, or similar. They are highly customizable, and can be horizontal and vertical as well.
              • Subtabs and Microtabs: Create subtabs for your tabs, as well as "microtab" components that you can put inside the tabs.
              • Achievements: How to create achievements for a layer (or for the whole game).
              • Infoboxes: Boxes containing text that can be shown or hidden.
              - - + + \ No newline at end of file diff --git a/public/gamedevtree/docs/achievements/index.html b/public/gamedevtree/docs/achievements/index.html index 3d2de0aa0..8e339bd82 100644 --- a/public/gamedevtree/docs/achievements/index.html +++ b/public/gamedevtree/docs/achievements/index.html @@ -6,8 +6,8 @@ Achievements | The Paper Pilot - - + + @@ -27,8 +27,8 @@ etc }

              Each achievement should have an id where the first digit is the row and the second digit is the column. Individual achievement can have these features:

              • name: optional, displayed at the top of the achievement. The only visible text. It can also be a function that returns updating text. Can use basic HTML.

              • done(): A function returning a boolean to determine if the achievement should be awarded.

              • tooltip: Default tooltip for the achievement, appears when it is hovered over. Should convey the goal and any reward for completing the achievement. It can also be a function that returns updating text. Can use basic HTML.

              • effect(): optional, A function that calculates and returns the current values of any bonuses from the achievement. Can return a value or an object containing multiple values.

              • unlocked(): optional, A function returning a bool to determine if the achievement is visible or not. Default is unlocked.

              • onComplete() - optional, this function will be called when the achievement is completed.

              • style: Optional, Applies CSS to this achievement, in the form of an object where the keys are CSS attributes, and the values are the values for those attributes (both as strings)

              • layer: Assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar

              • id: Assigned automagically. It's the "key" which the achievement was stored under, for convenient access. The achievement in the example's id is 11.

              • goalTooltip: optional, depracated Appears when the achievement is hovered over and locked, overrides the basic tooltip. This is to display the goal (or a hint). It can also be a function that returns updating text. Can use basic HTML.

              • doneTooltip: optional, depracated Appears when the achievement is hovered over and completed, overrides the basic tooltip. This can display what the player achieved (the goal), and the rewards, if any. It can also be a function that returns updating text. Can use basic HTML.

              - - + + \ No newline at end of file diff --git a/public/gamedevtree/docs/bars/index.html b/public/gamedevtree/docs/bars/index.html index 5978f61c3..21dbcf387 100644 --- a/public/gamedevtree/docs/bars/index.html +++ b/public/gamedevtree/docs/bars/index.html @@ -6,8 +6,8 @@ Bars | The Paper Pilot - - + + @@ -25,8 +25,8 @@ etc }

            Features:

            • direction: UP, DOWN, LEFT, or RIGHT (not Strings). Determines the direction that the bar is filled as it progresses. RIGHT means from left to right.

            • width, height: The size in pixels of the bar, but as Numbers (no "px" at the end)

            • progress(): A function that returns the portion of the bar that is filled, from "empty" at 0 to "full" at 1. (Nothing bad happens if the value goes out of these bounds, and it can be a number or Decimal).

            • display(): optional, A function that returns text to be displayed on top of the bar, can use HTML.

            • unlocked(): optional, A function returning a bool to determine if the bar is visible or not. Default is unlocked.

            • baseStyle, fillStyle, borderStyle, textStyle: Optional, Apply CSS to the unfilled portion, filled portion, border, and display text on the bar, in the form of an object where the keys are CSS attributes, and the values are the values for those attributes (both as strings).

            • layer: Assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar

            • id: Assigned automagically. It's the "key" which the bar was stored under, for convenient access. The bar in the example's id is "bigBar".

          - - + + \ No newline at end of file diff --git a/public/gamedevtree/docs/basic-layer-breakdown/index.html b/public/gamedevtree/docs/basic-layer-breakdown/index.html index 372c4adbe..8d3c22832 100644 --- a/public/gamedevtree/docs/basic-layer-breakdown/index.html +++ b/public/gamedevtree/docs/basic-layer-breakdown/index.html @@ -6,8 +6,8 @@ Basic layer breakdown | The Paper Pilot - - + + @@ -46,8 +46,8 @@ layerShown() {return true}, // Returns a bool for if this layer's node should be visible in the tree. },
          - - + + \ No newline at end of file diff --git a/public/gamedevtree/docs/buyables/index.html b/public/gamedevtree/docs/buyables/index.html index d5569240f..85bd75fc2 100644 --- a/public/gamedevtree/docs/buyables/index.html +++ b/public/gamedevtree/docs/buyables/index.html @@ -6,8 +6,8 @@ Buyables | The Paper Pilot - - + + @@ -32,8 +32,8 @@ etc }

          Features:

          • title: optional, displayed at the top in a larger font It can also be a function that returns updating text.

          • cost(): cost for buying the next buyable. Can have an optional argument "x" to calculate the cost of the x+1th object, but needs to use "current amount" as a default value for x. (x is a Decimal). Can return an object if there are multiple currencies.

          • effect(): optional, A function that calculates and returns the current values of bonuses of this buyable. Can return a value or an object containing multiple values.

          • display(): A function returning everything that should be displayed on the buyable after the title, likely including the description, amount bought, cost, and current effect. Can use basic HTML.

          • unlocked(): optional, A function returning a bool to determine if the buyable is visible or not. Default is unlocked.

          • canAfford(): A function returning a bool to determine if you can buy one of the buyables.

          • buy(): A function that implements buying one of the buyable, including spending the currency.

          • buyMax(): optional, A function that implements buying as many of the buyable as possible.

          • style: Optional, Applies CSS to this buyable, in the form of an object where the keys are CSS attributes, and the values are the values for those attributes (both as strings)

          • layer: Assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar

          • id: Assigned automagically. It's the "key" which the buyable was stored under, for convenient access. The buyable in the example's id is 11.

          Sell One/Sell All:

          Including a sellOne or sellAll function will cause an additional button to appear beneath the buyable. They are functionally identical, but "sell one" appears above "sell all". You can also use them for other things.

          sellOne/sellAll(): optional, Called when the button is pressed. The standard use would be to decrease/reset the amount of the buyable, And possibly return some currency to the player.

          canSellOne/canSellAll(): optional, booleans determining whether or not to show the buttons. If "canSellOne/All" is absent but "sellOne/All" is present, the appropriate button will always show.

        - - + + \ No newline at end of file diff --git a/public/gamedevtree/docs/challenges/index.html b/public/gamedevtree/docs/challenges/index.html index 569095286..6dbeaf20b 100644 --- a/public/gamedevtree/docs/challenges/index.html +++ b/public/gamedevtree/docs/challenges/index.html @@ -6,8 +6,8 @@ Challenges | The Paper Pilot - - + + @@ -27,8 +27,8 @@ etc }

      Each challenge should have an id where the first digit is the row and the second digit is the column. Individual Challenges can have these features:

      • name: Name of the challenge, can be a string or a function. Can use basic HTML.

      • challengeDescription: A description of what makes the challenge a challenge. You will need to implement these elsewhere It can also be a function that returns updating text. Can use basic HTML.

      • rewardDescription: A description of the reward's effect. You will also have to implement the effect where it is applied. It can also be a function that returns updating text. Can use basic HTML.

      • rewardEffect(): optional, A function that calculates and returns the current values of any bonuses from the reward. Can return a value or an object containing multiple values. Can use basic HTML.

      • rewardDisplay(): optional, A function that returns a display of the current effects of the reward with formatting. Default behavior is to just display the a number appropriately formatted.

      • goal: A Decimal for the amount of currency required to beat the challenge. By default, the goal is in basic Points. The goal can also be a function if its value changes.

      • unlocked(): optional, A function returning a bool to determine if the challenge is visible or not. Default is unlocked.

      • onComplete() - optional, this function will be called when the challenge is completed when previously incomplete.

      • countsAs: optional, If a challenge combines the effects of other challenges in this layer, you can use this. An array of challenge ids. The player is effectively in all of those challenges when in the current one.

      By default, challenges use basic Points for the goal. You can change that using these features.

      • currencyDisplayName: optional, the name to display for the currency for the goal

      • currencyInternalName: optional, the internal name for that currency

      • currencyLayer: optional, the internal name of the layer that currency is stored in. If it's not in a layer, omit. If it's not stored directly in a layer, instead use the next feature.

      • currencyLocation: optional, if your currency is stored in something inside a layer (e.g. a buyable's amount), you can access it this way. This is a function returning the object in "player" that contains the value (like player[this.layer].buyables)

      • completionLimit: optional, the amount of times you can complete this challenge. Default is 1 completion.

      • style: Optional, Applies CSS to this challenge, in the form of an object where the keys are CSS attributes, and the values are the values for those attributes (both as strings)

      • layer: Assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar

      • id: Assigned automagically. It's the "key" which the challenge was stored under, for convenient access. The challenge in the example's id is 11.

      - - + + \ No newline at end of file diff --git a/public/gamedevtree/docs/clickables/index.html b/public/gamedevtree/docs/clickables/index.html index 1e442f8ab..4ef69f7cf 100644 --- a/public/gamedevtree/docs/clickables/index.html +++ b/public/gamedevtree/docs/clickables/index.html @@ -6,8 +6,8 @@ Clickables | The Paper Pilot - - + + @@ -31,8 +31,8 @@ etc }

      Features:

      • title: optional, displayed at the top in a larger font It can also be a function that returns updating text.

      • effect(): optional, A function that calculates and returns the current values of bonuses of this clickable. Can return a value or an object containing multiple values.

      • display(): A function returning everything that should be displayed on the clickable after the title, likely changing based on its state. Can use basic HTML.

      • unlocked(): optional, A function returning a bool to determine if the clickable is visible or not. Default is unlocked.

      • canClick(): A function returning a bool to determine if you can click the clickable.

      • onClick(): A function that implements clicking one of the clickable.

      • style: Optional, Applies CSS to this clickable, in the form of an object where the keys are CSS attributes, and the values are the values for those attributes (both as strings)

      • layer: Assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar.

      • id: Assigned automagically. It's the "key" which the clickable was stored under, for convenient access. The clickable in the example's id is 11.

      - - + + \ No newline at end of file diff --git a/public/gamedevtree/docs/custom-tab-layouts/index.html b/public/gamedevtree/docs/custom-tab-layouts/index.html index 9247fe7d6..69ba87292 100644 --- a/public/gamedevtree/docs/custom-tab-layouts/index.html +++ b/public/gamedevtree/docs/custom-tab-layouts/index.html @@ -6,8 +6,8 @@ Custom tab layouts | The Paper Pilot - - + + @@ -27,8 +27,8 @@ ["toggle", ["c", "beep"]], "milestones", "blank", "blank", "upgrades"]

      It is a list of components, which can be either just a name, or an array with arguments. If it's an array, the first item is the name of the component, the second is the data passed into it, and the third (optional) applies a CSS style to it with a "CSS object", where the keys are CSS attributes.

      These are the existing components, but you can create more in v.js:

      • display-text: Displays some text (can use basic HTML). The argument is the text to display. It can also be a function that returns updating text.

      • raw-html: Displays some basic HTML, can also be a function.

      • blank: Adds empty space. The default dimensions are 8px x 17px. The argument changes the dimensions. If it's a single value (e.g. "20px"), that determines the height. If you have a pair of arguments, the first is width and the second is height.

      • row: Display a list of components horizontally. The argument is an array of components in the tab layout format.

      • column: Display a list of components vertically. The argument is an array of components in the tab layout format. This is useful to display columns within a row.

      • main-display: The text that displays the main currency for the layer and its effects.

      • resource-display: The text that displays the currency that this layer is based on, as well as the best and/or total values for this layer's prestige currency (if they are put in startData for this layer)

      • prestige-button: The argument is a string that the prestige button should say before the amount of currency you will gain. It can also be a function that returns updating text.

      • upgrades, milestones, challs, achievements: Display the upgrades, milestones, and challenges for a layer, as appropriate.

      • buyables, clickables: Display all of the buyables/clickables for this layer, as appropriate. The argument optional, and is the size of the boxes in pixels.

      • microtabs: Display a set of subtabs for an area. The argument is the name of the set of microtabs in the "microtabs" feature.

      • bar: Display a bar. The argument is the id of the bar to display.

      • infobox: Display an infobox. The argument is the id of the infobox to display.

      • toggle: A toggle button that toggles a bool value. The data is a pair that identifies what bool to toggle, [layer, id]

      The rest of the components are sub-components. They can be used just like other components, but are typically part of another component.

      • upgrade, milestone, chall, buyable, clickable, achievement: An individual upgrade, challenge, etc. The argument is the id. This can be used if you want to have upgrades split up across multiple subtabs, for example.

      • respec-button, master-button: The respec and master buttons for buyables and clickables, respectively.

      • sell-one, sell-all: The "sell one" and "sell all" for buyables, respectively. The argument is the id of the buyable.

- - + + \ No newline at end of file diff --git a/public/gamedevtree/docs/getting-started/index.html b/public/gamedevtree/docs/getting-started/index.html index d7685c92c..cafbe111b 100644 --- a/public/gamedevtree/docs/getting-started/index.html +++ b/public/gamedevtree/docs/getting-started/index.html @@ -6,8 +6,8 @@ Getting started | The Paper Pilot - - + + @@ -18,8 +18,8 @@
Skip to content
On this page

Getting started

Welcome to The Modding Tree!

Using the Modding Tree, at its simplest level, just requires getting a copy of it onto your computer. However, if you do it the right way, it will help in many ways.

Don't let the word "Github" scare you away. It's actually much easier to use than most people think, especially because most people use it the hard way. The key is Github Desktop, which lets you do everything you need to, without even touching the command line.

The benefits of using Github:

  • It makes it much, much easier to update The Modding Tree.
  • You can share your work without any extra effort using githack, or with a bit more effort, set up a github.io site.
  • It lets you undo changes to your code, and to have multiple versions of it.
  • It lets you collaborate with other people, if you want to.

Getting set up with Github and The Modding Tree:

  1. Install Github Desktop and Visual Studio Code.

  2. Make a Github account. You can handle this on your own.

  3. Log in on your browser, and go back to The Modding Tree page. At the top right, there should be a button that says "fork". Click on it, and then on your username. You now have your own fork, or copy, of The Modding Tree.

  4. Open Github Desktop and log in. Ignore everything else and choose "clone a repository". A "repository" is basically a "Github project", like The Modding Tree. "Cloning" is downloading a copy of the repository to your computer.

  5. Look for The Modding Tree in the list of repositiories (it should be the only one) and click "clone".

  6. Select that you're using it for your own purposes, and click continue. It will download the files and handle everything.

Using your repository

  1. Click on "show in finder" to the right, and then open index.html. This will let you view and test your project!

  2. To edit your project, click "open in VSCode" in Github Desktop.

  3. Open mod.js in VSCode, and look at the top part where it says "modInfo". On the lines below that, change the mod's name to whatever you want, and change the id as well. (It can be any string value, and it's used to determine where the savefile is. Make it something that's probably unique, and don't change it again later.)

  4. Save game.js, and then reload index.html. The title on the tab, as well as on the info page, will now be the new ones!

  5. Go back to Github Desktop. It's time to save your changes into the git system by making a "commit".

  6. At the bottom right corner, add a summary of your changes, and then click "commit to master".

  7. Finally, at the top middle, click "push origin" to push your changes out onto the online repository.

  8. You can view your project on line, or share it with others, by going to https://raw.githack.com/[YOUR-GITHUB-USERNAME]/The-Modding-Tree/master/index.html

And now, you have successfully used Github! You can look at the documentation to see how The Modding Tree's system works and to make your mod a reality.

- - + + \ No newline at end of file diff --git a/public/gamedevtree/docs/infoboxes/index.html b/public/gamedevtree/docs/infoboxes/index.html index 8a78b6383..f9134f46e 100644 --- a/public/gamedevtree/docs/infoboxes/index.html +++ b/public/gamedevtree/docs/infoboxes/index.html @@ -6,8 +6,8 @@ Infoboxes | The Paper Pilot - - + + @@ -25,8 +25,8 @@ etc }

Features:

  • title: The text displayed above the main box. Can be a function to be dynamic, and can use basic HTML.

  • body: The text displayed inside the box. Can be a function to be dynamic, and can use basic HTML.

  • style, titleStyle, bodyStyle: Optional, Apply CSS to the infobox, or to the title button or body of the infobox, in the form of an object where the keys are CSS attributes, and the values are the Values for those attributes (both as strings).

  • unlocked(): optional, A function returning a bool to determine if the infobox is visible or not. Default is unlocked.

  • layer: Assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar

  • id: Assigned automagically. It's the "key" which the bar was stored under, for convenient access. The bar in the example's id is "bigBar".

- - + + \ No newline at end of file diff --git a/public/gamedevtree/docs/layer-features/index.html b/public/gamedevtree/docs/layer-features/index.html index 36ddf1174..1d83528fd 100644 --- a/public/gamedevtree/docs/layer-features/index.html +++ b/public/gamedevtree/docs/layer-features/index.html @@ -6,8 +6,8 @@ Layer Features | The Paper Pilot - - + + @@ -35,8 +35,8 @@ "prestige-button"() {return {'color': '#AA66AA'}}, },

Custom Prestige type

  • getResetGain(): For custom prestige type, Returns how many points you should get if you reset now. You can call getResetGain(this.layer, useType = "static") or similar to calculate what your gain would be under another prestige type (provided you have all of the required features in the layer.)

  • getNextAt(canMax=false): For custom prestige type, Returns how many of the base currency you need to get to the next point. canMax is an optional variable used with Static-ish layers to differentiate between if it's looking for the first point you can reset at, or the requirement for any gain at all. (Supporting both is good). You can also call getNextAt(this.layer, canMax=false, useType = "static") or similar to calculate what your next at would be under another prestige type (provided you have all of the required features in the layer.)

  • canReset(): For custom prestige type, return true only if you have the resources required to do a prestige here.

- - + + \ No newline at end of file diff --git a/public/gamedevtree/docs/main-mod-info/index.html b/public/gamedevtree/docs/main-mod-info/index.html index 4ae5a802f..b0f599bf1 100644 --- a/public/gamedevtree/docs/main-mod-info/index.html +++ b/public/gamedevtree/docs/main-mod-info/index.html @@ -6,8 +6,8 @@ mod.js | The Paper Pilot - - + + @@ -24,8 +24,8 @@ happiness: new Decimal(72), }}
  • displayThings: An array of functions used to display extra things at the top of the tree tab. Each function returns a string, which is a line to display (with basic HTML support). If a function returns nothing, nothing is displayed (and it doesn't take up a line).

  • isEndgame(): A function to determine if the player has reached the end of the game, at which point the "you win!" screen appears.

Less important things beyond this point!

  • maxTickLength(): Returns the maximum tick length, in milliseconds. Only really useful if you have something that reduces over time, which long ticks mess up (usually a challenge).
- - + + \ No newline at end of file diff --git a/public/gamedevtree/docs/milestones/index.html b/public/gamedevtree/docs/milestones/index.html index 9c2073ef0..984a6b03b 100644 --- a/public/gamedevtree/docs/milestones/index.html +++ b/public/gamedevtree/docs/milestones/index.html @@ -6,8 +6,8 @@ Milestones | The Paper Pilot - - + + @@ -25,8 +25,8 @@ }

You can use hasMilestone(layer, id) to determine if the player has a given milestone

Milestone features:

  • requirementDesc: A string describing the requirement for unlocking this milestone. Suggestion: Use a "total". It can also be a function that returns updating text. Can use basic HTML.

  • effectDesc: A string describing the reward for having the milestone. You will have to implement the reward elsewhere. It can also be a function that returns updating text. Can use basic HTML.

  • done(): A function returning a boolean to determine if the milestone should be awarded.

  • toggles: optional, Creates toggle buttons that appear on the milestone when it is unlocked. The toggles can toggle a given boolean value in a layer. It is defined as an array of paired items, one pair per toggle. The first is the internal name of the layer the value being toggled is stored in, and the second is the internal name of the variable to toggle. (e.g. [["b", "auto"], ["g", "auto"])

         **Tip:** Toggles are not de-set if the milestone becomes locked! In this case, you should also check if the player has the milestone.
     
  • style: Optional, Applies CSS to this milestone, in the form of an object where the keys are CSS attributes, and the values are the values for those attributes (both as strings)

  • unlocked(): Optional A function returning a boolean to determine if the milestone should be shown. If absent, it is always shown.

  • layer: Assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar

  • id: Assigned automagically. It's the "key" which the milestone was stored under, for convenient access. The milestone in the example's id is 0.

- - + + \ No newline at end of file diff --git a/public/gamedevtree/docs/subtabs-and-microtabs/index.html b/public/gamedevtree/docs/subtabs-and-microtabs/index.html index e7c34d645..0012acc53 100644 --- a/public/gamedevtree/docs/subtabs-and-microtabs/index.html +++ b/public/gamedevtree/docs/subtabs-and-microtabs/index.html @@ -6,8 +6,8 @@ Subtabs and Microtabs | The Paper Pilot - - + + @@ -42,8 +42,8 @@ } },

Normal subtabs and microtab subtabs both use the same features:

Features:

  • content: The tab layout code for the subtab, in the tab layout format

  • style: Optional, Applies CSS to the whole subtab when switched to, in the form of an "CSS Object", where the keys are CSS attributes, and the values are the values for those attributes (both as strings)

  • buttonStyle: Optional, A CSS object, which affects the appearance of the button for that subtab.

  • unlocked(): Optional, a function to determine if the button for this subtab should be visible. By default, a subtab is always unlocked. (You can't use the "this" keyword in this function.)

- - + + \ No newline at end of file diff --git a/public/gamedevtree/docs/updating-tmt/index.html b/public/gamedevtree/docs/updating-tmt/index.html index 9c5c44797..85dbc059d 100644 --- a/public/gamedevtree/docs/updating-tmt/index.html +++ b/public/gamedevtree/docs/updating-tmt/index.html @@ -6,8 +6,8 @@ Updating The Modding Tree | The Paper Pilot - - + + @@ -18,8 +18,8 @@
Skip to content
On this page

Updating The Modding Tree

This tutorial assumes that you have used the Getting Started Tutorial, and are using Github Desktop and VSCode for your mod.

Here's what you have to do when there's a TMT update:

  1. Look at the changelog. It will warn you if the update will break anything or require any changes. Decide if you want to try to update.

  2. Open Github Desktop, and at the top middle, click "fetch origin". This will make Github Desktop get information about the update.

  3. Click where it says "current branch: master" at the top middle, and at the bottom of the thing that appears, click "choose a branch to merge into master.

  4. Select upstream/master. It will likely say there are conflicts, but you have tools to resolve them. Click "Merge upstream/master into master".

  5. A conflict happens when the things you're trying to merge have both made changes in the same place. Click "open in Visual Studio Code" next to the first file.

  6. Scroll down through the file, and look for the parts highlighted in red and green. One of these is your code, and the other is some code that will be modified by the update. Do your best to try to edit things to keep the updated changes, but keep your content.

  7. Continue to do this for all remaining challenges.

  8. Do any other changes required by the update, run the game, fix issues, etc.

- - + + \ No newline at end of file diff --git a/public/gamedevtree/docs/upgrades/index.html b/public/gamedevtree/docs/upgrades/index.html index c00d1a7f9..9080cb048 100644 --- a/public/gamedevtree/docs/upgrades/index.html +++ b/public/gamedevtree/docs/upgrades/index.html @@ -6,8 +6,8 @@ Upgrades | The Paper Pilot - - + + @@ -27,8 +27,8 @@ etc }

Each upgrade should have an id where the first digit is the row and the second digit is the column. Individual upgrades can have these features:

  • title: optional, displayed at the top in a larger font It can also be a function that returns updating text. Can use basic HTML.

  • description: A description of the upgrade's effect. You will also have to implement the effect where it is applied. It can also be a function that returns updating text. Can use basic HTML.

  • effect(): optional, A function that calculates and returns the current values of any bonuses from the upgrade. Can return a value or an object containing multiple values.

  • effectDisplay(): optional, A function that returns a display of the current effects of the upgrade with formatting. Default behavior is to just display the a number appropriately formatted. Can use basic HTML.

  • cost: A Decimal for the cost of the upgrade. By default, upgrades cost the main prestige currency for the layer.

  • unlocked(): optional, A function returning a bool to determine if the upgrade is visible or not. Default is unlocked.

  • onPurchase() - optional, this function will be called when the upgrade is purchased. Good for upgrades like "makes this layer act like it was unlocked first".

By default, upgrades use the main prestige currency for the layer. You can include these to change them (but it needs to be a Decimal):

  • currencyDisplayName: optional, the name to display for the currency for the upgrade

  • currencyInternalName: optional, the internal name for that currency

  • currencyLayer: optional, the internal name of the layer that currency is stored in. If it's not in a layer (like Points), omit. If it's not stored directly in a layer, instead use the next feature.

  • currencyLocation: optional, if your currency is stored in something inside a layer (e.g. a buyable's amount), you can access it this way. This is a function returning the object in "player" that contains the value (like player[this.layer].buyables)

  • style: Optional, Applies CSS to this upgrade, in the form of an object where the keys are CSS attributes, and the values are the values for those attributes (both as strings)

  • layer: Assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar

  • id: Assigned automagically. It's the "key" which the upgrade was stored under, for convenient access. The upgrade in the example's id is 11.

- - + + \ No newline at end of file diff --git a/public/kronos/Old Things/2.0-format-changes/index.html b/public/kronos/Old Things/2.0-format-changes/index.html index 5b46f4c75..5e8c94ab9 100644 --- a/public/kronos/Old Things/2.0-format-changes/index.html +++ b/public/kronos/Old Things/2.0-format-changes/index.html @@ -6,8 +6,8 @@ 2.0 format changes | The Paper Pilot - - + + @@ -18,8 +18,8 @@
Skip to content
On this page

2.0 format changes

  • Temp format is changed from temp.something[layer] to temp[layer].something, for consistency
  • Challenges are now saved as an object with the amount of completions in each spot. (This will break saves.)
  • effectDisplay in Challenges and Upgrades no longer takes an argument, and neither does effect for Buyables
  • Buyable cost can take an argument for amount of buyables, but it needs to function if no argument is supplied (it should do the cost for the next purchase).
  • Generation of Points now happens in the main game loop (not in a layer update function), enabled by canGenPoints in game.js.
  • Changed fullLayerReset to layerDataReset, which takes an array of names of values to keep

In addition, many names were changed, mostly expanding abbreviations:

All instances of:

  • chall -> challenge
  • unl -> unlocked
  • upg -> upgrade (besides CSS)
  • amt -> amount
  • desc -> description
  • resCeil -> roundUpCost
  • order -> unlockOrder
  • incr_order -> increaseUnlockOrder

Challenges:

  • desc -> challengeDescription
  • reward -> rewardDescription
  • effect -> rewardEffect
  • effectDisplay -> rewardDisplay
  • active -> challengeActive
- - + + \ No newline at end of file diff --git a/public/kronos/README/index.html b/public/kronos/README/index.html index bc7a4b746..a1a4dd509 100644 --- a/public/kronos/README/index.html +++ b/public/kronos/README/index.html @@ -6,8 +6,8 @@ Kronos | The Paper Pilot - - + + @@ -18,8 +18,8 @@
Skip to content
On this page

Kronos

Play here.

Updating the website:

  • git submodule update --remote
  • git add -A
  • git commit -m "Updated kronos"
  • git push
- - + + \ No newline at end of file diff --git a/public/kronos/changelog/index.html b/public/kronos/changelog/index.html index df15a4c6a..2b98981a4 100644 --- a/public/kronos/changelog/index.html +++ b/public/kronos/changelog/index.html @@ -6,8 +6,8 @@ The Modding Tree changelog: | The Paper Pilot - - + + @@ -18,8 +18,8 @@
Skip to content
On this page

The Modding Tree changelog:

v2.5.9.2 - 5/19/21

  • Fixed many issues with things not updating.

v2.5.9.1 - 5/18/21

  • Made text inputs never give NaNs.

v2.5.9 - 5/18/21

  • Fixed issue when using text inputs for Numbers.
  • Added particle color feature.
  • Particle speed and dir are updated as it moves.
  • Added setSpeed and setDir for particles.
  • Added more trig functions.

v2.5.8 - 5/17/21

  • Added makeShinies, which creates a stationary particle in a random spot.
  • Bars will visually update more quickly.
  • Fixed a major particle-related issue.
  • Fixed autoUpgrade.
  • Fixed a minor visual issue with tree nodes.

v2.5.7 - 5/15/21

  • Added a particle system! Not only can it be used for visual effects, but particles can interact with the mouse. They could be used to create golden cookies or collectables, for example.
  • Added marked feature to buyables, clickables, and challenges. By default, stars multi-completion challenges when maxed.
  • Added 'deactivated' feature to layers, which disables many features.
  • Improved number formatting slightly.

v2.5.6 - 5/14/21

  • You can now use non-numeric ids for upgrades, buyables, etc.
  • Fixed an exploit that let you buy an extra buyable.
  • Moved basic getter/setter functions to easyAccess.js.

v2.5.5.2 - 5/12/21

  • Fixed a major issue with buyables.
  • Fixed a variety of tabFormat-related issues.
  • Fixed commas appearing in decimal places (thanks to pg132!)

v2.5.5.1 - 5/12/21

  • Fixed clickables.

v2.5.5 - 5/12/21

  • Added grids! They are a grid of buttons which behave the same, but have their own data. Good for inventory grids, map tiles, and more!
  • Added "marked" feature to add a mark to a node. Can be an image instead of a star. (Originally by Jacorb)
  • Added "layer-proxy" component that lets you use components from another layer.
  • Added the ability to display non-whole numbers in main-display.

v2.5.4 - 5/10/21

  • Added a setting to always use single-tab mode.
  • Added directMult, which multiplies prestige gain after exponents and softcaps. It actually multiplies gain for static layers.
  • Added onEnter and onExit for challenges.
  • Improved displaying numbers between 0.0001 and 0.1.
  • Added documentation on how gainMult/Exp work for static layers.
  • Fixed a visual issue on mobile, thanks to thepaperpilot.
  • Improved documentation in general.

v2.5.3 - 5/8/21

  • Improved performance of tab formats and bars.
  • Respec confirmation settings are now kept on resets.
  • Improved compatibility with older browsers.
  • Fixed missing pixel on vertical bars.

v2.5.2.1 - 5/7/21

  • Fixed microtabs making layers highlight incorrectly.

v2.5.2 - 5/7/21

  • Added glowColor for subtabs.
  • Improved the display for extremely small numbers.
  • Fixed issues in the buyable docs.

v2.5.1 - 5/7/21

  • Fixed dynamic things in tabFormat not updating.

v2.5: Dreams Really Do Come True - 5/7/21

  • Optimizations, hopefully a significant amount.
  • Added OOM/s point gen display at high values (thanks to Ducdat!)
  • Only one tab will display if the window is not wide enough (also thanks to Ducdat!)
  • Holding down a buyable's button now buys it continuously.
  • New milestone setting will also show the most recently unlocked milestone. (Also renamed all settings to be clearer)
  • Added an onHold feature for clickables.
  • Layer nodes will be highlighted even if the player is on the same tab.
  • Added customizable node glowColor.
  • Added buyable purchaseLimit.
  • Amount is automatically supplied to buyable cost and effect functions.
  • Locked (not yet visible) milestones no longer take up space. Also fixed hidden milestones taking a tiny bit of space.
  • Re-centered respec buttons.
  • Force-displayed tooltips are not hidden by resets.
  • Added formatting support for very small numbers. Disabled in most places by default because rounding errors might cause issues. Access it with formatSmall, or enable it globally by adding "allowSmall: true" to modInfo.

v2.4.1 - 4/29/21

  • A number of minor fixes, many thanks to thepaperpilot.
  • The respec confirmation checkbox is now part of the respec-button component. (This also fixes the checkbox appearing when there is no respec button)
  • Added a few undocumented changes to the 2.4 changelog (the two at the bottom)

v2.4: Rationalized Edition - 4/29/21

  • Completely reworked tooltips. Shift-click a node to force its tooltip to stay displayed. (And hopefully finally fixed flickering!)

  • Added text-input and slider components.

  • Added the ability to toggle respec confirmations.

  • Added custom respec confirmation messages.

  • The red layer highlight will not appear before a layer is unlocked.

  • Added unlocking hotkeys.

  • You no longer need to supply 'rows' and 'cols' for any Big Features.

  • Node symbols can use HTML.

  • Added documentation for the respec button.

  • Added prestigeNotify to subtabs, and prestigeNotify in subtabs also highlights the layer node.

  • The version number no longer contains special characters or irrational numbers.

  • Added ctrlDown and shiftDown variables.

  • Tooltips now use HTML (this means you need to replace any newlines with
    )

v2.Ï€.1 - 4/7/21

  • Fixed formatting for some larger numbers.
  • Upgrades will expand if there is too much text to display.
  • Fixed styling challenges.
  • No longer attempts to display a base currency when there is none.

v2.Ï€: Incrementally Updated - 2/5/21

  • Performance improvements.
  • Fixed tooltips overlapping with the top display.
  • Clicking a popup dismisses it immediately.
  • Added support for bulk challenge completions.
  • "Best" is updated automatically.
  • Fixed keeping Decimal values on reset.
  • Code reorganization and style improvements by fudo.

v2.3.5 - 12/21/20

  • Added resetTime, which tracks the time since a layer prestiged or was reset.
  • A layer node will be highlighted red if one of its subtabs is highlighted red.
  • Fixed issues with keeping challenges, buyables, and clickables on reset.
  • Improved the unlocking of custom layers.
  • Other minor fixes.

v2.3.4 - 12/16/20

  • Added a node image feature.
  • Resource display now always shows the amount of the currency the layer's gain is based on.
  • Added spacing between tree nodes.
  • Another attempt to fix tooltip flickering.

v2.3.3 - 12/13/20

  • Fixed the first node in a row always taking up space.
  • layerShown is now optional.
  • All prestige types can now use features for custom prestige types.

v2.3.2 - 12/13/20

  • Fixed achievement/milestone popups.

v2.3.1 - 12/12/20

  • Another attempt to fix flickering tooltips.
  • The "this" keyword should work everywhere except tabFormat arrays (although I may have missed some things).
  • Fixed tree branches not updating when scrolling on the right-side tab.
  • Fixed a spacing issue when a node's symbol is ""
  • Removed some old, unneeded files.

v2.3: Cooler and Newer Edition - 12/10/20

  • Added achievement/milestone popups (thank you to Jacorb for this contribution!)
  • The changelog tab is back, and can be set in mod.js.
  • Layer nodes and respec buttons will not be clicked by pressing "enter".
  • Possible fix for flickering tooltips and strange transitions.
  • The victory screen text is configurable.
  • Added image and textStyle features to achievements.
  • Added an argument to use specific rows in an "upgrades" component.
  • Fixed the comma appearing in the main display when there was no effectDescription
  • Added the ability to easily make a tab that is a collection of layers in subtabs.
  • Improved spacing for embedding layers with subtabs into subtabs.

v2.2.8 - 12/03/20

  • Double-clicking a layer node brings you to the main subtab for that layer.
  • Attempted to fix challenges visually updating a different way.
  • Added a softcap function for use in formulas.
  • Added displayRow feature, which lets layers be shown somewhere separate from where they are in the reset order (e.g. side layers)
  • Fixed autoupgrade issue.

v2.2.7 - 11/30/20

  • Added autoUpgrade feature.
  • resource-display now shows resource gain per second if passiveGain is active.
  • Fixed formatting issues on some large numbers.
  • Better support for using classed objects in player and in layers/tmp.
  • Made hard resetting more effective.
  • Removed Herobrine from getStartClickables.

v2.2.6 - 11/30/20

  • Added goalDescription for challenges and made the new "canComplete" system the standard.
  • Another attempt to fix challenges not visually updating.
  • Fixed side layers not appearing.
  • Fixed getStartClickables again.

v2.2.5 - 11/29/20

  • Added features for overriding the displays and costs/goals of upgrades and challenges to make them fully custom.
  • best, total, and unlocked are always automatically added to layerData (but best and total will only display if you add them yourself).
  • Fixed getStartClickables.

v2.2.4 - 11/28/20

  • Added softcap and softcapPower features (for Normal layers)
  • Offline time limit and default max tick length were fixed (previously the limits were 1000x too large)
  • Added fixOldSaves.
  • You can use HTML in main-display.
  • Fixed a number of minor oddities.

v2.2.3 - 11/28/20

  • Layers will be highlighted if you can finish a challenge.
  • The "can complete challenge" color now overrides the "already completed" color.
  • Button nodes now work as side "layers".
  • Setting a tooltip to "" hides it entirely.

v2.2.2 - 11/22/20

  • Fixed right half of the screen being unclickable in some circumstances.
  • Fixed tree branches being offset.
  • Fix to lastSafeTab.

v2.2.1 - 11/7/20

  • Added a small highlight to layers you can meaningfully prestige on.
  • Added passiveGeneration and autoPrestige features to standardize prestige automation. (The old ways still work, but the new ones work better with other things)
  • Improved milestones visually a bit.
  • "best" and "total" are now only displayed if present in startData.
  • Fixed issues with things not updating visually. (Thank you to to Jacorb!)
  • Side layers and button nodes can now be highlighted.
  • Updated docs on the new tree-related features.

v2.2: Uprooted - 11/7/20

  • You can now embed a layer inside of a subtab or microtab!
  • Added support for hiding or reformatting the tree tab
  • Added non-layer button nodes
  • Added shouldNotify to subtab/microtab buttons. (You can make them highlighted)
  • Added commas to large exponents.
  • Upgrades now only show "currently" if they have an effectDisplay (so not for constant effects).
  • Achievements are part of the default tab format.
  • NaN is now handled more intelligently.
  • Renamed files, and moved less relevant ones to another folder.
  • The "hide completed challenges" setting now only hides challenges at max completions.
  • Thank you to thepaperpilot for fixing errors in docs and improving the infobox appearance!
  • Many other minor fixes.

v2.1.4 - 10/25/20

  • Added an infobox component. Thank you to thepaperpilot for this contribution!
  • Layer type is now optional, and defaults to "none".
  • Improved the look of bars and tab buttons.
  • Improved spacing between layer nodes (also thanks to thepaperpilot!)
  • Fixed the "blank" component breaking if only specifying the height.
  • Fixed some numbers not displaying with enough digits.
  • Made a few more things able to be functions.
  • A few other minor fixes.

v2.1.3.1 - 10/21/20

  • Fixed the update function.

v2.1.3 - 10/21/20

  • gainMult and gainExp are now optional.
  • Layer unlocking is now kept on reset.
  • Game should start up faster.
  • Layer updates now have a determined order and starts with earlier-rowed layers.
  • Automation now has a determined order and starts with later-rowed layers.
  • Fixed issues with resetting clickables and challenges.
  • Commas should no longer appear in the decimal places of a number.
  • Fixed potential issue in displaying the tree.

v2.1.2 - 10/19/20

  • Added buyUpgrade function (buyUpg still works though)
  • Added author name to modInfo.
  • Fix to crash caused when the name of a subtab or microtab is changed.
  • Fixes to outdated information in docs.
  • Improvements to Discord links.
  • Thank you to thepaperpilot for contributing to this update!

v2.1.1 - 10/17/20

  • Added resource-display component, which displays the base currency for the prestige layer, as well as the best and/or total of this layer's prestige currency.
  • Fixed the value for the base currency not updating in resource-display.

v2.1: We should have thought of this sooner! - 10/17/20

  • Moved most of the code users will want to edit to mod.js, added documentation for it.
    • Specifically, modInfo, VERSION, canGenPoints, getPointGen, and maxTickLength
  • Added getStartPoints()
  • Added the ability to store non-layer-related data
  • Added the ability to display more things at the top of the tree tab below points.
  • Made the endgame condition customizable
  • Added "sell one" and "sell all" buttons for buyables.
  • Moved the old "game" to demo.js, and replaced it with a minimal game that won't cause issues when edited.
  • Fixed issues with version number
  • Fixed number formatting issue making things like "10e9" appear.

v2.0.5 - 10/16/20

  • Made more features (including prestige parameters) able to be dynamic.
  • Layer nodes can be hidden but still take up space with "ghost" visibility
  • Added clickableEffect for real.
  • Fixed some visual issues with bars.
  • A few other minor tweaks and improvements.

v2.0.4 - 10/16/20

  • Fixed HTML on buttons interfering with clicking on them.

v2.0.3 - 10/16/20

  • Fixed hotkeys not displaying in info.
  • Fixed the game supressing all external hotkeys.
  • You can use more things as currencies for upgrade costs and challenge goals using currencyLocation.
  • Added maxTickLength, which can be used to prevent offline time or tab-switching from breaking time-limit based mechanics.
  • Made buyable respec buttons and clickable "master" buttons their own components, and gave them a hide/show feature.
  • Added a general "tooltip" feature for achievements.

v2.0.2 - 10/15/20

  • Branches are now dynamic (they can be functions).
  • Fixed a crash related to offline time.
  • Fixed links being too wide.

v2.0.1 - 10/15/20

  • Fixed side layers appearing multiple times.

v2.0: The Pinnacle of Achievement Mountain - 10/15/20

  • Added progress bars, which are highly customizable and can be horizontal or vertical!
  • Added "side layers", displayed smaller and off to the side, and don't get reset by default. They can be used for global achievements and statistics. Speaking of which...
  • Added achievements!
  • Added clickables, a more generalized variant of buyables.
  • Almost every value in layer data can be either a function or a constant value!
  • Added support for multiple completions of challenges.
  • Added "none" prestige type, which removes the need for any other prestige-related features.
  • The points display and other gui elements stay at the top of the screen when the tree scrolls.
  • Added getter/setter functions for the amounts and effects of most Big Features
  • Moved modInfo to game.js, added a spot in modInfo for a Discord link, changelog link. Also added a separate mod version from the TMT version in VERSION.
  • Tree structure is based on layer data, no index.html editing is needed.
  • Tmp does not need to be manually updated.
  • You don't have to have the same amount of upgrades in every row (and challs and buyables)
  • "unlocked" is optional for all Big Components (defaults to true).
  • All displays will update correctly.
  • Changelog is no longer in index.html at all.
  • Generation of Points now happens in the main game loop
  • Changed the reset functions to make keeping things easier
  • Renamed many things to increase readability (see the list in the link below)
  • Improved documentation based on feedback

v1.3.5:

  • Completely automated convertToDecimal, now you never have to worry about it again.
  • Branches can be defined without a color id. But they can also use hex values for color ids!
  • Created a tutorial for getting started with TMT and Github.
  • Page title is now automatically taken from mod name.

v1.3.4 - 10/8/20

  • Added "midsection" feature to add things to a tab's layout while still keeping the standard layout.
  • Fix for being able to buy more buyables than you should.

v1.3.3 - 10/7/20

  • Fix for the "order of operations" issue in temp.

v1.3.1 - 10/7/20

  • Added custom CSS and tooltips for Layer Nodes.
  • Added custom CSS for upgrades, buyables, milestones, and challenges, both individually and layer-wide.
  • You can now use HTML in most display text!
  • You can now make milestones unlockable and not display immediately.
  • Fixed importing saves, and issue with upgrades not appearing, and probably more.
  • Optional "name" layer feature, used in confirmation messages.

v1.3: Tabception... ception! - 10/7/20

  • Added subtabs! And also a Micro-tab component to let you make smaller subtab-esque areas anywhere.
  • Added a "custom" prestige formula type, and a number of features to support it.
  • Added points/sec display (can be disabled).
  • Added h-line, v-line and image-display components, plus components for individual upgrades, challenges, and milestones.
  • Added upgEffect, buyableEffect, and challEffect functions.
  • Added "hide completed challenges" setting.
  • Moved old changelogs to a separate place.
  • Fixed hasMilestone and incr_order.
  • Static layers now show the currency amount needed for the next one if you can buy max.

v1.2.4 - 10/4/20

  • Layers are now highlighted if you can buy an upgrade, and a new feature, shouldNotify, lets you make it highlight other ways.
  • Fixed bugs with hasUpg, hasChall, hasMilestone, and inChallenge.
  • Changed the sample code to use the above functions for convenience.

v1.2.3 - 10/3/20

  • Added a row component, which displays a list of objects in a row.
  • Added a column component, which displays a list of objects in a column (useful within a row).
  • Changed blanks to have a customizable width and height.

v1.2: This Changes Everything! - 10/3/20

  • Many layer features can now be static values or functions. (This made some formats change, which will break old things)
  • You can now use the "this" keyword, to make code easier to transfer when making new layers.
  • Also added "this.layer", which is the current layer's name, and works on existing subfeatures (e.g. individual upgrades) as well! Subfeatures also have "this.id".
  • Fixed a big save issue. If you use a unique mod id, your save will never conflict with other mods.
  • Added a configurable offline time limit in modinfo at the top of index.html. (default 1 hour)
  • Added a few minor features, and updated the docs with new information.

v1.1.1 - 9/30/20

  • You can define hotkeys directly from layer config.

v1.1: Enhanced Edition - 9/30/20

  • Added "Buyables", which can function like Space Buildings or Enhancers.
  • Custom CSS can now be used on any component! Make the third argument an object with CSS parameters.
  • Lots of minor good things.

v1.0 - 9/27/20

  • First release.
- - + + \ No newline at end of file diff --git a/public/kronos/docs/!general-info/index.html b/public/kronos/docs/!general-info/index.html index d41ca8a27..73568355e 100644 --- a/public/kronos/docs/!general-info/index.html +++ b/public/kronos/docs/!general-info/index.html @@ -6,8 +6,8 @@ The-Modding-Tree | The Paper Pilot - - + + @@ -18,8 +18,8 @@
Skip to content
On this page

The-Modding-Tree

Making a game in The Modding Tree mostly involves defining parameters or functions on objects. If you aren't following the getting started guide, you should start by setting up your basic mod info in mod.js. It's important to set a mod id to ensure saving works properly.

Beyond that, the main way to add content is through creating layers, often in layers.js. You can add new layers by calling addLayer(layername, layerdata). There is an example of a basic layer in layers.js showing the recommended method. It is just an example and can be freely deleted. You can also use it as a reference or a base for your own layers.

Most of the time, you won't need to dive deep into the code to create things, but you still can if you really want to, for example to add new Vue components in components.js.

The Modding Tree uses break_eternity.js to store large values. This means that many numbers are Decimal objects, and must be treated differently. For example, you have to use new Decimal(x) to create a Decimal value instead of a plain number, and perform operations on them by calling functions. e.g, instead of x = x + y, use x = x.add(y). Keep in mind this also applies to comparison operators, which should be replaced with calling the .gt, .gte, .lt, .lte, .eq, and .neq functions. See the break_eternity.js docs for more details on working with Decimal values.

Almost all values can be either a constant value, or a dynamic value. Dynamic values are defined by putting a function that returns what the value should be at any given time.

All display text can use basic HTML elements (But you can't use most Vue features there).

While reading this documentation, the following key will be used when describing features:

  • No label: This is required and the game may crash if it isn't included.
  • sometimes required: This is may be required, depending on other things in the layer.
  • optional: You can leave this out if you don't intend to use that feature for the layer.
  • assigned automagically: This value will be set automatically and override any value you set.
  • deprecated: This feature is not recommended to be used, because newer features are able to achieve the same thing in a better, easier way.

Table of Contents

General

  • Getting Started: Getting your own copy of the code set up with Github Desktop.
  • Main mod info: How to set up general things for your mod in mod.js.
  • Basic layer breakdown: Breaking down the components of a layer with minimal features.
  • Layer features: Explanations of all of the different properties that you can give a layer.
  • Custom Tab Layouts: An optional way to give your tabs a different layout. You can even create entirely new components to use.
  • Custom game layouts: You can get rid of the tree tab, add buttons and other things to the tree, or even customize the tab's layout like a layer tab.
  • Updating TMT: Using Github Desktop to update your mod's version of TMT.

Common components

  • Upgrades: How to create upgrades for a layer.
  • Milestones: How to create milestones for a layer.
  • Buyables: Create rebuyable upgrades for your layer (with the option to make them respec-able). Can be used to make Enhancers or Space Buildings, for example.
  • Clickables: A more generalized variant of buyables, for any kind of thing that is sometimes clickable. Between these and Buyables, you can do just about anything.
  • Achievements: How to create achievements for a layer (or for the whole game).

Other components and features

  • Challenges: How to create challenges for a layer.
  • Bars: Display some information as a progress bar, gauge, or similar. They are highly customizable, and can be horizontal and vertical as well.
  • Subtabs and Microtabs: Create subtabs for your tabs, as well as "microtab" components that you can put inside the tabs. You can even use them to embed a layer inside another layer!
  • [Grids][grids.md]: Create a group buttons that behave the same, but have their own data. Good for map tiles, an inventory grid, and more!
  • Infoboxes: Boxes containing text that can be shown or hidden.
  • Trees: Make your own trees. You can make non-layer button nodes too!
  • Particle system: Can be used to create particles for visual effects, but also interactable things like golden cookies or collectables.
- - + + \ No newline at end of file diff --git a/public/kronos/docs/achievements/index.html b/public/kronos/docs/achievements/index.html index 34c0fbf59..5e3e06cd8 100644 --- a/public/kronos/docs/achievements/index.html +++ b/public/kronos/docs/achievements/index.html @@ -6,8 +6,8 @@ Achievements | The Paper Pilot - - + + @@ -25,8 +25,8 @@ etc }

Usually, each achievement should have an id where the first digit is the row and the second digit is the column.

Individual achievement can have these features:

  • name: optional. displayed at the top of the achievement. The only visible text. It can also be a function that returns updating text. Can use basic HTML.

  • done(): A function returning a boolean to determine if the achievement should be awarded.

  • tooltip: Default tooltip for the achievement, appears when it is hovered over. Should convey the goal and any reward for completing the achievement. It can also be a function that returns updating text. Can use basic HTML. Setting this to "" disables the tooltip.

  • effect(): optional. A function that calculates and returns the current values of any bonuses from the achievement. Can return a value or an object containing multiple values.

  • unlocked(): optional. A function returning a bool to determine if the achievement is visible or not. Default is unlocked.

  • onComplete() - optional. this function will be called when the achievement is completed.

  • image: optional, puts the image from the given URL (relative or absolute) in the achievement

  • style: optional. Applies CSS to this achievement, in the form of an object where the keys are CSS attributes, and the values are the values for those attributes (both as strings).

  • textStyle: optional. Applies CSS to the text, in the form of an object where the keys are CSS attributes, and the values are the values for those attributes (both as strings).

  • layer: assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar.

  • id: assigned automagically. It's the "key" which the achievement was stored under, for convenient access. The achievement in the example's id is 11.

  • goalTooltip: optional, deprecated. Appears when the achievement is hovered over and locked, overrides the basic tooltip. This is to display the goal (or a hint). It can also be a function that returns updating text. Can use basic HTML.

  • doneTooltip: optional, deprecated. Appears when the achievement is hovered over and completed, overrides the basic tooltip. This can display what the player achieved (the goal), and the rewards, if any. It can also be a function that returns updating text. Can use basic HTML.

Disable achievement popups by adding achievementsPopups: false to the layer.

- - + + \ No newline at end of file diff --git a/public/kronos/docs/bars/index.html b/public/kronos/docs/bars/index.html index fde7ef3a9..7febe5726 100644 --- a/public/kronos/docs/bars/index.html +++ b/public/kronos/docs/bars/index.html @@ -6,8 +6,8 @@ Bars | The Paper Pilot - - + + @@ -28,8 +28,8 @@ etc }

Features:

  • direction: UP, DOWN, LEFT, or RIGHT (not strings). Determines the direction that the bar is filled as it progresses. RIGHT means from left to right.

  • width, height: The size in pixels of the bar, but as numbers (no "px" at the end).

  • progress(): A function that returns the portion of the bar that is filled, from "empty" at 0 to "full" at 1, updating automatically. (Nothing bad happens if the value goes out of these bounds, and it can be a number or Decimal)

  • display(): optional. A function that returns text to be displayed on top of the bar, can use HTML.

  • unlocked(): optional. A function returning a bool to determine if the bar is visible or not. Default is unlocked.

  • baseStyle, fillStyle, borderStyle, textStyle: Optional, Apply CSS to the unfilled portion, filled portion, border, and display text on the bar, in the form of an object where the keys are CSS attributes, and the values are the values for those attributes (both as strings).

  • layer: assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar.

  • id: assigned automagically. It's the "key" which the bar was stored under, for convenient access. The bar in the example's id is "bigBar".

- - + + \ No newline at end of file diff --git a/public/kronos/docs/basic-layer-breakdown/index.html b/public/kronos/docs/basic-layer-breakdown/index.html index 9b924f8aa..198b27ac9 100644 --- a/public/kronos/docs/basic-layer-breakdown/index.html +++ b/public/kronos/docs/basic-layer-breakdown/index.html @@ -6,8 +6,8 @@ Basic layer breakdown | The Paper Pilot - - + + @@ -50,8 +50,8 @@ }, }) - - + + \ No newline at end of file diff --git a/public/kronos/docs/buyables/index.html b/public/kronos/docs/buyables/index.html index 446c31e5c..8c3f2a1b9 100644 --- a/public/kronos/docs/buyables/index.html +++ b/public/kronos/docs/buyables/index.html @@ -6,8 +6,8 @@ Buyables | The Paper Pilot - - + + @@ -31,8 +31,8 @@ etc }

Features:

  • title: optional. displayed at the top in a larger font. It can also be a function that returns updating text.

  • cost(): cost for buying the next buyable. Can have an optional argument "x" to calculate the cost of the x+1th purchase. (x is a Decimal). Can return an object if there are multiple currencies.

  • effect(): optional. A function that calculates and returns the current values of bonuses of this buyable. Can have an optional argument "x" to calculate the effect of having x of the buyable.. Can return a value or an object containing multiple values.

  • display(): A function returning everything that should be displayed on the buyable after the title, likely including the description, amount bought, cost, and current effect. Can use basic HTML.

  • unlocked(): optional. A function returning a bool to determine if the buyable is visible or not. Default is unlocked.

  • canAfford(): A function returning a bool to determine if you can buy one of the buyables.

  • buy(): A function that implements buying one of the buyable, including spending the currency.

  • buyMax(): optional. A function that implements buying as many of the buyable as possible.

  • style: optional. Applies CSS to this buyable, in the form of an object where the keys are CSS attributes, and the values are the values for those attributes (both as strings).

  • purchaseLimit: optional. The limit on how many of the buyable can be bought. The default is no limit.

  • marked: optional Adds a mark to the corner of the buyable. If it's "true" it will be a star, but it can also be an image URL.

  • layer: assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar.

  • id: assigned automagically. It's the "key" which the buyable was stored under, for convenient access. The buyable in the example's id is 11.

Sell One/Sell All:

Including a sellOne or sellAll function will cause an additional button to appear beneath the buyable. They are functionally identical, but "sell one" appears above "sell all". You can also use them for other things.

  • sellOne/sellAll(): optional. Called when the button is pressed. The standard use would be to decrease/reset the amount of the buyable, and possibly return some currency to the player.

  • canSellOne/canSellAll(): optional. booleans determining whether or not to show the buttons. If "canSellOne/All" is absent but "sellOne/All" is present, the appropriate button will always show.

To add a respec button, or something similar, add the respecBuyables function to the main buyables object (not individual buyables). You can use these features along with it:

  • respec(): optional. This is called when the button is pressed (after a toggleable confirmation message).

  • respecText: optional. Text to display on the respec Button.

  • showRespec(): optional. A function determining whether or not to show the button, if respecBuyables is defined. Defaults to true if absent.

  • respecMessage: optional. A custom confirmation message on respec, in place of the default one.

- - + + \ No newline at end of file diff --git a/public/kronos/docs/challenges/index.html b/public/kronos/docs/challenges/index.html index 97c6fbb85..6c27495dd 100644 --- a/public/kronos/docs/challenges/index.html +++ b/public/kronos/docs/challenges/index.html @@ -6,8 +6,8 @@ Challenges | The Paper Pilot - - + + @@ -27,8 +27,8 @@ etc }

Usually, each challenge should have an id where the first digit is the row and the second digit is the column.

Individual Challenges can have these features:

  • name: Name of the challenge, can be a string or a function. Can use basic HTML.

  • challengeDescription: A description of what makes the challenge a challenge. You will need to implement these elsewhere. It can also be a function that returns updating text. Can use basic HTML.

  • goalDescription: A description of the win condition for the challenge. It can also be a function that returns updating text. Can use basic HTML. (Optional if using the old goal system)

  • canComplete(): A function that returns true if you meet the win condition for the challenge. Returning a number will allow bulk completing the challenge. (Optional if using the old goal system)

  • rewardDescription: A description of the reward's effect. You will also have to implement the effect where it is applied. It can also be a function that returns updating text. Can use basic HTML.

  • rewardEffect(): optional. A function that calculates and returns the current values of any bonuses from the reward. Can return a value or an object containing multiple values. Can use basic HTML.

  • rewardDisplay(): optional. A function that returns a display of the current effects of the reward with formatting. Default behavior is to just display the a number appropriately formatted.

  • fullDisplay(): OVERRIDE. Overrides the other displays and descriptions, and lets you set the full text for the challenge. Can use basic HTML.

  • unlocked(): optional. A function returning a bool to determine if the challenge is visible or not. Default is unlocked.

  • onComplete() - optional. this function will be called when the challenge is completed when previously incomplete.

  • onEnter() - optional. this function will be called when entering the challenge

  • onExit() - optional. this function will be called when exiting the challenge in any way

  • countsAs: optional. If a challenge combines the effects of other challenges in this layer, you can use this. An array of challenge ids. The player is effectively in all of those challenges when in the current one.

  • completionLimit: optional. the amount of times you can complete this challenge. Default is 1 completion.

  • style: optional. Applies CSS to this challenge, in the form of an object where the keys are CSS attributes, and the values are the values for those attributes (both as strings).

  • marked: optional Adds a mark to the corner of the challenge. If it's "true" it will be a star, but it can also be an image URL. By default, if the challenge has multiple completions, it will be starred at max completions.

  • layer: assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar

  • id: assigned automagically. It's the "key" which the challenge was stored under, for convenient access. The challenge in the example's id is 11.

The old goal system uses these features:

  • goal: deprecated, A Decimal for the amount of currency required to beat the challenge. By default, the goal is in basic Points. The goal can also be a function if its value changes.

  • currencyDisplayName: deprecated. the name to display for the currency for the goal

  • currencyInternalName: deprecated. the internal name for that currency

  • currencyLayer: deprecated. the internal name of the layer that currency is stored in. If it's not in a layer, omit. If it's not stored directly in a layer, instead use the next feature.

  • currencyLocation(): deprecated. if your currency is stored in something inside a layer (e.g. a buyable's amount), you can access it this way. This is a function returning the object in "player" that contains the value (like player[this.layer].buyables)

- - + + \ No newline at end of file diff --git a/public/kronos/docs/clickables/index.html b/public/kronos/docs/clickables/index.html index bb5db7795..4390bfbf7 100644 --- a/public/kronos/docs/clickables/index.html +++ b/public/kronos/docs/clickables/index.html @@ -6,8 +6,8 @@ Clickables | The Paper Pilot - - + + @@ -25,8 +25,8 @@ etc }

Features:

  • title: optional. displayed at the top in a larger font. It can also be a function that returns updating text.

  • effect(): optional. A function that calculates and returns the current values of bonuses of this clickable. Can return a value or an object containing multiple values.

  • display(): A function returning everything that should be displayed on the clickable after the title, likely changing based on its state. Can use basic HTML.

  • unlocked(): optional. A function returning a bool to determine if the clickable is visible or not. Default is unlocked.

  • canClick(): A function returning a bool to determine if you can click the clickable.

  • onClick(): A function that implements clicking the clickable.

  • onHold(): optional A function that is called 20x/sec when the button is held for at least 0.25 seconds.

  • style: optional. Applies CSS to this clickable, in the form of an object where the keys are CSS attributes, and the values are the values for those attributes (both as strings).

  • marked: optional Adds a mark to the corner of the clickable. If it's "true" it will be a star, but it can also be an image URL.

  • layer: assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar.

  • id: assigned automagically. It's the "key" which the clickable was stored under, for convenient access. The clickable in the example's id is 11.

You can also use these features on the clickables object to add a button above all the clickables, for implementing a respec button or similar.

  • masterButtonPress(): optional. If present, an additional button will appear above the clickables. Pressing it will call this function.

  • masterButtonText: optional. Text to display on the Master Button.

  • showMasterButton(): optional. A function determining whether or not to show the button, if masterButtonPress is defined. Defaults to true if absent.

- - + + \ No newline at end of file diff --git a/public/kronos/docs/custom-tab-layouts/index.html b/public/kronos/docs/custom-tab-layouts/index.html index 819def782..44021a37d 100644 --- a/public/kronos/docs/custom-tab-layouts/index.html +++ b/public/kronos/docs/custom-tab-layouts/index.html @@ -6,8 +6,8 @@ Custom tab layouts | The Paper Pilot - - + + @@ -32,8 +32,8 @@ "upgrades" ]

It is a list of components, which can be either just a name, or an array with arguments. If it's an array, the first item is the name of the component, the second is the data passed into it, and the third (optional) applies a CSS style to it with a "CSS object", where the keys are CSS attributes.

These are the existing components, but you can create more in components.js:

  • display-text: Displays some text (can use basic HTML). The argument is the text to display. It can also be a function that returns updating text.

  • raw-html: Displays some basic HTML, can also be a function.

  • blank: Adds empty space. The default dimensions are 8px x 17px. The argument changes the dimensions. If it's a single value (e.g. "20px"), that determines the height. If you have a pair of arguments, the first is width and the second is height.

  • row: Display a list of components horizontally. The argument is an array of components in the tab layout format.

  • column: Display a list of components vertically. The argument is an array of components in the tab layout format. This is useful to display columns within a row.

  • main-display: The text that displays the main currency for the layer and its effects. The argument is the amount of precision to use, allowing it to display non-whole numbers.

  • resource-display: The text that displays the currency that this layer is based on, as well as the best and/or total values for this layer's prestige currency (if they are put in startData for this layer).

  • prestige-button: The argument is a string that the prestige button should say before the amount of currency you will gain. It can also be a function that returns updating text.

  • text-input: A text input box. The argument is the name of the variable in player[layer] that the input is for, player[layer][argument] (Works with strings, numbers, and Decimals!)

  • slider: Lets the user input a value with a slider. The argument a 3-element array: [name, min, max]. The name is the name of the variable in player[layer] that the input that the input is for, and min and max are the limits of the slider. (Does not work for Decimal values)

  • upgrades: The layer's upgrades. The argument is optional, and is a the list of rows this component should include, if it doesn't have all of them.

  • milestones, challenges, achievements: Display the upgrades, milestones, and challenges for a layer, as appropriate.

  • buyables, clickables: Display all of the buyables/clickables for this layer, as appropriate. The argument is optional and is the size of the boxes in pixels.

  • microtabs: Display a set of subtabs for an area. The argument is the name of the set of microtabs in the "microtabs" feature.

  • bar: Display a bar. The argument is the id of the bar to display.

  • infobox: Display an infobox. The argument is the id of the infobox to display.

  • tree: Displays a tree. The argument is an array of arrays containing the names of the nodes in the tree (first by row, then by column) See here for more information on tree layouts and nodes!

  • toggle: A toggle button that toggles a bool value. The argument is a pair that identifies the location in player of the bool to toggle, e.g. [layer, id]. 'layer' also affects the color of the toggle.

  • grid: Displays the gridable grid for the layer. If you need more than one grid, use a layer proxy.

  • layer-proxy: Lets you use components from another layer. The argument is a pair, [layer, data], consisting of the id of the layer to proxy from, and the tabFormat for the components to show. (Note: you cannot use a microtab within a layer proxy)

The rest of the components are sub-components. They can be used just like other components, but are typically part of another component.

  • upgrade, milestone, challenge, buyable, clickable, achievement, gridable: An individual upgrade, challenge, etc. The argument is the id. This can be used if you want to have upgrades split up across multiple subtabs, for example.

  • respec-button, master-button: The respec and master buttons for buyables and clickables, respectively.

  • sell-one, sell-all: The "sell one" and "sell all" for buyables, respectively. The argument is the id of the buyable.

- - + + \ No newline at end of file diff --git a/public/kronos/docs/getting-started/index.html b/public/kronos/docs/getting-started/index.html index fad389ef0..8f715d5f5 100644 --- a/public/kronos/docs/getting-started/index.html +++ b/public/kronos/docs/getting-started/index.html @@ -6,8 +6,8 @@ Getting started | The Paper Pilot - - + + @@ -18,8 +18,8 @@
Skip to content
On this page

Getting started

Welcome to The Modding Tree!

Using the Modding Tree, at its simplest level, just requires getting a copy of it onto your computer. However, if you do it the right way, it will help in many ways.

Don't let the word "Github" scare you away. It's actually much easier to use than most people think, especially because most people use it the hard way. The key is Github Desktop, which lets you do everything you need to, without even touching the command line.

The benefits of using Github:

  • It makes it much, much easier to update The Modding Tree.
  • You can share your work without any extra effort using githack, or with a bit more effort, set up a github.io site.
  • It lets you undo changes to your code, and to have multiple versions of it.
  • It lets you collaborate with other people, if you want to.

Getting set up with Github Desktop, Visual Studio Code, and The Modding Tree:

  1. Install Github Desktop and Visual Studio Code.

  2. Make a Github account. You can handle this on your own.

  3. Log in on your browser, and go back to The Modding Tree page. At the top right, there should be a button that says "fork". Click on it, and then on your username. You now have your own fork, or copy, of The Modding Tree.

  4. Open Github Desktop and log in. Ignore everything else and choose "clone a repository". A "repository" is basically a "Github project", like The Modding Tree. "Cloning" is downloading a copy of the repository to your computer.

  5. Look for The Modding Tree in the list of repositiories (it should be the only one) and click "clone".

  6. Select that you're using it for your own purposes, and click continue. It will download the files and handle everything.

Using your repository

  1. Click on "show in explorer/finder" to the right, and then open the index.html file in the folder. The page should open up on your browser. This will let you view and test your project locally!

  2. To edit your project, click "open in VSCode" in Github Desktop.

  3. Open mod.js in VSCode, and look at the top part where it has a "modInfo" object. Fill in your mod's name to whatever you want, and change the id as well. (It can be any string value, and it's used to determine where the savefile is. Make it something that's probably unique, and don't change it again later or else it'll effectively wipe existing saves)

  4. Save mod.js, and then reload index.html in your browser. The title on the tab, as well as on the info page, will now be updated! You can reload the page every time you change the code to test it quickly and easily.

  5. Go back to Github Desktop. It's time to save your changes into the git system by making a "commit". This basically saves your work and creates a snapshot of what your code looks like at this moment, allowing you to look back at it later.

  6. At the bottom right corner, add a summary of your changes, and then click "commit to master".

  7. Finally, at the top middle, click "push origin" to push your changes out onto the online repository.

  8. You can view your project on line, or share it with others, by going to https://raw.githack.com/[YOUR-GITHUB-USERNAME]/The-Modding-Tree/master/index.html

And now, you have successfully used Github! You can look at the documentation to see how The Modding Tree's system works and to make your mod a reality.

- - + + \ No newline at end of file diff --git a/public/kronos/docs/grids/index.html b/public/kronos/docs/grids/index.html index b516fcfc6..4308cea1e 100644 --- a/public/kronos/docs/grids/index.html +++ b/public/kronos/docs/grids/index.html @@ -6,8 +6,8 @@ Grids | The Paper Pilot - - + + @@ -39,8 +39,8 @@ etc }

Features:

  • rows, cols: The amount of rows and columns of gridable to display.

  • maxRows, maxCols: sometimes needed. If rows or cols are dynamic, you need to define the maximum amount that there can be (you can increase it when you update the game though). These CANNOT be dynamic.

  • getStartData(id): Creates the default data for the gridable at this position. This can be an object, or a regular value.

  • getUnlocked(id): optional. Returns true if the gridable at this position should be visible.

  • getTitle(data, id): optional. Returns text that should displayed at the top in a larger font, based on the position and data of the gridable.

  • getDisplay(data, id): optional. Returns everything that should be displayed on the gridable after the title, based on the position and data of the gridable.

  • getStyle(data, id): optional. Returns CSS to apply to this gridable, in the form of an object where the keys are CSS attributes, and the values are the values for those attributes (both as strings).

  • getCanClick(data, id): optional. A function returning a bool to determine if you can click a gridable, based on its data and position. If absent, you can always click it.

  • onClick(data, id): A function that implements clicking on the gridable, based on its position and data.

  • onHold(data, id): optional A function that is called 20x/sec when the button is held for at least 0.25 seconds.

  • getEffect(data, id): optional. A function that calculates and returns a gridable's effect, based on its position and data. (Whatever that means for a gridable)

  • layer: assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar.

- - + + \ No newline at end of file diff --git a/public/kronos/docs/infoboxes/index.html b/public/kronos/docs/infoboxes/index.html index 4b1d6bab9..66fd69960 100644 --- a/public/kronos/docs/infoboxes/index.html +++ b/public/kronos/docs/infoboxes/index.html @@ -6,8 +6,8 @@ Infoboxes | The Paper Pilot - - + + @@ -26,8 +26,8 @@ etc }

Features:

  • title: The text displayed above the main box. Can be a function to be dynamic, and can use basic HTML.

  • body: The text displayed inside the box. Can be a function to be dynamic, and can use basic HTML.

  • style, titleStyle, bodyStyle: optional. Apply CSS to the infobox, or to the title button or body of the infobox, in the form of an object where the keys are CSS attributes, and the values are the values for those attributes (both as strings).

  • unlocked(): optional. A function returning a bool to determine if the infobox is visible or not. Default is unlocked.

  • layer: assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar

  • id: assigned automagically. It's the "key" which the bar was stored under, for convenient access. The infobox in the example's id is "lore".

- - + + \ No newline at end of file diff --git a/public/kronos/docs/layer-features/index.html b/public/kronos/docs/layer-features/index.html index 0b071337e..2000be260 100644 --- a/public/kronos/docs/layer-features/index.html +++ b/public/kronos/docs/layer-features/index.html @@ -6,8 +6,8 @@ Layer Features | The Paper Pilot - - + + @@ -30,8 +30,8 @@ "prestige-button"() { return {'color': '#AA66AA'} } }
  • deactivated: optional, if this is true, hasUpgrade, hasChallenge, hasAchievement, and hasMilestone will return false for things in the layer, and you will be unable to buy or click things on the layer. You will have to disable effects of buyables, the innate layer effect, and possibly other things yourself.

Custom Prestige type

(All of these can also be used by other prestige types)

  • getResetGain(): mostly for custom prestige type. Returns how many points you should get if you reset now. You can call getResetGain(this.layer, useType = "static") or similar to calculate what your gain would be under another prestige type (provided you have all of the required features in the layer).

  • getNextAt(canMax=false): mostly for custom prestige type. Returns how many of the base currency you need to get to the next point. canMax is an optional variable used with Static-ish layers to differentiate between if it's looking for the first point you can reset at, or the requirement for any gain at all (Supporting both is good). You can also call getNextAt(this.layer, canMax=false, useType = "static") or similar to calculate what your next at would be under another prestige type (provided you have all of the required features in the layer).

  • canReset(): mostly for custom prestige type. Return true only if you have the resources required to do a prestige here.

  • prestigeNotify(): mostly for custom prestige types, returns true if this layer should be subtly highlighted to indicate you can prestige for a meaningful gain.

- - + + \ No newline at end of file diff --git a/public/kronos/docs/main-mod-info/index.html b/public/kronos/docs/main-mod-info/index.html index 2eddd83da..7e147db1b 100644 --- a/public/kronos/docs/main-mod-info/index.html +++ b/public/kronos/docs/main-mod-info/index.html @@ -6,8 +6,8 @@ mod.js | The Paper Pilot - - + + @@ -24,8 +24,8 @@ happiness: new Decimal(72), }}
  • displayThings: An array of functions used to display extra things at the top of the tree tab. Each function returns a string, which is a line to display (with basic HTML support). If a function returns nothing, nothing is displayed (and it doesn't take up a line).

  • isEndgame(): A function to determine if the player has reached the end of the game, at which point the "you win!" screen appears.

Less important things beyond this point!

  • maxTickLength(): Returns the maximum tick length, in milliseconds. Only really useful if you have something that reduces over time, which long ticks mess up (usually a challenge).

  • fixOldSave(): Can be used to modify a save file when loading into a new version of the game. Use this to undo inflation, never forcibly hard reset your players.

- - + + \ No newline at end of file diff --git a/public/kronos/docs/milestones/index.html b/public/kronos/docs/milestones/index.html index f32664474..88d037a0b 100644 --- a/public/kronos/docs/milestones/index.html +++ b/public/kronos/docs/milestones/index.html @@ -6,8 +6,8 @@ Milestones | The Paper Pilot - - + + @@ -26,8 +26,8 @@ etc }

You can use hasMilestone(layer, id) to determine if the player has a given milestone

Milestone features:

  • requirementDescription: A string describing the requirement for unlocking this milestone. Suggestion: Use a "total". It can also be a function that returns updating text. Can use basic HTML.

  • effectDescription: A string describing the reward for having the milestone. You will have to implement the reward elsewhere. It can also be a function that returns updating text. Can use basic HTML.

  • done(): A function returning a boolean to determine if the milestone should be awarded.

  • toggles: optional. Creates toggle buttons that appear on the milestone when it is unlocked. The toggles can toggle a given boolean value in a layer. It is defined as an array of paired items, one pair per toggle. The first is the internal name of the layer the value being toggled is stored in, and the second is the internal name of the variable to toggle. (e.g. [["b", "auto"], ["g", "auto"])

    Tip: Toggles are not de-set if the milestone becomes locked! In this case, you should also check if the player has the milestone.

  • style: optional. Applies CSS to this milestone, in the form of an object where the keys are CSS attributes, and the values are the values for those attributes (both as strings).

  • unlocked(): optional. A function returning a boolean to determine if the milestone should be shown. If absent, it is always shown.

  • layer: assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar.

  • id: assigned automagically. It's the "key" which the milestone was stored under, for convenient access. The milestone in the example's id is 0.

Disaable milestone popups by adding milestonePopups: false to the layer.

- - + + \ No newline at end of file diff --git a/public/kronos/docs/particles/index.html b/public/kronos/docs/particles/index.html index 50278fed4..0b8e24e61 100644 --- a/public/kronos/docs/particles/index.html +++ b/public/kronos/docs/particles/index.html @@ -6,8 +6,8 @@ Particles | The Paper Pilot - - + + @@ -29,8 +29,8 @@ etc... }

Features can be functions or constant. These features will be called when each particle is made, with an id argument, which is assigned based on which of the amount particles being spawned this is. All of these are optional, with a default value.

All distances are in pixels and angles are in degrees, with 0 being up and going clockwise.

  • time: The amount of time, in seconds, that the particle will last. Default is 3.

  • fadeOutTime: The amount of seconds that fading out at the end should take (part of the total lifetime). Default is 1.

  • fadeInTime: The amount of seconds that fading in should take (part of the total lifetime). Default is 0.

  • image: The image the particle should display. "" will display no image. Default is a generic particle.

  • text: Displays text on the particle. Can use basic HTML.

  • style: Lets you apply other CSS styling to the particle.

  • width, height: The dimensions of the particle. Default is 35 and 35.

  • color: Sets the color of the image to this color.

  • angle: The angle that the particle should face. Default is 0.

  • dir: The initial angle that the particles should move in, before spread is factored in. Default is whatever angle is.

  • spread: If there are several particles, they will be spread out by this many degrees, centered on dir. Default is 30.

  • rotation: The amount that the (visual) angle of the particle should change by. Default is 0.

  • speed: The starting speed of the particle. Default is 15.

  • gravity: The amount the particle should accelerate downwards. Default is 0.

  • x, y: The starting coordinates of the particle. Default is at the mouse position.

  • offset: How far from the start each particle should appear. Default is 10.

  • xVel, yVel: Set initially based on other properties, then used to update movement.

  • layer: When changing tabs, if leaving the layer tab, this particle will be erased.

  • You can add other features to particles, but you must impliment their effects yourself.

Function features: These stay as functions and are for more advanced things. They are optional.

  • update(): Called each tick. Lets you do more advanced visual and movement behaviors by changing other properties.
  • onClick(), onMouseOver(), onMouseLeave(): Called when the particle is interacted with.

Other useful things that are not features of the particle object:

  • setDir(particle, dir), setSpeed(particle, speed): Set the speed/direction on a particle.
  • clearParticles(check): Function to delete particles. With no check, it deletes all particles. Check is a function that takes a particle, and returns true if that particle should be deleted.
  • You can use Vue.delete(particles, this.id) to make a particle delete itself.
  • mouseX and mouseY are variables that track the mouse position.
  • sin(x), cos(x), tan(x): functions that do these operations, with x in degrees. (Instead of radians).
  • asin(x), acos(x), atan(x): functions that do these operations, with the returned value in degrees. (instead of radians).
- - + + \ No newline at end of file diff --git a/public/kronos/docs/subtabs-and-microtabs/index.html b/public/kronos/docs/subtabs-and-microtabs/index.html index aa7ed7255..6a7182445 100644 --- a/public/kronos/docs/subtabs-and-microtabs/index.html +++ b/public/kronos/docs/subtabs-and-microtabs/index.html @@ -6,8 +6,8 @@ Subtabs and Microtabs | The Paper Pilot - - + + @@ -44,8 +44,8 @@ } }

Normal subtabs and microtab subtabs both use the same features:

Features:

  • content: The tab layout code for the subtab, in the tab layout format.

  • style: optional. Applies CSS to the whole subtab when switched to, in the form of an "CSS Object", where the keys are CSS attributes, and the values are the values for those attributes (both as strings).

  • buttonStyle: optional. A CSS object, which affects the appearance of the button for that subtab.

  • unlocked(): optional. a function to determine if the button for this subtab should be visible. By default, a subtab is always unlocked. You can't use the "this" keyword in this function.

  • shouldNotify()/prestigeNotify(): optional, if true, the tab button will be highlighted to notify the player that there is something there.

  • glowColor: optional, specifies the color that the subtab glows. If this subtab is causing the main layer to node glow (and it would't otherwise) the node also glows this color. Is NOT overridden by embedding a layer.

  • embedLayer: SIGNIFICANT, the id of another layer. If you have this, it will override "content", "style" and "shouldNotify", instead displaying the entire layer in the subtab.

- - + + \ No newline at end of file diff --git a/public/kronos/docs/trees-and-tree-customization/index.html b/public/kronos/docs/trees-and-tree-customization/index.html index af37f9995..b8b569b8d 100644 --- a/public/kronos/docs/trees-and-tree-customization/index.html +++ b/public/kronos/docs/trees-and-tree-customization/index.html @@ -6,8 +6,8 @@ Trees and tree customization | The Paper Pilot - - + + @@ -21,8 +21,8 @@ ["left", "blank", "right", "blank"] ["a", "b", "blank", "c", "weirdButton"]]

Nodes

Nodes are non-layer buttons that can go in trees. They are defined similarly to layers, but with addNode instead of addLayer.

Features:

  • color: optional, The node's color. (A string in hex format with a #)

  • symbol: optional The text on the button (The id capitalized by default)

  • canClick(): Returns true if the player can click the node. ()

  • onClick(): The function called when the node is clicked.

  • layerShown(): optional, A function returning a bool which determines if this node should be visible. It can also return "ghost", which will hide the layer, but its node will still take up space in its tree.

  • branches: optional. An array of layer/node ids. On a tree, a line will appear from this node to all of the nodes in the list. Alternatively, an entry in the array can be a 2-element array consisting of the id and a color value. The color value can either be a string with a hex color code, or a number from 1-3 (theme-affected colors).

  • nodeStyle: optional. A CSS object, where the keys are CSS attributes, which styles this node on the tree.

  • tooltip() / tooltipLocked(): optional. Functions that return text, which is the tooltip for the node when the layer is unlocked or locked, respectively. By default the tooltips behave the same as in the original Prestige Tree.

  • row: optional, the row that this node appears in (for the default tree).

  • position: optional, Determines the horizontal position of the layer in its row in a default tree. By default, it uses the id, and layers/nodes are sorted in alphabetical order.

- - + + \ No newline at end of file diff --git a/public/kronos/docs/updating-tmt/index.html b/public/kronos/docs/updating-tmt/index.html index 9fc95575a..c83a594f3 100644 --- a/public/kronos/docs/updating-tmt/index.html +++ b/public/kronos/docs/updating-tmt/index.html @@ -6,8 +6,8 @@ Updating The Modding Tree | The Paper Pilot - - + + @@ -18,8 +18,8 @@
Skip to content
On this page

Updating The Modding Tree

This tutorial assumes that you have used the Getting Started Tutorial, and are using Github Desktop and VSCode for your mod.

Here's what you have to do when there's a TMT update:

  1. Look at the changelog. It will warn you if the update will break anything or require any changes. Decide if you want to try to update.

  2. Open Github Desktop, and at the top middle, click "fetch origin". This will make Github Desktop get information about the update.

  3. Click where it says "current branch: master" at the top middle, and at the bottom of the thing that appears, click "choose a branch to merge into master".

  4. Select upstream/master. It will likely say there are conflicts, but you have tools to resolve them. Click "Merge upstream/master into master".

  5. A conflict happens when the things you're trying to merge have both made changes in the same place. Click "open in Visual Studio Code" next to the first file.

  6. Scroll down through the file, and look for the parts highlighted in red and green. One of these is your code, and the other is some code that will be modified by the update. Do your best to try to edit things to keep the updated changes, but keep your content.

  7. Continue to do this for all remaining changes.

  8. Do any other changes required by the update, run the game, fix issues, etc.

- - + + \ No newline at end of file diff --git a/public/kronos/docs/upgrades/index.html b/public/kronos/docs/upgrades/index.html index 47bde88e6..d00325529 100644 --- a/public/kronos/docs/upgrades/index.html +++ b/public/kronos/docs/upgrades/index.html @@ -6,8 +6,8 @@ Upgrades | The Paper Pilot - - + + @@ -26,8 +26,8 @@ etc }

Usually, upgrades should have an id where the first digit is the row and the second digit is the column.

Individual upgrades can have these features:

  • title: optional. Displayed at the top in a larger font. It can also be a function that returns updating text. Can use basic HTML.

  • description: A description of the upgrade's effect. You will also have to implement the effect where it is applied. It can also be a function that returns updating text. Can use basic HTML.

  • effect(): optional. A function that calculates and returns the current values of any bonuses from the upgrade. Can return a value or an object containing multiple values.

  • effectDisplay(): optional. A function that returns a display of the current effects of the upgrade with formatting. Default displays nothing. Can use basic HTML.

  • fullDisplay(): OVERRIDE. Overrides the other displays and descriptions, and lets you set the full text for the upgrade. Can use basic HTML.

  • cost: A Decimal for the cost of the upgrade. By default, upgrades cost the main prestige currency for the layer.

  • unlocked(): optional. A function returning a bool to determine if the upgrade is visible or not. Default is unlocked.

  • onPurchase(): optional. This function will be called when the upgrade is purchased. Good for upgrades like "makes this layer act like it was unlocked first".

  • style: optional. Applies CSS to this upgrade, in the form of an object where the keys are CSS attributes, and the values are the values for those attributes (both as strings).

  • layer: assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar.

  • id: assigned automagically. It's the "key" which the upgrade was stored under, for convenient access. The upgrade in the example's id is 11.

By default, upgrades use the main prestige currency for the layer. You can include these to change them (but it needs to be a Decimal):

  • currencyDisplayName: optional. The name to display for the currency for the upgrade.

  • currencyInternalName: optional. The internal name for that currency.

  • currencyLayer: optional. The internal name of the layer that currency is stored in. If it's not in a layer (like Points), omit. If it's not stored directly in a layer, instead use the next feature.

  • currencyLocation: optional. If your currency is stored in something inside a layer (e.g. a buyable's amount), you can access it this way. This is a function returning the object in "player" that contains the value (like player[this.layer].buyables)

If you want to do something more complicated like upgrades that cost two currencies, you can override the purchase system with these (and you need to use fullDisplay as well)

  • canAfford(): OVERRIDE, a function determining if you are able to buy the upgrade

  • pay(): OVERRIDE, a function that reduces your currencies when you buy the upgrade

- - + + \ No newline at end of file diff --git a/public/lit/Old Things/2.0-format-changes/index.html b/public/lit/Old Things/2.0-format-changes/index.html index af774b5c4..8eea3c3c9 100644 --- a/public/lit/Old Things/2.0-format-changes/index.html +++ b/public/lit/Old Things/2.0-format-changes/index.html @@ -6,8 +6,8 @@ 2.0 format changes | The Paper Pilot - - + + @@ -18,8 +18,8 @@
Skip to content
On this page

2.0 format changes

  • Temp format is changed from temp.something[layer] to temp[layer].something, for consistency
  • Challenges are now saved as an object with the amount of completions in each spot. (This will break saves.)
  • effectDisplay in Challenges and Upgrades no longer takes an argument, and neither does effect for Buyables
  • Buyable cost can take an argument for amount of buyables, but it needs to function if no argument is supplied (it should do the cost for the next purchase).
  • Generation of Points now happens in the main game loop (not in a layer update function), enabled by canGenPoints in game.js.
  • Changed fullLayerReset to layerDataReset, which takes an array of names of values to keep

In addition, many names were changed, mostly expanding abbreviations:

All instances of:

  • chall -> challenge
  • unl -> unlocked
  • upg -> upgrade (besides CSS)
  • amt -> amount
  • desc -> description
  • resCeil -> roundUpCost
  • order -> unlockOrder
  • incr_order -> increaseUnlockOrder

Challenges:

  • desc -> challengeDescription
  • reward -> rewardDescription
  • effect -> rewardEffect
  • effectDisplay -> rewardDisplay
  • active -> challengeActive
- - + + \ No newline at end of file diff --git a/public/lit/README/index.html b/public/lit/README/index.html index 70085a0b4..cc3c7d496 100644 --- a/public/lit/README/index.html +++ b/public/lit/README/index.html @@ -6,8 +6,8 @@ Kronos | The Paper Pilot - - + + @@ -18,8 +18,8 @@
Skip to content
On this page

Kronos

Play here.

Updating the website:

  • git submodule update --remote
  • git add -A
  • git commit -m "Updated kronos"
  • git push
- - + + \ No newline at end of file diff --git a/public/lit/changelog/index.html b/public/lit/changelog/index.html index 79e49c206..17342b3c9 100644 --- a/public/lit/changelog/index.html +++ b/public/lit/changelog/index.html @@ -6,8 +6,8 @@ The Modding Tree changelog: | The Paper Pilot - - + + @@ -18,8 +18,8 @@
Skip to content
On this page

The Modding Tree changelog:

v2.Ï€: Incrementally Updated - 2/5/21

  • Performance improvements.
  • Fixed tooltips overlapping with the top display.
  • Clicking a popup dismisses it immediately.
  • Added support for bulk challenge completions.
  • "Best" is updated automatically.
  • Fixed keeping Decimal values on reset.
  • Code reorganization and style improvements by fudo.

v2.3.5 - 12/21/20

  • Added resetTime, which tracks the time since a layer prestiged or was reset.
  • A layer node will be highlighted red if one of its subtabs is highlighted red.
  • Fixed issues with keeping challenges, buyables, and clickables on reset.
  • Improved the unlocking of custom layers.
  • Other minor fixes.

v2.3.4 - 12/16/20

  • Added a node image feature.
  • Resource display now always shows the amount of the currency the layer's gain is based on.
  • Added spacing between tree nodes.
  • Another attempt to fix tooltip flickering.

v2.3.3 - 12/13/20

  • Fixed the first node in a row always taking up space.
  • layerShown is now optional.
  • All prestige types can now use features for custom prestige types.

v2.3.2 - 12/13/20

  • Fixed achievement/milestone popups.

v2.3.1 - 12/12/20

  • Another attempt to fix flickering tooltips.
  • The "this" keyword should work everywhere except tabFormat arrays (although I may have missed some things).
  • Fixed tree branches not updating when scrolling on the right-side tab.
  • Fixed a spacing issue when a node's symbol is ""
  • Removed some old, unneeded files.

v2.3: Cooler and Newer Edition - 12/10/20

  • Added achievement/milestone popups (thank you to Jacorb for this contribution!)
  • The changelog tab is back, and can be set in mod.js.
  • Layer nodes and respec buttons will not be clicked by pressing "enter".
  • Possible fix for flickering tooltips and strange transitions.
  • The victory screen text is configurable.
  • Added image and textStyle features to achievements.
  • Added an argument to use specific rows in an "upgrades" component.
  • Fixed the comma appearing in the main display when there was no effectDescription
  • Added the ability to easily make a tab that is a collection of layers in subtabs.
  • Improved spacing for embedding layers with subtabs into subtabs.

v2.2.8 - 12/03/20

  • Double-clicking a layer node brings you to the main subtab for that layer.
  • Attempted to fix challenges visually updating a different way.
  • Added a softcap function for use in formulas.
  • Added displayRow feature, which lets layers be shown somewhere separate from where they are in the reset order (e.g. side layers)
  • Fixed autoupgrade issue.

v2.2.7 - 11/30/20

  • Added autoUpgrade feature.
  • resource-display now shows resource gain per second if passiveGain is active.
  • Fixed formatting issues on some large numbers.
  • Better support for using classed objects in player and in layers/tmp.
  • Made hard resetting more effective.
  • Removed Herobrine from getStartClickables.

v2.2.6 - 11/30/20

  • Added goalDescription for challenges and made the new "canComplete" system the standard.
  • Another attempt to fix challenges not visually updating.
  • Fixed side layers not appearing.
  • Fixed getStartClickables again.

v2.2.5 - 11/29/20

  • Added features for overriding the displays and costs/goals of upgrades and challenges to make them fully custom.
  • best, total, and unlocked are always automatically added to layerData (but best and total will only display if you add them yourself).
  • Fixed getStartClickables.

v2.2.4 - 11/28/20

  • Added softcap and softcapPower features (for Normal layers)
  • Offline time limit and default max tick length were fixed (previously the limits were 1000x too large)
  • Added fixOldSaves.
  • You can use HTML in main-display.
  • Fixed a number of minor oddities.

v2.2.3 - 11/28/20

  • Layers will be highlighted if you can finish a challenge.
  • The "can complete challenge" color now overrides the "already completed" color.
  • Button nodes now work as side "layers".
  • Setting a tooltip to "" hides it entirely.

v2.2.2 - 11/22/20

  • Fixed right half of the screen being unclickable in some circumstances.
  • Fixed tree branches being offset.
  • Fix to lastSafeTab.

v2.2.1 - 11/7/20

  • Added a small highlight to layers you can meaningfully prestige on.
  • Added passiveGeneration and autoPrestige features to standardize prestige automation. (The old ways still work, but the new ones work better with other things)
  • Improved milestones visually a bit.
  • "best" and "total" are now only displayed if present in startData.
  • Fixed issues with things not updating visually. (Thank you to to Jacorb!)
  • Side layers and button nodes can now be highlighted.
  • Updated docs on the new tree-related features.

v2.2: Uprooted - 11/7/20

  • You can now embed a layer inside of a subtab or microtab!
  • Added support for hiding or reformatting the tree tab
  • Added non-layer button nodes
  • Added shouldNotify to subtab/microtab buttons. (You can make them highlighted)
  • Added commas to large exponents.
  • Upgrades now only show "currently" if they have an effectDisplay (so not for constant effects).
  • Achievements are part of the default tab format.
  • NaN is now handled more intelligently.
  • Renamed files, and moved less relevant ones to another folder.
  • The "hide completed challenges" setting now only hides challenges at max completions.
  • Thank you to thepaperpilot for fixing errors in docs and improving the infobox appearance!
  • Many other minor fixes.

v2.1.4 - 10/25/20

  • Added an infobox component. Thank you to thepaperpilot for this contribution!
  • Layer type is now optional, and defaults to "none".
  • Improved the look of bars and tab buttons.
  • Improved spacing between layer nodes (also thanks to thepaperpilot!)
  • Fixed the "blank" component breaking if only specifying the height.
  • Fixed some numbers not displaying with enough digits.
  • Made a few more things able to be functions.
  • A few other minor fixes.

v2.1.3.1 - 10/21/20

  • Fixed the update function.

v2.1.3 - 10/21/20

  • gainMult and gainExp are now optional.
  • Layer unlocking is now kept on reset.
  • Game should start up faster.
  • Layer updates now have a determined order and starts with earlier-rowed layers.
  • Automation now has a determined order and starts with later-rowed layers.
  • Fixed issues with resetting clickables and challenges.
  • Commas should no longer appear in the decimal places of a number.
  • Fixed potential issue in displaying the tree.

v2.1.2 - 10/19/20

  • Added buyUpgrade function (buyUpg still works though)
  • Added author name to modInfo.
  • Fix to crash caused when the name of a subtab or microtab is changed.
  • Fixes to outdated information in docs.
  • Improvements to Discord links.
  • Thank you to thepaperpilot for contributing to this update!

v2.1.1 - 10/17/20

  • Added resource-display component, which displays the base currency for the prestige layer, as well as the best and/or total of this layer's prestige currency.
  • Fixed the value for the base currency not updating in resource-display.

v2.1: We should have thought of this sooner! - 10/17/20

  • Moved most of the code users will want to edit to mod.js, added documentation for it.
    • Specifically, modInfo, VERSION, canGenPoints, getPointGen, and maxTickLength
  • Added getStartPoints()
  • Added the ability to store non-layer-related data
  • Added the ability to display more things at the top of the tree tab below points.
  • Made the endgame condition customizable
  • Added "sell one" and "sell all" buttons for buyables.
  • Moved the old "game" to demo.js, and replaced it with a minimal game that won't cause issues when edited.
  • Fixed issues with version number
  • Fixed number formatting issue making things like "10e9" appear.

v2.0.5 - 10/16/20

  • Made more features (including prestige parameters) able to be dynamic.
  • Layer nodes can be hidden but still take up space with "ghost" visibility
  • Added clickableEffect for real.
  • Fixed some visual issues with bars.
  • A few other minor tweaks and improvements.

v2.0.4 - 10/16/20

  • Fixed HTML on buttons interfering with clicking on them.

v2.0.3 - 10/16/20

  • Fixed hotkeys not displaying in info.
  • Fixed the game supressing all external hotkeys.
  • You can use more things as currencies for upgrade costs and challenge goals using currencyLocation.
  • Added maxTickLength, which can be used to prevent offline time or tab-switching from breaking time-limit based mechanics.
  • Made buyable respec buttons and clickable "master" buttons their own components, and gave them a hide/show feature.
  • Added a general "tooltip" feature for achievements.

v2.0.2 - 10/15/20

  • Branches are now dynamic (they can be functions).
  • Fixed a crash related to offline time.
  • Fixed links being too wide.

v2.0.1 - 10/15/20

  • Fixed side layers appearing multiple times.

v2.0: The Pinnacle of Achievement Mountain - 10/15/20

  • Added progress bars, which are highly customizable and can be horizontal or vertical!
  • Added "side layers", displayed smaller and off to the side, and don't get reset by default. They can be used for global achievements and statistics. Speaking of which...
  • Added achievements!
  • Added clickables, a more generalized variant of buyables.
  • Almost every value in layer data can be either a function or a constant value!
  • Added support for multiple completions of challenges.
  • Added "none" prestige type, which removes the need for any other prestige-related features.
  • The points display and other gui elements stay at the top of the screen when the tree scrolls.
  • Added getter/setter functions for the amounts and effects of most Big Features
  • Moved modInfo to game.js, added a spot in modInfo for a Discord link, changelog link. Also added a separate mod version from the TMT version in VERSION.
  • Tree structure is based on layer data, no index.html editing is needed.
  • Tmp does not need to be manually updated.
  • You don't have to have the same amount of upgrades in every row (and challs and buyables)
  • "unlocked" is optional for all Big Components (defaults to true).
  • All displays will update correctly.
  • Changelog is no longer in index.html at all.
  • Generation of Points now happens in the main game loop
  • Changed the reset functions to make keeping things easier
  • Renamed many things to increase readability (see the list in the link below)
  • Improved documentation based on feedback

v1.3.5:

  • Completely automated convertToDecimal, now you never have to worry about it again.
  • Branches can be defined without a color id. But they can also use hex values for color ids!
  • Created a tutorial for getting started with TMT and Github.
  • Page title is now automatically taken from mod name.

v1.3.4 - 10/8/20

  • Added "midsection" feature to add things to a tab's layout while still keeping the standard layout.
  • Fix for being able to buy more buyables than you should.

v1.3.3 - 10/7/20

  • Fix for the "order of operations" issue in temp.

v1.3.1 - 10/7/20

  • Added custom CSS and tooltips for Layer Nodes.
  • Added custom CSS for upgrades, buyables, milestones, and challenges, both individually and layer-wide.
  • You can now use HTML in most display text!
  • You can now make milestones unlockable and not display immediately.
  • Fixed importing saves, and issue with upgrades not appearing, and probably more.
  • Optional "name" layer feature, used in confirmation messages.

v1.3: Tabception... ception! - 10/7/20

  • Added subtabs! And also a Micro-tab component to let you make smaller subtab-esque areas anywhere.
  • Added a "custom" prestige formula type, and a number of features to support it.
  • Added points/sec display (can be disabled).
  • Added h-line, v-line and image-display components, plus components for individual upgrades, challenges, and milestones.
  • Added upgEffect, buyableEffect, and challEffect functions.
  • Added "hide completed challenges" setting.
  • Moved old changelogs to a separate place.
  • Fixed hasMilestone and incr_order.
  • Static layers now show the currency amount needed for the next one if you can buy max.

v1.2.4 - 10/4/20

  • Layers are now highlighted if you can buy an upgrade, and a new feature, shouldNotify, lets you make it highlight other ways.
  • Fixed bugs with hasUpg, hasChall, hasMilestone, and inChallenge.
  • Changed the sample code to use the above functions for convenience.

v1.2.3 - 10/3/20

  • Added a row component, which displays a list of objects in a row.
  • Added a column component, which displays a list of objects in a column (useful within a row).
  • Changed blanks to have a customizable width and height.

v1.2: This Changes Everything! - 10/3/20

  • Many layer features can now be static values or functions. (This made some formats change, which will break old things)
  • You can now use the "this" keyword, to make code easier to transfer when making new layers.
  • Also added "this.layer", which is the current layer's name, and works on existing subfeatures (e.g. individual upgrades) as well! Subfeatures also have "this.id".
  • Fixed a big save issue. If you use a unique mod id, your save will never conflict with other mods.
  • Added a configurable offline time limit in modinfo at the top of index.html. (default 1 hour)
  • Added a few minor features, and updated the docs with new information.

v1.1.1:

  • You can define hotkeys directly from layer config.

v1.1: Enhanced Edition

  • Added "Buyables", which can function like Space Buildings or Enhancers.
  • Custom CSS can now be used on any component! Make the third argument an object with CSS parameters.
  • Lots of minor good things.

v1.0:

  • First release.
- - + + \ No newline at end of file diff --git a/public/lit/docs/!general-info/index.html b/public/lit/docs/!general-info/index.html index 07cf0e751..0100f04a9 100644 --- a/public/lit/docs/!general-info/index.html +++ b/public/lit/docs/!general-info/index.html @@ -6,8 +6,8 @@ The-Modding-Tree | The Paper Pilot - - + + @@ -18,8 +18,8 @@
Skip to content
On this page

The-Modding-Tree

The main way to add content is through creating layers. You can either add a layer directly in the layers object in layerSupport.js, or declare it in another file and register it by calling addLayer(layername, layerdata). There is an example layer registration in layers.js showing the recommended method. It is just an example and can be freely deleted. You can also use it as a reference or a base for your own layers.

The first thing you need to do is fill out the modInfo object at the top of mod.js to set your mod's name, ID (a string), and other information. A unique modId will prevent your mod's saves from conflicting with other mods. Note that changing this after people have started playing will reset their saves.

Most of the time, you won't need to dive deep into the code to create things, but you still can if you really want to, for example to add new Vue components in v.js.

The Modding Tree uses break_eternity.js to store large values. This means that many numbers are Decimal objects, and must be treated differently. For example, you have to use new Decimal(x) to create a Decimal value instead of a plain number, and perform operations on them by calling functions. e.g, instead of x = x + y, use x = x.add(y). Keep in mind this also applies to comparison operators, which should be replaced with calling the .gt, .gte, .lt, .lte, .eq, and .neq functions. See the break_eternity.js docs for more details on working with Decimal values.

Almost all values can be either a constant value, or a dynamic value. Dynamic values are defined by putting a function that returns what the value should be at any given time.

All display text can use basic HTML elements (But you can't use most Vue features there).

While reading this documentation, the following key will be used when describing features:

  • No label: This is required and the game may crash if it isn't included.
  • sometimes required: This is may be required, depending on other things in the layer.
  • optional: You can leave this out if you don't intend to use that feature for the layer.
  • assigned automagically: This value will be set automatically and override any value you set.
  • deprecated: This feature is not recommended to be used anymore, and may be removed in future versions of TMT.

Table of Contents

General

  • Getting Started: Getting your own copy of the code set up with Github Desktop.
  • Main mod info: How to set up general things for your mod in mod.js.
  • Basic layer breakdown: Breaking down the components of a layer with minimal features.
  • Layer features: Explanations of all of the different properties that you can give a layer.
  • Custom Tab Layouts: An optional way to give your tabs a different layout. You can even create entirely new components to use.
  • Custom game layouts: You can get rid of the tree tab, add buttons and other things to the tree, or even customize the tab's layout like a layer tab.
  • Updating TMT: Using Github Desktop to update your mod's version of TMT.

Common components

  • Upgrades: How to create upgrades for a layer.
  • Milestones: How to create milestones for a layer.
  • Buyables: Create rebuyable upgrades for your layer (with the option to make them respec-able). Can be used to make Enhancers or Space Buildings.
  • Clickables: A more generalized variant of buyables, for any kind of thing that is sometimes clickable. Between these and Buyables, you can do just about anything.

Other components and features

  • Challenges: How to create challenges for a layer.
  • Bars: Display some information as a progress bar, gauge, or similar. They are highly customizable, and can be horizontal and vertical as well.
  • Subtabs and Microtabs: Create subtabs for your tabs, as well as "microtab" components that you can put inside the tabs. You can even use them to embed a layer inside another layer!
  • Achievements: How to create achievements for a layer (or for the whole game).
  • Infoboxes: Boxes containing text that can be shown or hidden.
  • Trees: Make your own trees. You can make non-layer button nodes too!
- - + + \ No newline at end of file diff --git a/public/lit/docs/achievements/index.html b/public/lit/docs/achievements/index.html index 01bafe192..8f2cb6796 100644 --- a/public/lit/docs/achievements/index.html +++ b/public/lit/docs/achievements/index.html @@ -6,8 +6,8 @@ Achievements | The Paper Pilot - - + + @@ -27,8 +27,8 @@ etc }

Each achievement should have an id where the first digit is the row and the second digit is the column.

Individual achievement can have these features:

  • name: optional. displayed at the top of the achievement. The only visible text. It can also be a function that returns updating text. Can use basic HTML.

  • done(): A function returning a boolean to determine if the achievement should be awarded.

  • tooltip: Default tooltip for the achievement, appears when it is hovered over. Should convey the goal and any reward for completing the achievement. It can also be a function that returns updating text. Can use basic HTML. Setting this to "" disables the tooltip.

  • effect(): optional. A function that calculates and returns the current values of any bonuses from the achievement. Can return a value or an object containing multiple values.

  • unlocked(): optional. A function returning a bool to determine if the achievement is visible or not. Default is unlocked.

  • onComplete() - optional. this function will be called when the achievement is completed.

  • image: optional, puts the image from the given URL (relative or absolute) in the achievement

  • style: optional. Applies CSS to this achievement, in the form of an object where the keys are CSS attributes, and the values are the values for those attributes (both as strings).

  • textStyle: optional. Applies CSS to the text, in the form of an object where the keys are CSS attributes, and the values are the values for those attributes (both as strings).

  • layer: assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar.

  • id: assigned automagically. It's the "key" which the achievement was stored under, for convenient access. The achievement in the example's id is 11.

  • goalTooltip: optional, deprecated. Appears when the achievement is hovered over and locked, overrides the basic tooltip. This is to display the goal (or a hint). It can also be a function that returns updating text. Can use basic HTML.

  • doneTooltip: optional, deprecated. Appears when the achievement is hovered over and completed, overrides the basic tooltip. This can display what the player achieved (the goal), and the rewards, if any. It can also be a function that returns updating text. Can use basic HTML.

Disable achievement popups by adding achievementsPopups: false to the layer.

- - + + \ No newline at end of file diff --git a/public/lit/docs/bars/index.html b/public/lit/docs/bars/index.html index 26159df86..04fefd79a 100644 --- a/public/lit/docs/bars/index.html +++ b/public/lit/docs/bars/index.html @@ -6,8 +6,8 @@ Bars | The Paper Pilot - - + + @@ -28,8 +28,8 @@ etc }

Features:

  • direction: UP, DOWN, LEFT, or RIGHT (not strings). Determines the direction that the bar is filled as it progresses. RIGHT means from left to right.

  • width, height: The size in pixels of the bar, but as numbers (no "px" at the end).

  • progress(): A function that returns the portion of the bar that is filled, from "empty" at 0 to "full" at 1, updating automatically. (Nothing bad happens if the value goes out of these bounds, and it can be a number or Decimal)

  • display(): optional. A function that returns text to be displayed on top of the bar, can use HTML.

  • unlocked(): optional. A function returning a bool to determine if the bar is visible or not. Default is unlocked.

  • baseStyle, fillStyle, borderStyle, textStyle: Optional, Apply CSS to the unfilled portion, filled portion, border, and display text on the bar, in the form of an object where the keys are CSS attributes, and the values are the values for those attributes (both as strings).

  • layer: assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar.

  • id: assigned automagically. It's the "key" which the bar was stored under, for convenient access. The bar in the example's id is "bigBar".

- - + + \ No newline at end of file diff --git a/public/lit/docs/basic-layer-breakdown/index.html b/public/lit/docs/basic-layer-breakdown/index.html index 929194e6d..fba069c8c 100644 --- a/public/lit/docs/basic-layer-breakdown/index.html +++ b/public/lit/docs/basic-layer-breakdown/index.html @@ -6,8 +6,8 @@ Basic layer breakdown | The Paper Pilot - - + + @@ -46,8 +46,8 @@ layerShown() { return true } // Returns a bool for if this layer's node should be visible in the tree. }) - - + + \ No newline at end of file diff --git a/public/lit/docs/buyables/index.html b/public/lit/docs/buyables/index.html index 0c4147fbb..8c34efc36 100644 --- a/public/lit/docs/buyables/index.html +++ b/public/lit/docs/buyables/index.html @@ -6,8 +6,8 @@ Buyables | The Paper Pilot - - + + @@ -33,8 +33,8 @@ etc }

Features:

  • title: optional. displayed at the top in a larger font. It can also be a function that returns updating text.

  • cost(): cost for buying the next buyable. Can have an optional argument "x" to calculate the cost of the x+1th object, but needs to use "current amount" as a default value for x. (x is a Decimal). Can return an object if there are multiple currencies.

  • effect(): optional. A function that calculates and returns the current values of bonuses of this buyable. Can return a value or an object containing multiple values.

  • display(): A function returning everything that should be displayed on the buyable after the title, likely including the description, amount bought, cost, and current effect. Can use basic HTML.

  • unlocked(): optional. A function returning a bool to determine if the buyable is visible or not. Default is unlocked.

  • canAfford(): A function returning a bool to determine if you can buy one of the buyables.

  • buy(): A function that implements buying one of the buyable, including spending the currency.

  • buyMax(): optional. A function that implements buying as many of the buyable as possible.

  • style: optional. Applies CSS to this buyable, in the form of an object where the keys are CSS attributes, and the values are the values for those attributes (both as strings).

  • layer: assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar.

  • id: assigned automagically. It's the "key" which the buyable was stored under, for convenient access. The buyable in the example's id is 11.

Sell One/Sell All:

Including a sellOne or sellAll function will cause an additional button to appear beneath the buyable. They are functionally identical, but "sell one" appears above "sell all". You can also use them for other things.

  • sellOne/sellAll(): optional. Called when the button is pressed. The standard use would be to decrease/reset the amount of the buyable, and possibly return some currency to the player.

  • canSellOne/canSellAll(): optional. booleans determining whether or not to show the buttons. If "canSellOne/All" is absent but "sellOne/All" is present, the appropriate button will always show.

- - + + \ No newline at end of file diff --git a/public/lit/docs/challenges/index.html b/public/lit/docs/challenges/index.html index 0a108b06b..91d807d4b 100644 --- a/public/lit/docs/challenges/index.html +++ b/public/lit/docs/challenges/index.html @@ -6,8 +6,8 @@ Challenges | The Paper Pilot - - + + @@ -29,8 +29,8 @@ etc }

Each challenge should have an id where the first digit is the row and the second digit is the column.

Individual Challenges can have these features:

  • name: Name of the challenge, can be a string or a function. Can use basic HTML.

  • challengeDescription: A description of what makes the challenge a challenge. You will need to implement these elsewhere. It can also be a function that returns updating text. Can use basic HTML.

  • goalDescription: A description of the win condition for the challenge. It can also be a function that returns updating text. Can use basic HTML. (Optional if using the old goal system)

  • canComplete(): A function that returns true if you meet the win condition for the challenge. Returning a number will allow bulk completing the challenge. (Optional if using the old goal system)

  • rewardDescription: A description of the reward's effect. You will also have to implement the effect where it is applied. It can also be a function that returns updating text. Can use basic HTML.

  • rewardEffect(): optional. A function that calculates and returns the current values of any bonuses from the reward. Can return a value or an object containing multiple values. Can use basic HTML.

  • rewardDisplay(): optional. A function that returns a display of the current effects of the reward with formatting. Default behavior is to just display the a number appropriately formatted.

  • fullDisplay(): OVERRIDE. Overrides the other displays and descriptions, and lets you set the full text for the challenge. Can use basic HTML.

  • unlocked(): optional. A function returning a bool to determine if the challenge is visible or not. Default is unlocked.

  • onComplete() - optional. this function will be called when the challenge is completed when previously incomplete.

  • countsAs: optional. If a challenge combines the effects of other challenges in this layer, you can use this. An array of challenge ids. The player is effectively in all of those challenges when in the current one.

  • completionLimit: optional. the amount of times you can complete this challenge. Default is 1 completion.

  • style: optional. Applies CSS to this challenge, in the form of an object where the keys are CSS attributes, and the values are the values for those attributes (both as strings).

  • layer: assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar

  • id: assigned automagically. It's the "key" which the challenge was stored under, for convenient access. The challenge in the example's id is 11.

The old goal system uses these features:

  • goal: deprecated, A Decimal for the amount of currency required to beat the challenge. By default, the goal is in basic Points. The goal can also be a function if its value changes.

  • currencyDisplayName: deprecated. the name to display for the currency for the goal

  • currencyInternalName: deprecated. the internal name for that currency

  • currencyLayer: deprecated. the internal name of the layer that currency is stored in. If it's not in a layer, omit. If it's not stored directly in a layer, instead use the next feature.

  • currencyLocation(): deprecated. if your currency is stored in something inside a layer (e.g. a buyable's amount), you can access it this way. This is a function returning the object in "player" that contains the value (like player[this.layer].buyables)

- - + + \ No newline at end of file diff --git a/public/lit/docs/clickables/index.html b/public/lit/docs/clickables/index.html index 423448970..d65585e51 100644 --- a/public/lit/docs/clickables/index.html +++ b/public/lit/docs/clickables/index.html @@ -6,8 +6,8 @@ Clickables | The Paper Pilot - - + + @@ -27,8 +27,8 @@ etc }

Features:

  • title: optional. displayed at the top in a larger font. It can also be a function that returns updating text.

  • effect(): optional. A function that calculates and returns the current values of bonuses of this clickable. Can return a value or an object containing multiple values.

  • display(): A function returning everything that should be displayed on the clickable after the title, likely changing based on its state. Can use basic HTML.

  • unlocked(): optional. A function returning a bool to determine if the clickable is visible or not. Default is unlocked.

  • canClick(): A function returning a bool to determine if you can click the clickable.

  • onClick(): A function that implements clicking one of the clickable.

  • style: optional. Applies CSS to this clickable, in the form of an object where the keys are CSS attributes, and the values are the values for those attributes (both as strings).

  • layer: assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar.

  • id: assigned automagically. It's the "key" which the clickable was stored under, for convenient access. The clickable in the example's id is 11.

You can also use these features on the clickables object to add a button above all the clickables, for implementing a respec button or similar.

  • masterButtonPress(): optional. If present, an additional button will appear above the clickables. Pressing it will call this function.

  • masterButtonText: optional. Text to display on the Master Button.

  • showMasterButton(): optional. A function determining whether or not to show the button. Defaults to true if absent.

- - + + \ No newline at end of file diff --git a/public/lit/docs/custom-tab-layouts/index.html b/public/lit/docs/custom-tab-layouts/index.html index c2c696017..5f0c34c99 100644 --- a/public/lit/docs/custom-tab-layouts/index.html +++ b/public/lit/docs/custom-tab-layouts/index.html @@ -6,8 +6,8 @@ Custom tab layouts | The Paper Pilot - - + + @@ -32,8 +32,8 @@ "upgrades" ]

It is a list of components, which can be either just a name, or an array with arguments. If it's an array, the first item is the name of the component, the second is the data passed into it, and the third (optional) applies a CSS style to it with a "CSS object", where the keys are CSS attributes.

These are the existing components, but you can create more in components.js:

  • display-text: Displays some text (can use basic HTML). The argument is the text to display. It can also be a function that returns updating text.

  • raw-html: Displays some basic HTML, can also be a function.

  • blank: Adds empty space. The default dimensions are 8px x 17px. The argument changes the dimensions. If it's a single value (e.g. "20px"), that determines the height. If you have a pair of arguments, the first is width and the second is height.

  • row: Display a list of components horizontally. The argument is an array of components in the tab layout format.

  • column: Display a list of components vertically. The argument is an array of components in the tab layout format. This is useful to display columns within a row.

  • main-display: The text that displays the main currency for the layer and its effects.

  • resource-display: The text that displays the currency that this layer is based on, as well as the best and/or total values for this layer's prestige currency (if they are put in startData for this layer).

  • prestige-button: The argument is a string that the prestige button should say before the amount of currency you will gain. It can also be a function that returns updating text.

  • upgrades: The layer's upgrades. The argument is optional, and is a the list of rows this component should include, if it doesn't have all of them.

  • milestones, challenges, achievements: Display the upgrades, milestones, and challenges for a layer, as appropriate.

  • buyables, clickables: Display all of the buyables/clickables for this layer, as appropriate. The argument is optional and is the size of the boxes in pixels.

  • microtabs: Display a set of subtabs for an area. The argument is the name of the set of microtabs in the "microtabs" feature.

  • bar: Display a bar. The argument is the id of the bar to display.

  • infobox: Display an infobox. The argument is the id of the infobox to display.

  • tree: Displays a tree. The argument is an array of arrays containing the names of the nodes in the tree (first by row, then by column) See here for more information on tree layouts and nodes!

  • toggle: A toggle button that toggles a bool value. The data is a pair that identifies what bool to toggle, e.g. [layer, id]

The rest of the components are sub-components. They can be used just like other components, but are typically part of another component.

  • upgrade, milestone, challenge, buyable, clickable, achievement: An individual upgrade, challenge, etc. The argument is the id. This can be used if you want to have upgrades split up across multiple subtabs, for example.

  • respec-button, master-button: The respec and master buttons for buyables and clickables, respectively.

  • sell-one, sell-all: The "sell one" and "sell all" for buyables, respectively. The argument is the id of the buyable.

- - + + \ No newline at end of file diff --git a/public/lit/docs/getting-started/index.html b/public/lit/docs/getting-started/index.html index 02e1f1776..98256582c 100644 --- a/public/lit/docs/getting-started/index.html +++ b/public/lit/docs/getting-started/index.html @@ -6,8 +6,8 @@ Getting started | The Paper Pilot - - + + @@ -18,8 +18,8 @@
Skip to content
On this page

Getting started

Welcome to The Modding Tree!

Using the Modding Tree, at its simplest level, just requires getting a copy of it onto your computer. However, if you do it the right way, it will help in many ways.

Don't let the word "Github" scare you away. It's actually much easier to use than most people think, especially because most people use it the hard way. The key is Github Desktop, which lets you do everything you need to, without even touching the command line.

The benefits of using Github:

  • It makes it much, much easier to update The Modding Tree.
  • You can share your work without any extra effort using githack, or with a bit more effort, set up a github.io site.
  • It lets you undo changes to your code, and to have multiple versions of it.
  • It lets you collaborate with other people, if you want to.

Getting set up with Github Desktop, Visual Studio Code, and The Modding Tree:

  1. Install Github Desktop and Visual Studio Code.

  2. Make a Github account. You can handle this on your own.

  3. Log in on your browser, and go back to The Modding Tree page. At the top right, there should be a button that says "fork". Click on it, and then on your username. You now have your own fork, or copy, of The Modding Tree.

  4. Open Github Desktop and log in. Ignore everything else and choose "clone a repository". A "repository" is basically a "Github project", like The Modding Tree. "Cloning" is downloading a copy of the repository to your computer.

  5. Look for The Modding Tree in the list of repositiories (it should be the only one) and click "clone".

  6. Select that you're using it for your own purposes, and click continue. It will download the files and handle everything.

Using your repository

  1. Click on "show in explorer/finder" to the right, and then open the index.html file in the folder. The page should open up on your browser. This will let you view and test your project locally!

  2. To edit your project, click "open in VSCode" in Github Desktop.

  3. Open mod.js in VSCode, and look at the top part where it has a "modInfo" object. Fill in your mod's name to whatever you want, and change the id as well. (It can be any string value, and it's used to determine where the savefile is. Make it something that's probably unique, and don't change it again later or else it'll effectively wipe existing saves)

  4. Save mod.js, and then reload index.html in your browser. The title on the tab, as well as on the info page, will now be updated! You can reload the page every time you change the code to test it quickly and easily.

  5. Go back to Github Desktop. It's time to save your changes into the git system by making a "commit". This basically saves your work and creates a snapshot of what your code looks like at this moment, allowing you to look back at it later.

  6. At the bottom right corner, add a summary of your changes, and then click "commit to master".

  7. Finally, at the top middle, click "push origin" to push your changes out onto the online repository.

  8. You can view your project on line, or share it with others, by going to https://raw.githack.com/[YOUR-GITHUB-USERNAME]/The-Modding-Tree/master/index.html

And now, you have successfully used Github! You can look at the documentation to see how The Modding Tree's system works and to make your mod a reality.

- - + + \ No newline at end of file diff --git a/public/lit/docs/infoboxes/index.html b/public/lit/docs/infoboxes/index.html index b0c78506d..26bc4daa4 100644 --- a/public/lit/docs/infoboxes/index.html +++ b/public/lit/docs/infoboxes/index.html @@ -6,8 +6,8 @@ Infoboxes | The Paper Pilot - - + + @@ -26,8 +26,8 @@ etc }

Features:

  • title: The text displayed above the main box. Can be a function to be dynamic, and can use basic HTML.

  • body: The text displayed inside the box. Can be a function to be dynamic, and can use basic HTML.

  • style, titleStyle, bodyStyle: optional. Apply CSS to the infobox, or to the title button or body of the infobox, in the form of an object where the keys are CSS attributes, and the values are the values for those attributes (both as strings).

  • unlocked(): optional. A function returning a bool to determine if the infobox is visible or not. Default is unlocked.

  • layer: assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar

  • id: assigned automagically. It's the "key" which the bar was stored under, for convenient access. The infobox in the example's id is "lore".

- - + + \ No newline at end of file diff --git a/public/lit/docs/layer-features/index.html b/public/lit/docs/layer-features/index.html index 94e40a8a4..7e1ed0495 100644 --- a/public/lit/docs/layer-features/index.html +++ b/public/lit/docs/layer-features/index.html @@ -6,8 +6,8 @@ Layer Features | The Paper Pilot - - + + @@ -29,8 +29,8 @@ "prestige-button"() { return {'color': '#AA66AA'} } }

Custom Prestige type

(All of these can also be used by other prestige types)

  • getResetGain(): mostly for custom prestige type. Returns how many points you should get if you reset now. You can call getResetGain(this.layer, useType = "static") or similar to calculate what your gain would be under another prestige type (provided you have all of the required features in the layer).

  • getNextAt(canMax=false): mostly for custom prestige type. Returns how many of the base currency you need to get to the next point. canMax is an optional variable used with Static-ish layers to differentiate between if it's looking for the first point you can reset at, or the requirement for any gain at all (Supporting both is good). You can also call getNextAt(this.layer, canMax=false, useType = "static") or similar to calculate what your next at would be under another prestige type (provided you have all of the required features in the layer).

  • canReset(): mostly for custom prestige type. Return true only if you have the resources required to do a prestige here.

  • prestigeNotify(): mostly for custom prestige types, returns true if this layer should be subtly highlighted to indicate you can prestige for a meaningful gain.

- - + + \ No newline at end of file diff --git a/public/lit/docs/main-mod-info/index.html b/public/lit/docs/main-mod-info/index.html index 6747f60e7..5298f4f86 100644 --- a/public/lit/docs/main-mod-info/index.html +++ b/public/lit/docs/main-mod-info/index.html @@ -6,8 +6,8 @@ mod.js | The Paper Pilot - - + + @@ -24,8 +24,8 @@ happiness: new Decimal(72), }}
  • displayThings: An array of functions used to display extra things at the top of the tree tab. Each function returns a string, which is a line to display (with basic HTML support). If a function returns nothing, nothing is displayed (and it doesn't take up a line).

  • isEndgame(): A function to determine if the player has reached the end of the game, at which point the "you win!" screen appears.

Less important things beyond this point!

  • maxTickLength(): Returns the maximum tick length, in milliseconds. Only really useful if you have something that reduces over time, which long ticks mess up (usually a challenge).
- - + + \ No newline at end of file diff --git a/public/lit/docs/milestones/index.html b/public/lit/docs/milestones/index.html index 0c0dcc29e..e89bc40b3 100644 --- a/public/lit/docs/milestones/index.html +++ b/public/lit/docs/milestones/index.html @@ -6,8 +6,8 @@ Milestones | The Paper Pilot - - + + @@ -26,8 +26,8 @@ etc }

You can use hasMilestone(layer, id) to determine if the player has a given milestone

Milestone features:

  • requirementDescription: A string describing the requirement for unlocking this milestone. Suggestion: Use a "total". It can also be a function that returns updating text. Can use basic HTML.

  • effectDescription: A string describing the reward for having the milestone. You will have to implement the reward elsewhere. It can also be a function that returns updating text. Can use basic HTML.

  • done(): A function returning a boolean to determine if the milestone should be awarded.

  • toggles: optional. Creates toggle buttons that appear on the milestone when it is unlocked. The toggles can toggle a given boolean value in a layer. It is defined as an array of paired items, one pair per toggle. The first is the internal name of the layer the value being toggled is stored in, and the second is the internal name of the variable to toggle. (e.g. [["b", "auto"], ["g", "auto"])

    Tip: Toggles are not de-set if the milestone becomes locked! In this case, you should also check if the player has the milestone.

  • style: optional. Applies CSS to this milestone, in the form of an object where the keys are CSS attributes, and the values are the values for those attributes (both as strings).

  • unlocked(): optional. A function returning a boolean to determine if the milestone should be shown. If absent, it is always shown.

  • layer: assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar.

  • id: assigned automagically. It's the "key" which the milestone was stored under, for convenient access. The milestone in the example's id is 0.

Disaable milestone popups by adding milestonePopups: false to the layer.

- - + + \ No newline at end of file diff --git a/public/lit/docs/subtabs-and-microtabs/index.html b/public/lit/docs/subtabs-and-microtabs/index.html index 4de0ad981..d436372f4 100644 --- a/public/lit/docs/subtabs-and-microtabs/index.html +++ b/public/lit/docs/subtabs-and-microtabs/index.html @@ -6,8 +6,8 @@ Subtabs and Microtabs | The Paper Pilot - - + + @@ -44,8 +44,8 @@ } }

Normal subtabs and microtab subtabs both use the same features:

Features:

  • content: The tab layout code for the subtab, in the tab layout format.

  • style: optional. Applies CSS to the whole subtab when switched to, in the form of an "CSS Object", where the keys are CSS attributes, and the values are the values for those attributes (both as strings).

  • buttonStyle: optional. A CSS object, which affects the appearance of the button for that subtab.

  • unlocked(): optional. a function to determine if the button for this subtab should be visible. By default, a subtab is always unlocked. You can't use the "this" keyword in this function.

  • shouldNotify(): optional, if true, the tab button will be highlighted to notify the player that there is something there.

  • embedLayer: SIGNIFICANT, the id of another layer. If you have this, it will override "content", "style" and "shouldNotify", instead displaying the entire layer in the subtab.

- - + + \ No newline at end of file diff --git a/public/lit/docs/trees-and-tree-customization/index.html b/public/lit/docs/trees-and-tree-customization/index.html index 2087ae608..419b7fbf2 100644 --- a/public/lit/docs/trees-and-tree-customization/index.html +++ b/public/lit/docs/trees-and-tree-customization/index.html @@ -6,8 +6,8 @@ Trees and tree customization | The Paper Pilot - - + + @@ -21,8 +21,8 @@ ["left", "blank", "right", "blank"] ["a", "b", "blank", "c", "weirdButton"]]

Nodes

Nodes are non-layer buttons that can go in trees. They are defined similarly to layers, but with addNode instead of addLayer.

Features:

  • color: optional, The node's color. (A string in hex format with a #)

  • symbol: optional The text on the button (The id capitalized by default)

  • canClick(): Returns true if the player can click the node. ()

  • onClick(): The function called when the node is clicked.

  • layerShown(): optional, A function returning a bool which determines if this node should be visible. It can also return "ghost", which will hide the layer, but its node will still take up space in its tree.

  • branches: optional. An array of layer/node ids. On a tree, a line will appear from this node to all of the nodes in the list. Alternatively, an entry in the array can be a 2-element array consisting of the id and a color value. The color value can either be a string with a hex color code, or a number from 1-3 (theme-affected colors).

  • nodeStyle: optional. A CSS object, where the keys are CSS attributes, which styles this node on the tree.

  • tooltip() / tooltipLocked(): optional. Functions that return text, which is the tooltip for the node when the layer is unlocked or locked, respectively. By default the tooltips behave the same as in the original Prestige Tree.

  • row: optional, the row that this node appears in (for the default tree).

  • position: optional, Determines the horizontal position of the layer in its row in a default tree. By default, it uses the id, and layers/nodes are sorted in alphabetical order.

- - + + \ No newline at end of file diff --git a/public/lit/docs/updating-tmt/index.html b/public/lit/docs/updating-tmt/index.html index 48636e63d..28a8f7de4 100644 --- a/public/lit/docs/updating-tmt/index.html +++ b/public/lit/docs/updating-tmt/index.html @@ -6,8 +6,8 @@ Updating The Modding Tree | The Paper Pilot - - + + @@ -18,8 +18,8 @@
Skip to content
On this page

Updating The Modding Tree

This tutorial assumes that you have used the Getting Started Tutorial, and are using Github Desktop and VSCode for your mod.

Here's what you have to do when there's a TMT update:

  1. Look at the changelog. It will warn you if the update will break anything or require any changes. Decide if you want to try to update.

  2. Open Github Desktop, and at the top middle, click "fetch origin". This will make Github Desktop get information about the update.

  3. Click where it says "current branch: master" at the top middle, and at the bottom of the thing that appears, click "choose a branch to merge into master".

  4. Select upstream/master. It will likely say there are conflicts, but you have tools to resolve them. Click "Merge upstream/master into master".

  5. A conflict happens when the things you're trying to merge have both made changes in the same place. Click "open in Visual Studio Code" next to the first file.

  6. Scroll down through the file, and look for the parts highlighted in red and green. One of these is your code, and the other is some code that will be modified by the update. Do your best to try to edit things to keep the updated changes, but keep your content.

  7. Continue to do this for all remaining changes.

  8. Do any other changes required by the update, run the game, fix issues, etc.

- - + + \ No newline at end of file diff --git a/public/lit/docs/upgrades/index.html b/public/lit/docs/upgrades/index.html index 36ed46599..2f4d9df76 100644 --- a/public/lit/docs/upgrades/index.html +++ b/public/lit/docs/upgrades/index.html @@ -6,8 +6,8 @@ Upgrades | The Paper Pilot - - + + @@ -28,8 +28,8 @@ etc }

Each upgrade should have an id where the first digit is the row and the second digit is the column.

Individual upgrades can have these features:

  • title: optional. Displayed at the top in a larger font. It can also be a function that returns updating text. Can use basic HTML.

  • description: A description of the upgrade's effect. You will also have to implement the effect where it is applied. It can also be a function that returns updating text. Can use basic HTML.

  • effect(): optional. A function that calculates and returns the current values of any bonuses from the upgrade. Can return a value or an object containing multiple values.

  • effectDisplay(): optional. A function that returns a display of the current effects of the upgrade with formatting. Default displays nothing. Can use basic HTML.

  • fullDisplay(): OVERRIDE. Overrides the other displays and descriptions, and lets you set the full text for the upgrade. Can use basic HTML.

  • cost: A Decimal for the cost of the upgrade. By default, upgrades cost the main prestige currency for the layer.

  • unlocked(): optional. A function returning a bool to determine if the upgrade is visible or not. Default is unlocked.

  • onPurchase(): optional. This function will be called when the upgrade is purchased. Good for upgrades like "makes this layer act like it was unlocked first".

  • style: optional. Applies CSS to this upgrade, in the form of an object where the keys are CSS attributes, and the values are the values for those attributes (both as strings).

  • layer: assigned automagically. It's the same value as the name of this layer, so you can do player[this.layer].points or similar.

  • id: assigned automagically. It's the "key" which the upgrade was stored under, for convenient access. The upgrade in the example's id is 11.

By default, upgrades use the main prestige currency for the layer. You can include these to change them (but it needs to be a Decimal):

  • currencyDisplayName: optional. The name to display for the currency for the upgrade.

  • currencyInternalName: optional. The internal name for that currency.

  • currencyLayer: optional. The internal name of the layer that currency is stored in. If it's not in a layer (like Points), omit. If it's not stored directly in a layer, instead use the next feature.

  • currencyLocation: optional. If your currency is stored in something inside a layer (e.g. a buyable's amount), you can access it this way. This is a function returning the object in "player" that contains the value (like player[this.layer].buyables)

If you want to do something more complicated like upgrades that cost two currencies, you can override the purchase system with these (and you need to use fullDisplay as well)

  • canAfford(): OVERRIDE, a function determining if you are able to buy the upgrade

  • pay(): OVERRIDE, a function that reduces your currencies when you buy the upgrade

- - + + \ No newline at end of file