2024-03-03 11:53:50 +00:00
// ************ Big Feature related ************
function respecBuyables ( layer ) {
if ( ! layers [ layer ] . buyables ) return
if ( ! layers [ layer ] . buyables . respec ) return
if ( ! player [ layer ] . noRespecConfirm && ! confirm ( tmp [ layer ] . buyables . respecMessage || "Are you sure you want to respec? This will force you to do a \"" + ( tmp [ layer ] . name ? tmp [ layer ] . name : layer ) + "\" reset as well!" ) ) return
run ( layers [ layer ] . buyables . respec , layers [ layer ] . buyables )
updateBuyableTemp ( layer )
document . activeElement . blur ( )
}
function canAffordUpgrade ( layer , id ) {
let upg = tmp [ layer ] . upgrades [ id ]
if ( tmp [ layer ] . deactivated ) return false
if ( tmp [ layer ] . upgrades [ id ] . canAfford === false ) return false
let cost = tmp [ layer ] . upgrades [ id ] . cost
if ( cost !== undefined )
return canAffordPurchase ( layer , upg , cost )
return true
}
function canBuyBuyable ( layer , id ) {
let b = temp [ layer ] . buyables [ id ]
return ( b . unlocked && run ( b . canAfford , b ) && player [ layer ] . buyables [ id ] . lt ( b . purchaseLimit ) && ! tmp [ layer ] . deactivated )
}
function canAffordPurchase ( layer , thing , cost ) {
if ( thing . currencyInternalName ) {
let name = thing . currencyInternalName
if ( thing . currencyLocation ) {
return ! ( thing . currencyLocation [ name ] . lt ( cost ) )
}
else if ( thing . currencyLayer ) {
let lr = thing . currencyLayer
return ! ( player [ lr ] [ name ] . lt ( cost ) )
}
else {
return ! ( player [ name ] . lt ( cost ) )
}
}
else {
return ! ( player [ layer ] . points . lt ( cost ) )
}
}
function buyUpgrade ( layer , id ) {
buyUpg ( layer , id )
}
function buyUpg ( layer , id ) {
if ( ! tmp [ layer ] . upgrades || ! tmp [ layer ] . upgrades [ id ] ) return
let upg = tmp [ layer ] . upgrades [ id ]
if ( ! player [ layer ] . unlocked || player [ layer ] . deactivated ) return
if ( ! tmp [ layer ] . upgrades [ id ] . unlocked ) return
if ( player [ layer ] . upgrades . includes ( id ) ) return
if ( upg . canAfford === false ) return
let pay = layers [ layer ] . upgrades [ id ] . pay
if ( pay !== undefined )
run ( pay , layers [ layer ] . upgrades [ id ] )
else {
let cost = tmp [ layer ] . upgrades [ id ] . cost
if ( upg . currencyInternalName ) {
let name = upg . currencyInternalName
if ( upg . currencyLocation ) {
if ( upg . currencyLocation [ name ] . lt ( cost ) ) return
upg . currencyLocation [ name ] = upg . currencyLocation [ name ] . sub ( cost )
}
else if ( upg . currencyLayer ) {
let lr = upg . currencyLayer
if ( player [ lr ] [ name ] . lt ( cost ) ) return
player [ lr ] [ name ] = player [ lr ] [ name ] . sub ( cost )
}
else {
if ( player [ name ] . lt ( cost ) ) return
player [ name ] = player [ name ] . sub ( cost )
}
}
else {
if ( player [ layer ] . points . lt ( cost ) ) return
player [ layer ] . points = player [ layer ] . points . sub ( cost )
}
}
player [ layer ] . upgrades . push ( id ) ;
if ( upg . onPurchase != undefined )
run ( upg . onPurchase , upg )
needCanvasUpdate = true
}
function buyMaxBuyable ( layer , id ) {
if ( ! player [ layer ] . unlocked ) return
if ( ! tmp [ layer ] . buyables [ id ] . unlocked ) return
if ( ! tmp [ layer ] . buyables [ id ] . canBuy ) return
if ( ! layers [ layer ] . buyables [ id ] . buyMax ) return
run ( layers [ layer ] . buyables [ id ] . buyMax , layers [ layer ] . buyables [ id ] )
updateBuyableTemp ( layer )
}
function buyBuyable ( layer , id ) {
if ( ! player [ layer ] . unlocked ) return
if ( ! tmp [ layer ] . buyables [ id ] . unlocked ) return
if ( ! tmp [ layer ] . buyables [ id ] . canBuy ) return
run ( layers [ layer ] . buyables [ id ] . buy , layers [ layer ] . buyables [ id ] )
updateBuyableTemp ( layer )
}
function clickClickable ( layer , id ) {
if ( ! player [ layer ] . unlocked || tmp [ layer ] . deactivated ) return
if ( ! tmp [ layer ] . clickables [ id ] . unlocked ) return
if ( ! tmp [ layer ] . clickables [ id ] . canClick ) return
run ( layers [ layer ] . clickables [ id ] . onClick , layers [ layer ] . clickables [ id ] )
updateClickableTemp ( layer )
}
function clickGrid ( layer , id ) {
if ( ! player [ layer ] . unlocked || tmp [ layer ] . deactivated ) return
if ( ! run ( layers [ layer ] . grid . getUnlocked , layers [ layer ] . grid , id ) ) return
if ( ! gridRun ( layer , 'getCanClick' , player [ layer ] . grid [ id ] , id ) ) return
gridRun ( layer , 'onClick' , player [ layer ] . grid [ id ] , id )
}
// Function to determine if the player is in a challenge
function inChallenge ( layer , id ) {
let challenge = player [ layer ] . activeChallenge
if ( ! challenge ) return false
id = toNumber ( id )
if ( challenge == id ) return true
if ( layers [ layer ] . challenges [ challenge ] . countsAs )
return tmp [ layer ] . challenges [ challenge ] . countsAs . includes ( id ) || false
return false
}
// ************ Misc ************
var onTreeTab = true
function showTab ( name , prev ) {
if ( LAYERS . includes ( name ) && ! layerunlocked ( name ) ) return
if ( player . tab !== name ) clearParticles ( function ( p ) { return p . layer === player . tab } )
if ( tmp [ name ] && player . tab === name && isPlainObject ( tmp [ name ] . tabFormat ) ) {
player . subtabs [ name ] . mainTabs = Object . keys ( layers [ name ] . tabFormat ) [ 0 ]
}
var toTreeTab = name == "none"
player . tab = name
if ( tmp [ name ] && ( tmp [ name ] . row !== "side" ) && ( tmp [ name ] . row !== "otherside" ) ) player . lastSafeTab = name
updateTabFormats ( )
needCanvasUpdate = true
document . activeElement . blur ( )
}
function showNavTab ( name , prev ) {
console . log ( prev )
if ( LAYERS . includes ( name ) && ! layerunlocked ( name ) ) return
if ( player . navTab !== name ) clearParticles ( function ( p ) { return p . layer === player . navTab } )
if ( tmp [ name ] && tmp [ name ] . previousTab !== undefined ) prev = tmp [ name ] . previousTab
var toTreeTab = name == "tree-tab"
console . log ( name + prev )
if ( name !== "none" && prev && ! tmp [ prev ] ? . leftTab == ! tmp [ name ] ? . leftTab ) player [ name ] . prevTab = prev
else if ( player [ name ] )
player [ name ] . prevTab = ""
player . navTab = name
updateTabFormats ( )
needCanvasUpdate = true
}
function goBack ( layer ) {
let nextTab = "none"
if ( player [ layer ] . prevTab ) nextTab = player [ layer ] . prevTab
if ( player . navTab === "none" && ( tmp [ layer ] ? . row == "side" || tmp [ layer ] . row == "otherside" ) ) nextTab = player . lastSafeTab
if ( tmp [ layer ] . leftTab ) showNavTab ( nextTab , layer )
else showTab ( nextTab , layer )
}
function layOver ( obj1 , obj2 ) {
for ( let x in obj2 ) {
if ( obj2 [ x ] instanceof Decimal ) obj1 [ x ] = new Decimal ( obj2 [ x ] )
else if ( obj2 [ x ] instanceof Object ) layOver ( obj1 [ x ] , obj2 [ x ] ) ;
else obj1 [ x ] = obj2 [ x ] ;
}
}
function prestigeNotify ( layer ) {
if ( layers [ layer ] . prestigeNotify ) return layers [ layer ] . prestigeNotify ( )
if ( isPlainObject ( tmp [ layer ] . tabFormat ) ) {
for ( subtab in tmp [ layer ] . tabFormat ) {
if ( subtabResetNotify ( layer , 'mainTabs' , subtab ) )
return true
}
}
for ( family in tmp [ layer ] . microtabs ) {
for ( subtab in tmp [ layer ] . microtabs [ family ] ) {
if ( subtabResetNotify ( layer , family , subtab ) )
return true
}
}
if ( tmp [ layer ] . autoPrestige || tmp [ layer ] . passiveGeneration ) return false
else if ( tmp [ layer ] . type == "static" ) return tmp [ layer ] . canReset
else if ( tmp [ layer ] . type == "normal" ) return ( tmp [ layer ] . canReset && ( tmp [ layer ] . resetGain . gte ( player [ layer ] . points . div ( 10 ) ) ) )
else return false
}
function notifyLayer ( name ) {
if ( player . tab == name || ! layerunlocked ( name ) ) return
player . notify [ name ] = 1
}
function subtabShouldNotify ( layer , family , id ) {
let subtab = { }
if ( family == "mainTabs" ) subtab = tmp [ layer ] . tabFormat [ id ]
else subtab = tmp [ layer ] . microtabs [ family ] [ id ]
if ( ! subtab . unlocked ) return false
if ( subtab . embedLayer ) return tmp [ subtab . embedLayer ] . notify
else return subtab . shouldNotify
}
function subtabResetNotify ( layer , family , id ) {
let subtab = { }
if ( family == "mainTabs" ) subtab = tmp [ layer ] . tabFormat [ id ]
else subtab = tmp [ layer ] . microtabs [ family ] [ id ]
if ( subtab . embedLayer ) return tmp [ subtab . embedLayer ] . prestigeNotify
else return subtab . prestigeNotify
}
function nodeShown ( layer ) {
return layerShown ( layer )
}
function layerunlocked ( layer ) {
if ( tmp [ layer ] && tmp [ layer ] . type == "none" ) return ( player [ layer ] . unlocked )
return LAYERS . includes ( layer ) && ( player [ layer ] . unlocked || ( tmp [ layer ] . canReset && tmp [ layer ] . layerShown ) )
}
function keepGoing ( ) {
player . keepGoing = true ;
needCanvasUpdate = true ;
}
function toNumber ( x ) {
if ( x . mag !== undefined ) return x . toNumber ( )
if ( x + 0 !== x ) return parseFloat ( x )
return x
}
function updateMilestones ( layer ) {
if ( tmp [ layer ] . deactivated ) return
for ( id in layers [ layer ] . milestones ) {
if ( ! ( hasMilestone ( layer , id ) ) && layers [ layer ] . milestones [ id ] . done ( ) ) {
player [ layer ] . milestones . push ( id )
if ( layers [ layer ] . milestones [ id ] . onComplete ) layers [ layer ] . milestones [ id ] . onComplete ( )
if ( tmp [ layer ] . milestonePopups || tmp [ layer ] . milestonePopups === undefined ) doPopup ( "milestone" , tmp [ layer ] . milestones [ id ] . requirementDescription , "Milestone Gotten!" , 3 , tmp [ layer ] . color ) ;
player [ layer ] . lastMilestone = id
}
}
}
function updateAchievements ( layer ) {
if ( tmp [ layer ] . deactivated ) return
for ( id in layers [ layer ] . achievements ) {
if ( isPlainObject ( layers [ layer ] . achievements [ id ] ) && ! ( hasAchievement ( layer , id ) ) && layers [ layer ] . achievements [ id ] . done ( ) ) {
player [ layer ] . achievements . push ( id )
if ( layers [ layer ] . achievements [ id ] . onComplete ) layers [ layer ] . achievements [ id ] . onComplete ( )
if ( tmp [ layer ] . achievementPopups || tmp [ layer ] . achievementPopups === undefined ) doPopup ( "achievement" , tmp [ layer ] . achievements [ id ] . name , "Achievement Gotten!" , 3 , tmp [ layer ] . color ) ;
}
}
}
function addTime ( diff , layer ) {
let data = player
let time = data . timePlayed
if ( layer ) {
data = data [ layer ]
time = data . time
}
//I am not that good to perfectly fix that leak. ~ DB Aarex
if ( time + 0 !== time ) {
console . log ( "Memory leak detected. Trying to fix..." )
time = toNumber ( time )
if ( isNaN ( time ) || time == 0 ) {
console . log ( "Couldn't fix! Resetting..." )
time = layer ? player . timePlayed : 0
if ( ! layer ) player . timePlayedReset = true
}
}
time += toNumber ( diff )
if ( layer ) data . time = time
else data . timePlayed = time
}
shiftDown = false
ctrlDown = false
document . onkeydown = function ( e ) {
if ( player === undefined ) return ;
shiftDown = e . shiftKey
ctrlDown = e . ctrlKey
if ( tmp . gameEnded && ! player . keepGoing ) return ;
let key = e . key
if ( ctrlDown ) key = "ctrl+" + key
if ( onFocused ) return
if ( ctrlDown && hotkeys [ key ] ) e . preventDefault ( )
if ( hotkeys [ key ] ) {
let k = hotkeys [ key ]
if ( player [ k . layer ] . unlocked && tmp [ k . layer ] . hotkeys [ k . id ] . unlocked )
k . onPress ( )
}
}
document . onkeyup = function ( e ) {
shiftDown = e . shiftKey
ctrlDown = e . ctrlKey
}
var onFocused = false
function focused ( x ) {
onFocused = x
}
function isFunction ( obj ) {
return ! ! ( obj && obj . constructor && obj . call && obj . apply ) ;
} ;
function isPlainObject ( obj ) {
return ( ! ! obj ) && ( obj . constructor === Object )
}
document . title = modInfo . name
// Converts a string value to whatever it's supposed to be
function toValue ( value , oldValue ) {
if ( oldValue instanceof Decimal ) {
value = new Decimal ( value )
if ( checkDecimalNaN ( value ) ) return decimalZero
return value
}
if ( ! isNaN ( oldValue ) )
return parseFloat ( value ) || 0
return value
}
// Variables that must be defined to display popups
var activePopups = [ ] ;
var popupID = 0 ;
// Function to show popups
function doPopup ( type = "none" , text = "This is a test popup." , title = "" , timer = 3 , color = "" ) {
switch ( type ) {
case "achievement" :
popupTitle = "Achievement Unlocked!" ;
popupType = "achievement-popup"
break ;
case "challenge" :
popupTitle = "Challenge Complete" ;
popupType = "challenge-popup"
break ;
default :
popupTitle = "Something Happened?" ;
popupType = "default-popup"
break ;
}
if ( title != "" ) popupTitle = title ;
popupMessage = text ;
popupTimer = timer ;
activePopups . push ( { "time" : popupTimer , "type" : popupType , "title" : popupTitle , "message" : ( popupMessage + "\n" ) , "id" : popupID , "color" : color } )
popupID ++ ;
}
//Function to reduce time on active popups
function adjustPopupTime ( diff ) {
for ( popup in activePopups ) {
activePopups [ popup ] . time -= diff ;
if ( activePopups [ popup ] [ "time" ] < 0 ) {
activePopups . splice ( popup , 1 ) ; // Remove popup when time hits 0
}
}
}
function run ( func , target , args = null ) {
if ( isFunction ( func ) ) {
let bound = func . bind ( target )
return bound ( args )
}
else
return func ;
}
function gridRun ( layer , func , data , id ) {
if ( isFunction ( layers [ layer ] . grid [ func ] ) ) {
let bound = layers [ layer ] . grid [ func ] . bind ( layers [ layer ] . grid )
return bound ( data , id )
}
else
return layers [ layer ] . grid [ func ] ;
2024-03-08 19:37:47 +00:00
}
// Small functions
2024-03-10 17:19:22 +00:00
function softcap ( number , after , method , delta = new Decimal ( 0 ) ) {
if ( Decimal . add ( number , delta ) . lt ( after ) ) { return new Decimal ( number ) }
else { return method ( Decimal . add ( number , delta ) . sub ( after ) ) . add ( after ) . sub ( delta ) }
2024-03-03 11:53:50 +00:00
}