From e60fdac003f7d52df5b7e595c16c0c82b785f0f7 Mon Sep 17 00:00:00 2001 From: Mees Buschman Date: Tue, 10 Sep 2024 17:22:02 +0200 Subject: [PATCH] feat: offline progress for adventure mode --- .eslintcache | 2 +- src/stores/adventureStore.ts | 937 ++++++++++++++++++++--------------- src/stores/gameStore.ts | 24 +- src/views/Adventure.vue | 7 +- src/views/Home.vue | 12 +- 5 files changed, 580 insertions(+), 402 deletions(-) diff --git a/.eslintcache b/.eslintcache index 52cbcba..e37c8c5 100644 --- a/.eslintcache +++ b/.eslintcache @@ -1 +1 @@ -[{"C:\\Development\\IdleViteVue\\.eslintrc.js":"1","C:\\Development\\IdleViteVue\\postcss.config.js":"2","C:\\Development\\IdleViteVue\\tailwind.config.js":"3","C:\\Development\\IdleViteVue\\vite.config.js":"4","C:\\Development\\IdleViteVue\\src\\App.vue":"5","C:\\Development\\IdleViteVue\\src\\main.ts":"6","C:\\Development\\IdleViteVue\\src\\routes.ts":"7","C:\\Development\\IdleViteVue\\src\\shims-vue.d.ts":"8","C:\\Development\\IdleViteVue\\src\\store.ts":"9","C:\\Development\\IdleViteVue\\src\\components\\AntSimulation.vue":"10","C:\\Development\\IdleViteVue\\src\\views\\Adventure.vue":"11","C:\\Development\\IdleViteVue\\src\\views\\AntResources.vue":"12","C:\\Development\\IdleViteVue\\src\\views\\Home.vue":"13","C:\\Development\\IdleViteVue\\src\\views\\NotFound.vue":"14","C:\\Development\\IdleViteVue\\src\\stores\\adventureStore.ts":"15","C:\\Development\\IdleViteVue\\src\\stores\\gameStore.ts":"16","C:\\Development\\IdleViteVue\\src\\views\\Debugger.vue":"17","C:\\Development\\IdleViteVue\\src\\views\\Inventory.vue":"18","C:\\Development\\IdleViteVue\\src\\stores\\inventoryStore.ts":"19","C:\\Development\\IdleViteVue\\src\\components\\InventoryItem.vue":"20","C:\\Development\\IdleViteVue\\src\\types\\itemRegistry.ts":"21","C:\\Development\\IdleViteVue\\src\\firebase.ts":"22","C:\\Development\\IdleViteVue\\src\\components\\Modal.vue":"23","C:\\Development\\IdleViteVue\\src\\views\\PrestigeShop.vue":"24","C:\\Development\\IdleViteVue\\src\\views\\Settings.vue":"25","C:\\Development\\IdleViteVue\\src\\stores\\prestigeStore.ts":"26"},{"size":758,"mtime":1725657576729},{"size":83,"mtime":1725657576792},{"size":726,"mtime":1725826628130},{"size":177,"mtime":1725657576822},{"size":83,"mtime":1725657506695,"results":"27","hashOfConfig":"28"},{"size":1843,"mtime":1725898066056,"results":"29","hashOfConfig":"28"},{"size":272,"mtime":1725660566335,"results":"30","hashOfConfig":"28"},{"size":120,"mtime":1725474178300,"results":"31","hashOfConfig":"28"},{"size":90,"mtime":1725474178300,"results":"32","hashOfConfig":"28"},{"size":14778,"mtime":1725824992912,"results":"33","hashOfConfig":"28"},{"size":4382,"mtime":1725896031604,"results":"34","hashOfConfig":"28"},{"size":14557,"mtime":1725910395274,"results":"35","hashOfConfig":"28"},{"size":12208,"mtime":1725915468765,"results":"36","hashOfConfig":"28"},{"size":436,"mtime":1725474178301,"results":"37","hashOfConfig":"28"},{"size":14104,"mtime":1725902793489,"results":"38","hashOfConfig":"28"},{"size":24160,"mtime":1725954155960,"results":"39","hashOfConfig":"28"},{"size":3251,"mtime":1725899290112,"results":"40","hashOfConfig":"28"},{"size":4598,"mtime":1725776358787,"results":"41","hashOfConfig":"28"},{"size":6536,"mtime":1725902610389,"results":"42","hashOfConfig":"28"},{"size":1448,"mtime":1725739147002,"results":"43","hashOfConfig":"28"},{"size":4070,"mtime":1725900842399,"results":"44","hashOfConfig":"28"},{"size":1173,"mtime":1725903219799,"results":"45","hashOfConfig":"28"},{"size":1290,"mtime":1725801294724},{"size":5672,"mtime":1725895682524},{"size":1423,"mtime":1725824134747},{"size":11069,"mtime":1725901778619,"results":"46","hashOfConfig":"28"},{"filePath":"47","messages":"48","suppressedMessages":"49","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"adzkch",{"filePath":"50","messages":"51","suppressedMessages":"52","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"53","messages":"54","suppressedMessages":"55","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"56","messages":"57","suppressedMessages":"58","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"59","messages":"60","suppressedMessages":"61","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"62","messages":"63","suppressedMessages":"64","errorCount":0,"fatalErrorCount":0,"warningCount":9,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"65","messages":"66","suppressedMessages":"67","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"68","messages":"69","suppressedMessages":"70","errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"71","messages":"72","suppressedMessages":"73","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"74","messages":"75","suppressedMessages":"76","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"77","messages":"78","suppressedMessages":"79","errorCount":0,"fatalErrorCount":0,"warningCount":4,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"80","messages":"81","suppressedMessages":"82","errorCount":0,"fatalErrorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"83","messages":"84","suppressedMessages":"85","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"86","messages":"87","suppressedMessages":"88","errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"89","messages":"90","suppressedMessages":"91","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"92","messages":"93","suppressedMessages":"94","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"95","messages":"96","suppressedMessages":"97","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"98","messages":"99","suppressedMessages":"100","errorCount":0,"fatalErrorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"101","messages":"102","suppressedMessages":"103","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"C:\\Development\\IdleViteVue\\src\\App.vue",[],[],"C:\\Development\\IdleViteVue\\src\\main.ts",[],[],"C:\\Development\\IdleViteVue\\src\\routes.ts",[],[],"C:\\Development\\IdleViteVue\\src\\shims-vue.d.ts",[],[],"C:\\Development\\IdleViteVue\\src\\store.ts",[],[],"C:\\Development\\IdleViteVue\\src\\components\\AntSimulation.vue",["104","105","106","107","108","109","110","111","112"],[],"C:\\Development\\IdleViteVue\\src\\views\\Adventure.vue",[],[],"C:\\Development\\IdleViteVue\\src\\views\\AntResources.vue",["113","114"],[],"C:\\Development\\IdleViteVue\\src\\views\\Home.vue",[],[],"C:\\Development\\IdleViteVue\\src\\views\\NotFound.vue",[],[],"C:\\Development\\IdleViteVue\\src\\stores\\adventureStore.ts",["115","116","117","118"],[],"C:\\Development\\IdleViteVue\\src\\stores\\gameStore.ts",["119"],[],"C:\\Development\\IdleViteVue\\src\\views\\Debugger.vue",[],[],"C:\\Development\\IdleViteVue\\src\\views\\Inventory.vue",["120","121"],[],"C:\\Development\\IdleViteVue\\src\\stores\\inventoryStore.ts",[],[],"C:\\Development\\IdleViteVue\\src\\components\\InventoryItem.vue",[],[],"C:\\Development\\IdleViteVue\\src\\types\\itemRegistry.ts",[],[],"C:\\Development\\IdleViteVue\\src\\firebase.ts",["122","123","124"],[],"C:\\Development\\IdleViteVue\\src\\stores\\prestigeStore.ts",[],[],{"ruleId":"125","severity":1,"message":"126","line":252,"column":49,"nodeType":"127","messageId":"128","endLine":252,"endColumn":62,"suggestions":"129"},{"ruleId":"125","severity":1,"message":"126","line":254,"column":62,"nodeType":"127","messageId":"128","endLine":254,"endColumn":75,"suggestions":"130"},{"ruleId":"125","severity":1,"message":"126","line":256,"column":49,"nodeType":"127","messageId":"128","endLine":256,"endColumn":62,"suggestions":"131"},{"ruleId":"125","severity":1,"message":"126","line":258,"column":62,"nodeType":"127","messageId":"128","endLine":258,"endColumn":75,"suggestions":"132"},{"ruleId":"125","severity":1,"message":"126","line":281,"column":3,"nodeType":"127","messageId":"128","endLine":281,"endColumn":13,"suggestions":"133"},{"ruleId":"125","severity":1,"message":"126","line":294,"column":3,"nodeType":"127","messageId":"128","endLine":294,"endColumn":13,"suggestions":"134"},{"ruleId":"125","severity":1,"message":"126","line":295,"column":3,"nodeType":"127","messageId":"128","endLine":295,"endColumn":13,"suggestions":"135"},{"ruleId":"125","severity":1,"message":"126","line":295,"column":29,"nodeType":"127","messageId":"128","endLine":295,"endColumn":42,"suggestions":"136"},{"ruleId":"125","severity":1,"message":"126","line":295,"column":50,"nodeType":"127","messageId":"128","endLine":295,"endColumn":63,"suggestions":"137"},{"ruleId":"138","severity":1,"message":"139","line":313,"column":9,"nodeType":"140","messageId":"141","endLine":313,"endColumn":12},{"ruleId":"138","severity":1,"message":"142","line":314,"column":8,"nodeType":"140","messageId":"141","endLine":314,"endColumn":13},{"ruleId":"138","severity":1,"message":"143","line":5,"column":9,"nodeType":"140","messageId":"141","endLine":5,"endColumn":21},{"ruleId":"138","severity":1,"message":"144","line":6,"column":9,"nodeType":"140","messageId":"141","endLine":6,"endColumn":12},{"ruleId":"138","severity":1,"message":"145","line":6,"column":14,"nodeType":"140","messageId":"141","endLine":6,"endColumn":17},{"ruleId":"138","severity":1,"message":"146","line":6,"column":19,"nodeType":"140","messageId":"141","endLine":6,"endColumn":22},{"ruleId":"138","severity":1,"message":"147","line":346,"column":15,"nodeType":"140","messageId":"141","endLine":346,"endColumn":25},{"ruleId":"138","severity":1,"message":"148","line":48,"column":15,"nodeType":"140","messageId":"141","endLine":48,"endColumn":21},{"ruleId":"149","severity":1,"message":"150","line":77,"column":18,"nodeType":"151","messageId":"152","endLine":77,"endColumn":21,"suggestions":"153"},{"ruleId":"138","severity":1,"message":"154","line":2,"column":24,"nodeType":"140","messageId":"141","endLine":2,"endColumn":34},{"ruleId":"138","severity":1,"message":"155","line":4,"column":10,"nodeType":"140","messageId":"141","endLine":4,"endColumn":28},{"ruleId":"138","severity":1,"message":"156","line":4,"column":30,"nodeType":"140","messageId":"141","endLine":4,"endColumn":49},"@typescript-eslint/no-non-null-assertion","Forbidden non-null assertion.","TSNonNullExpression","noNonNull",["157"],["158"],["159"],["160"],["161"],["162"],["163"],["164"],["165"],"@typescript-eslint/no-unused-vars","'ref' is defined but never used.","Identifier","unusedVar","'Modal' is defined but never used.","'itemRegistry' is defined but never used.","'del' is defined but never used.","'get' is defined but never used.","'set' is defined but never used.","'credential' is assigned a value but never used.","'height' is assigned a value but never used.","@typescript-eslint/no-explicit-any","Unexpected any. Specify a different type.","TSAnyKeyword","unexpectedAny",["166","167"],"'collection' is defined but never used.","'initializeAppCheck' is defined but never used.","'ReCaptchaV3Provider' is defined but never used.",{"messageId":"168","fix":"169","desc":"170"},{"messageId":"168","fix":"171","desc":"170"},{"messageId":"168","fix":"172","desc":"170"},{"messageId":"168","fix":"173","desc":"170"},{"messageId":"168","fix":"174","desc":"170"},{"messageId":"168","fix":"175","desc":"170"},{"messageId":"168","fix":"176","desc":"170"},{"messageId":"168","fix":"177","desc":"170"},{"messageId":"168","fix":"178","desc":"170"},{"messageId":"179","fix":"180","desc":"181"},{"messageId":"182","fix":"183","desc":"184"},"suggestOptionalChain",{"range":"185","text":"186"},"Consider using the optional chain operator `?.` instead. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator.",{"range":"187","text":"186"},{"range":"188","text":"186"},{"range":"189","text":"186"},{"range":"190","text":"186"},{"range":"191","text":"186"},{"range":"192","text":"186"},{"range":"193","text":"186"},{"range":"194","text":"186"},"suggestUnknown",{"range":"195","text":"196"},"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct.","suggestNever",{"range":"195","text":"197"},"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of.",[8615,8616],"?",[8758,8759],[8853,8854],[8992,8993],[9678,9679],[10057,10058],[10112,10113],[10141,10142],[10162,10163],[2559,2562],"unknown","never"] \ No newline at end of file +[{"C:\\Development\\IdleViteVue\\.eslintrc.js":"1","C:\\Development\\IdleViteVue\\postcss.config.js":"2","C:\\Development\\IdleViteVue\\tailwind.config.js":"3","C:\\Development\\IdleViteVue\\vite.config.js":"4","C:\\Development\\IdleViteVue\\src\\App.vue":"5","C:\\Development\\IdleViteVue\\src\\main.ts":"6","C:\\Development\\IdleViteVue\\src\\routes.ts":"7","C:\\Development\\IdleViteVue\\src\\shims-vue.d.ts":"8","C:\\Development\\IdleViteVue\\src\\store.ts":"9","C:\\Development\\IdleViteVue\\src\\components\\AntSimulation.vue":"10","C:\\Development\\IdleViteVue\\src\\views\\Adventure.vue":"11","C:\\Development\\IdleViteVue\\src\\views\\AntResources.vue":"12","C:\\Development\\IdleViteVue\\src\\views\\Home.vue":"13","C:\\Development\\IdleViteVue\\src\\views\\NotFound.vue":"14","C:\\Development\\IdleViteVue\\src\\stores\\adventureStore.ts":"15","C:\\Development\\IdleViteVue\\src\\stores\\gameStore.ts":"16","C:\\Development\\IdleViteVue\\src\\views\\Debugger.vue":"17","C:\\Development\\IdleViteVue\\src\\views\\Inventory.vue":"18","C:\\Development\\IdleViteVue\\src\\stores\\inventoryStore.ts":"19","C:\\Development\\IdleViteVue\\src\\components\\InventoryItem.vue":"20","C:\\Development\\IdleViteVue\\src\\types\\itemRegistry.ts":"21","C:\\Development\\IdleViteVue\\src\\firebase.ts":"22","C:\\Development\\IdleViteVue\\src\\components\\Modal.vue":"23","C:\\Development\\IdleViteVue\\src\\views\\PrestigeShop.vue":"24","C:\\Development\\IdleViteVue\\src\\views\\Settings.vue":"25","C:\\Development\\IdleViteVue\\src\\stores\\prestigeStore.ts":"26"},{"size":758,"mtime":1725657576729},{"size":83,"mtime":1725657576792},{"size":726,"mtime":1725826628130},{"size":177,"mtime":1725657576822},{"size":83,"mtime":1725657506695,"results":"27","hashOfConfig":"28"},{"size":1843,"mtime":1725898066056,"results":"29","hashOfConfig":"28"},{"size":272,"mtime":1725660566335,"results":"30","hashOfConfig":"28"},{"size":120,"mtime":1725474178300,"results":"31","hashOfConfig":"28"},{"size":90,"mtime":1725474178300,"results":"32","hashOfConfig":"28"},{"size":14778,"mtime":1725824992912,"results":"33","hashOfConfig":"28"},{"size":4382,"mtime":1725896031604,"results":"34","hashOfConfig":"28"},{"size":14557,"mtime":1725910395274,"results":"35","hashOfConfig":"28"},{"size":12208,"mtime":1725915468765,"results":"36","hashOfConfig":"28"},{"size":436,"mtime":1725474178301,"results":"37","hashOfConfig":"28"},{"size":14104,"mtime":1725902793489,"results":"38","hashOfConfig":"28"},{"size":23861,"mtime":1725954205494,"results":"39","hashOfConfig":"28"},{"size":3251,"mtime":1725899290112,"results":"40","hashOfConfig":"28"},{"size":4598,"mtime":1725776358787,"results":"41","hashOfConfig":"28"},{"size":6536,"mtime":1725902610389,"results":"42","hashOfConfig":"28"},{"size":1448,"mtime":1725739147002,"results":"43","hashOfConfig":"28"},{"size":4070,"mtime":1725900842399,"results":"44","hashOfConfig":"28"},{"size":1173,"mtime":1725903219799,"results":"45","hashOfConfig":"28"},{"size":1290,"mtime":1725801294724},{"size":5672,"mtime":1725895682524},{"size":1423,"mtime":1725824134747},{"size":11069,"mtime":1725901778619,"results":"46","hashOfConfig":"28"},{"filePath":"47","messages":"48","suppressedMessages":"49","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"adzkch",{"filePath":"50","messages":"51","suppressedMessages":"52","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"53","messages":"54","suppressedMessages":"55","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"56","messages":"57","suppressedMessages":"58","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"59","messages":"60","suppressedMessages":"61","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"62","messages":"63","suppressedMessages":"64","errorCount":0,"fatalErrorCount":0,"warningCount":9,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"65","messages":"66","suppressedMessages":"67","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"68","messages":"69","suppressedMessages":"70","errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"71","messages":"72","suppressedMessages":"73","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"74","messages":"75","suppressedMessages":"76","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"77","messages":"78","suppressedMessages":"79","errorCount":0,"fatalErrorCount":0,"warningCount":4,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"80","messages":"81","suppressedMessages":"82","errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"83","messages":"84","suppressedMessages":"85","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"86","messages":"87","suppressedMessages":"88","errorCount":0,"fatalErrorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"89","messages":"90","suppressedMessages":"91","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"92","messages":"93","suppressedMessages":"94","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"95","messages":"96","suppressedMessages":"97","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"98","messages":"99","suppressedMessages":"100","errorCount":0,"fatalErrorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"101","messages":"102","suppressedMessages":"103","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"C:\\Development\\IdleViteVue\\src\\App.vue",[],[],"C:\\Development\\IdleViteVue\\src\\main.ts",[],[],"C:\\Development\\IdleViteVue\\src\\routes.ts",[],[],"C:\\Development\\IdleViteVue\\src\\shims-vue.d.ts",[],[],"C:\\Development\\IdleViteVue\\src\\store.ts",[],[],"C:\\Development\\IdleViteVue\\src\\components\\AntSimulation.vue",["104","105","106","107","108","109","110","111","112"],[],"C:\\Development\\IdleViteVue\\src\\views\\Adventure.vue",[],[],"C:\\Development\\IdleViteVue\\src\\views\\AntResources.vue",["113","114"],[],"C:\\Development\\IdleViteVue\\src\\views\\Home.vue",[],[],"C:\\Development\\IdleViteVue\\src\\views\\NotFound.vue",[],[],"C:\\Development\\IdleViteVue\\src\\stores\\adventureStore.ts",["115","116","117","118"],[],"C:\\Development\\IdleViteVue\\src\\stores\\gameStore.ts",["119","120"],[],"C:\\Development\\IdleViteVue\\src\\views\\Debugger.vue",[],[],"C:\\Development\\IdleViteVue\\src\\views\\Inventory.vue",["121","122"],[],"C:\\Development\\IdleViteVue\\src\\stores\\inventoryStore.ts",[],[],"C:\\Development\\IdleViteVue\\src\\components\\InventoryItem.vue",[],[],"C:\\Development\\IdleViteVue\\src\\types\\itemRegistry.ts",[],[],"C:\\Development\\IdleViteVue\\src\\firebase.ts",["123","124","125"],[],"C:\\Development\\IdleViteVue\\src\\stores\\prestigeStore.ts",[],[],{"ruleId":"126","severity":1,"message":"127","line":252,"column":49,"nodeType":"128","messageId":"129","endLine":252,"endColumn":62,"suggestions":"130"},{"ruleId":"126","severity":1,"message":"127","line":254,"column":62,"nodeType":"128","messageId":"129","endLine":254,"endColumn":75,"suggestions":"131"},{"ruleId":"126","severity":1,"message":"127","line":256,"column":49,"nodeType":"128","messageId":"129","endLine":256,"endColumn":62,"suggestions":"132"},{"ruleId":"126","severity":1,"message":"127","line":258,"column":62,"nodeType":"128","messageId":"129","endLine":258,"endColumn":75,"suggestions":"133"},{"ruleId":"126","severity":1,"message":"127","line":281,"column":3,"nodeType":"128","messageId":"129","endLine":281,"endColumn":13,"suggestions":"134"},{"ruleId":"126","severity":1,"message":"127","line":294,"column":3,"nodeType":"128","messageId":"129","endLine":294,"endColumn":13,"suggestions":"135"},{"ruleId":"126","severity":1,"message":"127","line":295,"column":3,"nodeType":"128","messageId":"129","endLine":295,"endColumn":13,"suggestions":"136"},{"ruleId":"126","severity":1,"message":"127","line":295,"column":29,"nodeType":"128","messageId":"129","endLine":295,"endColumn":42,"suggestions":"137"},{"ruleId":"126","severity":1,"message":"127","line":295,"column":50,"nodeType":"128","messageId":"129","endLine":295,"endColumn":63,"suggestions":"138"},{"ruleId":"139","severity":1,"message":"140","line":313,"column":9,"nodeType":"141","messageId":"142","endLine":313,"endColumn":12},{"ruleId":"139","severity":1,"message":"143","line":314,"column":8,"nodeType":"141","messageId":"142","endLine":314,"endColumn":13},{"ruleId":"139","severity":1,"message":"144","line":5,"column":9,"nodeType":"141","messageId":"142","endLine":5,"endColumn":21},{"ruleId":"139","severity":1,"message":"145","line":6,"column":9,"nodeType":"141","messageId":"142","endLine":6,"endColumn":12},{"ruleId":"139","severity":1,"message":"146","line":6,"column":14,"nodeType":"141","messageId":"142","endLine":6,"endColumn":17},{"ruleId":"139","severity":1,"message":"147","line":6,"column":19,"nodeType":"141","messageId":"142","endLine":6,"endColumn":22},{"ruleId":"139","severity":1,"message":"148","line":175,"column":17,"nodeType":"141","messageId":"142","endLine":175,"endColumn":30},{"ruleId":"139","severity":1,"message":"149","line":354,"column":15,"nodeType":"141","messageId":"142","endLine":354,"endColumn":25},{"ruleId":"139","severity":1,"message":"150","line":48,"column":15,"nodeType":"141","messageId":"142","endLine":48,"endColumn":21},{"ruleId":"151","severity":1,"message":"152","line":77,"column":18,"nodeType":"153","messageId":"154","endLine":77,"endColumn":21,"suggestions":"155"},{"ruleId":"139","severity":1,"message":"156","line":2,"column":24,"nodeType":"141","messageId":"142","endLine":2,"endColumn":34},{"ruleId":"139","severity":1,"message":"157","line":4,"column":10,"nodeType":"141","messageId":"142","endLine":4,"endColumn":28},{"ruleId":"139","severity":1,"message":"158","line":4,"column":30,"nodeType":"141","messageId":"142","endLine":4,"endColumn":49},"@typescript-eslint/no-non-null-assertion","Forbidden non-null assertion.","TSNonNullExpression","noNonNull",["159"],["160"],["161"],["162"],["163"],["164"],["165"],["166"],["167"],"@typescript-eslint/no-unused-vars","'ref' is defined but never used.","Identifier","unusedVar","'Modal' is defined but never used.","'itemRegistry' is defined but never used.","'del' is defined but never used.","'get' is defined but never used.","'set' is defined but never used.","'prestigeStore' is assigned a value but never used.","'credential' is assigned a value but never used.","'height' is assigned a value but never used.","@typescript-eslint/no-explicit-any","Unexpected any. Specify a different type.","TSAnyKeyword","unexpectedAny",["168","169"],"'collection' is defined but never used.","'initializeAppCheck' is defined but never used.","'ReCaptchaV3Provider' is defined but never used.",{"messageId":"170","fix":"171","desc":"172"},{"messageId":"170","fix":"173","desc":"172"},{"messageId":"170","fix":"174","desc":"172"},{"messageId":"170","fix":"175","desc":"172"},{"messageId":"170","fix":"176","desc":"172"},{"messageId":"170","fix":"177","desc":"172"},{"messageId":"170","fix":"178","desc":"172"},{"messageId":"170","fix":"179","desc":"172"},{"messageId":"170","fix":"180","desc":"172"},{"messageId":"181","fix":"182","desc":"183"},{"messageId":"184","fix":"185","desc":"186"},"suggestOptionalChain",{"range":"187","text":"188"},"Consider using the optional chain operator `?.` instead. This operator includes runtime checks, so it is safer than the compile-only non-null assertion operator.",{"range":"189","text":"188"},{"range":"190","text":"188"},{"range":"191","text":"188"},{"range":"192","text":"188"},{"range":"193","text":"188"},{"range":"194","text":"188"},{"range":"195","text":"188"},{"range":"196","text":"188"},"suggestUnknown",{"range":"197","text":"198"},"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct.","suggestNever",{"range":"197","text":"199"},"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of.",[8615,8616],"?",[8758,8759],[8853,8854],[8992,8993],[9678,9679],[10057,10058],[10112,10113],[10141,10142],[10162,10163],[2559,2562],"unknown","never"] \ No newline at end of file diff --git a/src/stores/adventureStore.ts b/src/stores/adventureStore.ts index 9a03a99..75884b2 100644 --- a/src/stores/adventureStore.ts +++ b/src/stores/adventureStore.ts @@ -1,452 +1,605 @@ -import {defineStore} from 'pinia' -import {useGameStore} from './gameStore' -import {useToast} from 'vue-toast-notification' -import {useInventoryStore} from './inventoryStore' -import {itemRegistry} from '../types/itemRegistry' -import {del, get, set} from 'idb-keyval' -import {deleteDoc, doc, getDoc, setDoc} from 'firebase/firestore' -import {db} from '../firebase' +import { defineStore } from 'pinia' +import { useGameStore } from './gameStore' +import { useToast } from 'vue-toast-notification' +import { useInventoryStore } from './inventoryStore' +import { deleteDoc, doc, getDoc, setDoc } from 'firebase/firestore' +import { db } from '../firebase' export const useAdventureStore = defineStore('adventureStore', { - state: () => ({ - armyHealth: 100, - armyMaxHealth: 100, - armyAttack: 10, - armyDefense: 5, - armyRegen: 5, - - bugHealth: 0, - bugMaxHealth: 0, - bugAttack: 0, - bugDefense: 0, - bugRegen: 2, - - currentArea: 'Wasteland', - enemyWaves: [ - { - name: 'Wasteland', - enemies: [ - { - name: 'Grasshopper', health: 100, attack: 8, defense: 4, regen: 2, dropOptions: [ - { - name: 'Seeds', - chance: 0.5, - amountBetween: [100, 500], - }, - { - name: 'Grasshopper Leg', - chance: 0.2, - amountBetween: [1, 2], - }, - ], - }, - { - name: 'Beetle', - health: 150, - attack: 10, - defense: 5, - regen: 3, - dropOptions: [ - { - name: 'Seeds', - chance: 0.5, - amountBetween: [100, 500], - }, - { - name: 'Ant Strength Potion', - chance: 0.1, - amountBetween: [1, 2], - }, - ], - }, - { - name: 'Wasp', - health: 120, - attack: 12, - defense: 6, - regen: 2, - dropOptions: [ - { - name: 'Seeds', - chance: 0.5, - amountBetween: [100, 500], - }, - { - name: 'Queen Crown', - chance: 0.05, - amountBetween: [1, 1], - }, - ], - }, - ], - unlocked: true, - }, - { - name: 'Forest', - enemies: [ - { - name: 'Spider', - health: 2000, - attack: 150, - defense: 80, - regen: 40, - dropOptions: [ - { - name: 'Seeds', - chance: 0.5, - amountBetween: [100, 500], - }, - { - name: 'Spider Silk', - chance: 0.05, - amountBetween: [1, 2], - }, - ], - }, - { - name: 'Centipede', - health: 2500, - attack: 180, - defense: 100, - regen: 50, - dropOptions: [ - { - name: 'Seeds', - chance: 0.5, - amountBetween: [100, 500], - }, - { - name: 'Centipede Leg', - chance: 0.2, - amountBetween: [1, 2], - }, - ], - }, - { - name: 'Moth', - health: 1800, - attack: 140, - defense: 70, - regen: 30, - dropOptions: [ - { - name: 'Seeds', - chance: 0.5, - amountBetween: [100, 500], - }, - { - name: 'Moth Dust', - chance: 0.1, - amountBetween: [1, 2], - }, - ], - }, - { - name: 'Butterfly', - health: 3000, - attack: 200, - defense: 120, - regen: 60, - dropOptions: [ - { - name: 'Butterfly Wing', - chance: 0.01, - amountBetween: [1, 2], - }, - { - name: 'Butterfly Dust', - chance: 0.05, - amountBetween: [1, 1], - }, - ], - }, - ], - unlocked: true, - }, - ], - currentEnemy: null, - - enemySpawned: false, - battleRunning: false, // Combat status - isFighting: false, // Whether the combat is currently happening - lastFrameTime: 0, - accumulatedTime: 0, // To accumulate time between frames - combatTick: 2000, // Combat happens every 1000ms (1 second) - - // Kill counts - killCounts: { - grasshopperKills: 0, - beetleKills: 0, - waspKills: 0, + state: () => ({ + loaded: false, // To track when adventure state is fully loaded + progress: 0, // Track progress for offline calculation + + armyHealth: 100, + armyMaxHealth: 100, + armyAttack: 10, + armyDefense: 5, + armyRegen: 5, + + bugHealth: 0, + bugMaxHealth: 0, + bugAttack: 0, + bugDefense: 0, + bugRegen: 2, + + currentArea: 'Wasteland', + enemyWaves: [ + { + name: 'Wasteland', + enemies: [ + { + name: 'Grasshopper', + health: 100, + attack: 8, + defense: 4, + regen: 2, + dropOptions: [ + { + name: 'Seeds', + chance: 0.5, + amountBetween: [100, 500], + }, + { + name: 'Grasshopper Leg', + chance: 0.2, + amountBetween: [1, 2], + }, + ], + }, + { + name: 'Beetle', + health: 150, + attack: 10, + defense: 5, + regen: 3, + dropOptions: [ + { + name: 'Seeds', + chance: 0.5, + amountBetween: [100, 500], + }, + { + name: 'Ant Strength Potion', + chance: 0.1, + amountBetween: [1, 2], + }, + ], + }, + { + name: 'Wasp', + health: 120, + attack: 12, + defense: 6, + regen: 2, + dropOptions: [ + { + name: 'Seeds', + chance: 0.5, + amountBetween: [100, 500], + }, + { + name: 'Queen Crown', + chance: 0.05, + amountBetween: [1, 1], + }, + ], + }, + ], + unlocked: true, }, - }), - - actions: { - toggleBattle(shouldJustStart = false) { - if (this.isFighting && !shouldJustStart) { - console.log('Battle Stopped') - this.stopBattle() // Stop if currently running - } else { - console.log('Battle Started') - this.startBattle() // Start if not running - } - }, - - // Start the battle loop - startBattle() { - this.battleRunning = true - this.isFighting = true - this.lastFrameTime = performance.now() - this.accumulatedTime = 0 - - // Spawn a new enemy if none exists - if (this.bugHealth === 0) { - this.spawnRandomEnemy() - } - - requestAnimationFrame(this.battleLoop) + { + name: 'Forest', + enemies: [ + { + name: 'Spider', + health: 2000, + attack: 150, + defense: 80, + regen: 40, + dropOptions: [ + { + name: 'Seeds', + chance: 0.5, + amountBetween: [100, 500], + }, + { + name: 'Spider Silk', + chance: 0.05, + amountBetween: [1, 2], + }, + ], + }, + { + name: 'Centipede', + health: 2500, + attack: 180, + defense: 100, + regen: 50, + dropOptions: [ + { + name: 'Seeds', + chance: 0.5, + amountBetween: [100, 500], + }, + { + name: 'Centipede Leg', + chance: 0.2, + amountBetween: [1, 2], + }, + ], + }, + { + name: 'Moth', + health: 1800, + attack: 140, + defense: 70, + regen: 30, + dropOptions: [ + { + name: 'Seeds', + chance: 0.5, + amountBetween: [100, 500], + }, + { + name: 'Moth Dust', + chance: 0.1, + amountBetween: [1, 2], + }, + ], + }, + { + name: 'Butterfly', + health: 3000, + attack: 200, + defense: 120, + regen: 60, + dropOptions: [ + { + name: 'Butterfly Wing', + chance: 0.01, + amountBetween: [1, 2], + }, + { + name: 'Butterfly Dust', + chance: 0.05, + amountBetween: [1, 1], + }, + ], + }, + ], + unlocked: true, }, + ], + currentEnemy: null, + + enemySpawned: false, + battleRunning: false, // Combat status + isFighting: false, // Whether the combat is currently happening + battleCooldown: false, + lastFrameTime: 0, + accumulatedTime: 0, // To accumulate time between frames + combatTick: 2000, // Combat happens every 2000ms (2 seconds) + + // Kill counts + killCounts: { + grasshopperKills: 0, + beetleKills: 0, + waspKills: 0, + }, - // Stop the battle loop - stopBattle() { - this.isFighting = false - this.battleRunning = false - }, + // For offline progress + lastSavedTime: Date.now(), + isSimulatingOffline: false, + }), + + actions: { + toggleBattle(shouldJustStart = false) { + if ((this.isFighting && !shouldJustStart) || (this.battleCooldown && !shouldJustStart)) { + console.log('Battle Stopped') + this.stopBattle() // Stop if currently running + } else { + console.log('Battle Started') + this.startBattle() // Start if not running + } + }, - // Main battle loop with requestAnimationFrame - battleLoop(currentTime) { - const deltaTime = currentTime - this.lastFrameTime - this.lastFrameTime = currentTime - this.accumulatedTime += deltaTime + // Start the battle loop + startBattle() { + // Check if already running + if (this.battleRunning) { + console.error('Battle is already running') + return + } + + console.log('Battle Loop Started') + this.battleRunning = true + this.isFighting = true + this.lastFrameTime = performance.now() + this.accumulatedTime = 0 + + // Spawn a new enemy if none exists + if (this.bugHealth === 0 || !this.enemySpawned) { + this.spawnRandomEnemy() + } + + requestAnimationFrame(this.battleLoop) + }, - // Process combat if the accumulated time exceeds the tick threshold - if (this.accumulatedTime >= this.combatTick) { - this.processCombat() - this.accumulatedTime = 0 - } + // Stop the battle loop + stopBattle() { + this.isFighting = false + this.battleRunning = false + this.battleCooldown = false + }, - // Keep running the loop as long as the battle is running - if (this.battleRunning) { - requestAnimationFrame(this.battleLoop) - } - }, + // Main battle loop with requestAnimationFrame + battleLoop(currentTime) { + const deltaTime = currentTime - this.lastFrameTime + this.lastFrameTime = currentTime + this.accumulatedTime += deltaTime - processCombat() { - if (this.isFighting && this.enemySpawned) { - // Combat logic here - const armyDamage = Math.max(this.armyAttack - this.bugDefense, 1) - this.bugHealth = Math.max(this.bugHealth - armyDamage, 0) + // Process combat if the accumulated time exceeds the tick threshold + if (this.accumulatedTime >= this.combatTick) { + this.processCombat() + this.accumulatedTime = 0 + } - const bugDamage = Math.max(this.bugAttack - this.armyDefense, 1) - this.armyHealth = Math.max(this.armyHealth - bugDamage, 0) + // Keep running the loop as long as the battle is running + if (this.battleRunning) { + requestAnimationFrame(this.battleLoop) + } + }, - if (this.armyHealth === 0) { - this.handlePlayerDefeat() - } + processCombat() { + if (this.isFighting && this.enemySpawned) { + this.applyArmyDamage() + this.applyBugDamage() - if (this.bugHealth === 0 && this.enemySpawned) { - this.handleEnemyDefeat() - } + if (this.armyHealth === 0) { + this.handlePlayerDefeat() } - this.applyRegeneration() - }, + if (this.bugHealth === 0) { + this.handleEnemyDefeat() + } + } - handlePlayerDefeat() { - console.log('Bug Wins!') - this.isFighting = false - this.applyRegeneration() // Regenerate after defeat - }, + this.applyRegeneration() // No params for real-time loop + }, - handleEnemyDefeat() { - this.enemySpawned = false - this.isFighting = false + applyArmyDamage() { + const armyDamage = Math.max(this.armyAttack - this.bugDefense, 1) + this.bugHealth = Math.max(this.bugHealth - armyDamage, 0) + }, - // Update kill counts - this.killCounts[this.currentEnemy.name.toLowerCase().replace(/\s+/g, '') + 'Kills'] += 1 + applyBugDamage() { + const bugDamage = Math.max(this.bugAttack - this.armyDefense, 1) + this.armyHealth = Math.max(this.armyHealth - bugDamage, 0) + }, - // Handle loot - this.currentEnemy.dropOptions?.forEach((drop) => { - if (Math.random() < drop.chance) { - const amount = Math.floor( - Math.random() * (drop.amountBetween[1] - drop.amountBetween[0] + 1), - ) + drop.amountBetween[0] - console.log(`Loot: +${amount} ${drop.name}`) + handlePlayerDefeat() { + console.log('Bug Wins!') + this.isFighting = false + this.applyRegeneration() // Regenerate after defeat + }, + handleEnemyDefeat() { + this.enemySpawned = false + this.battleCooldown = true // Enter cooldown state + this.isFighting = false + + // Update kill counts + const killKey = this.currentEnemy.name.toLowerCase().replace(/\s+/g, '') + 'Kills' + if (this.killCounts[killKey] !== undefined) { + this.killCounts[killKey] += 1 + } else { + this.killCounts[killKey] = 1 // Initialize if not present + } + + // Handle loot + this.currentEnemy.dropOptions?.forEach((drop) => { + if (Math.random() < drop.chance) { + const amount = + Math.floor(Math.random() * (drop.amountBetween[1] - drop.amountBetween[0] + 1)) + + drop.amountBetween[0] + console.log(`Loot: +${amount} ${drop.name}`) + + if (!this.isSimulatingOffline) { const $toast = useToast() $toast.success(`Loot: +${amount} ${drop.name}`) + } - if (drop.name === 'Seeds') { - // Add seeds to gameStore - useGameStore().seeds += amount + if (drop.name === 'Seeds') { + // Add seeds to gameStore + useGameStore().seeds += amount + } else { + // Handle item drops + const itemId = drop.name.toLowerCase().replace(/\s+/g, '-') + const item = useInventoryStore().getItemById(itemId) + if (item) { + this.handleItemDrop(item, amount) } else { - // Handle item drops - const itemId = drop.name.toLowerCase().replace(/\s+/g, '-') - const item = useInventoryStore().getItemById(itemId) - if (item) { - this.handleItemDrop(item, amount) - } else { - console.error(`Item ${drop.name} not found in registry`) - } + console.error(`Item ${drop.name} not found in registry`) } } - }) + } + }) - // Spawn a new enemy - setTimeout(() => { - this.spawnRandomEnemy() + // Spawn a new enemy + setTimeout(() => { + this.spawnRandomEnemy() - setTimeout(() => { + setTimeout(() => { + if (this.battleRunning) { this.isFighting = true - }, 1000) - }, 2000) - }, + this.battleCooldown = false + } + }, 1000) + }, 2000) + }, - // Apply effects based on item type - handleItemDrop(item, amount) { - const inventoryStore = useInventoryStore() - inventoryStore.addItemToInventory({ - id: item.id, - name: item.name, - amount, - }) - }, + // Apply effects based on item type + handleItemDrop(item, amount) { + const inventoryStore = useInventoryStore() + inventoryStore.addItemToInventory({ + id: item.id, + name: item.name, + amount, + }) + }, - applyRegeneration() { - if (this.armyHealth < this.armyMaxHealth) { - this.armyHealth = Math.min(this.armyHealth + this.armyRegen, this.armyMaxHealth) - } + applyRegeneration(deltaTime = null) { + const regenTicks = deltaTime ? Math.floor(deltaTime) : 1 // Use deltaTime for offline, or 1 tick for real-time + + // Apply army regeneration + this.armyHealth = Math.min( + this.armyHealth + this.armyRegen * regenTicks, + this.armyMaxHealth, + ) + + // Apply bug regeneration if the bug was spawned + if (this.enemySpawned) { + this.bugHealth = Math.min( + this.bugHealth + this.bugRegen * regenTicks, + this.bugMaxHealth, + ) + } + }, - if (this.bugHealth < this.bugMaxHealth && this.enemySpawned) { - this.bugHealth = Math.min(this.bugHealth + this.bugRegen, this.bugMaxHealth) - } - }, + spawnRandomEnemy() { + const enemies = this.enemyWaves.find((wave) => wave.name === this.currentArea)?.enemies + if (!enemies) { + console.error('No enemies found for the current area') + return + } + + const randomIndex = Math.floor(Math.random() * enemies.length) + const enemy = enemies[randomIndex] + this.currentEnemy = enemy + + this.bugHealth = enemy.health + this.bugMaxHealth = enemy.health + this.bugAttack = enemy.attack + this.bugDefense = enemy.defense + this.bugRegen = enemy.regen + + console.log(`New Enemy Spawned: ${enemy.name}`) + this.enemySpawned = true + }, - spawnRandomEnemy() { - const enemies = this.enemyWaves.find(wave => wave.name === this.currentArea)?.enemies - if (!enemies) { - console.error('No enemies found for the current area') - return - } + // Save adventure state to Firebase Firestore + // Save adventure state to Firebase Firestore + async saveAdventureState() { + const userId = await useGameStore().getUserId() + if (!userId) { + console.error('User ID not found') + return + } + + const adventureState = { + armyHealth: this.armyHealth, + armyMaxHealth: this.armyMaxHealth, + armyAttack: this.armyAttack, + armyDefense: this.armyDefense, + armyRegen: this.armyRegen, + killCounts: this.killCounts, + currentArea: this.currentArea, + isFighting: this.isFighting || this.battleCooldown, // Save the current battle state + lastSavedTime: Date.now(), + userId: userId, + } + + console.log('Saving adventure state to Firestore:', adventureState) + + try { + await setDoc(doc(db, 'adventure', userId), adventureState) + console.log('Adventure state saved to Firestore') + } catch (error) { + console.error('Error saving adventure state to Firestore:', error) + } + }, - const randomIndex = Math.floor(Math.random() * enemies.length) - const enemy = enemies[randomIndex] - this.currentEnemy = enemy + // Load adventure state from Firebase Firestore + async loadAdventureState() { + this.loaded = false // Mark as not loaded - this.bugHealth = enemy.health - this.bugMaxHealth = enemy.health - this.bugAttack = enemy.attack - this.bugDefense = enemy.defense - this.bugRegen = enemy.regen + try { + const gameStore = useGameStore() + const userId = await gameStore.getUserId() + if (!userId) { + console.error('User ID not found') + return + } - console.log(`New Enemy Spawned: ${enemy.name}`) - this.enemySpawned = true - }, + const docRef = doc(db, 'adventure', userId) + const docSnap = await getDoc(docRef) + + if (docSnap.exists()) { + const adventureState = docSnap.data() + console.log('Adventure state loaded from Firestore:', adventureState) + + // Load the saved state + this.armyHealth = adventureState.armyHealth ?? this.armyHealth + this.armyMaxHealth = adventureState.armyMaxHealth ?? this.armyMaxHealth + this.armyAttack = adventureState.armyAttack ?? this.armyAttack + this.armyDefense = adventureState.armyDefense ?? this.armyDefense + this.armyRegen = adventureState.armyRegen ?? this.armyRegen + this.killCounts = adventureState.killCounts ?? this.killCounts + this.currentArea = adventureState.currentArea ?? this.currentArea + this.isFighting = adventureState.isFighting ?? false + this.lastSavedTime = adventureState.lastSavedTime ?? Date.now() + + // Mark as loaded once the state is fully set + this.loaded = true + } else { + console.log('No adventure state found in Firestore') + this.loaded = true + } + } catch (error) { + console.error('Error loading adventure state from Firestore:', error) + this.loaded = true + } + }, - // Save adventure state to Firebase Firestore - async saveAdventureState() { - const userId = await useGameStore().getUserId() + // Reset adventure state and clear from Firebase Firestore + async resetAdventureState() { + try { + const gameStore = useGameStore() // Access the gameStore + const userId = await gameStore.getUserId() // Use gameStore's getUserId method if (!userId) { console.error('User ID not found') return } - const adventureState = { - armyHealth: this.armyHealth, - armyMaxHealth: this.armyMaxHealth, - armyAttack: this.armyAttack, - armyDefense: this.armyDefense, - armyRegen: this.armyRegen, - killCounts: this.killCounts, - currentArea: this.currentArea, - - lastSavedTime: Date.now(), - userId: userId, + // Clear the user's adventure state from Firestore + const docRef = doc(db, 'adventure', userId) + await deleteDoc(docRef) // Delete the document from Firestore + + // Reset the local adventure state + this.armyHealth = 100 + this.armyMaxHealth = 100 + this.armyAttack = 10 + this.armyDefense = 5 + this.armyRegen = 5 + this.killCounts = { + grasshopperKills: 0, + beetleKills: 0, + waspKills: 0, } + this.lastSavedTime = Date.now() + console.log('Adventure state reset and cleared from Firestore') + } catch (error) { + console.error('Error resetting adventure state:', error) + } + }, + + // Offline progress calculation + calculateOfflineProgress() { + return new Promise((resolve, reject) => { try { - const gameStore = useGameStore() // Access the gameStore - const userId = await gameStore.getUserId() // Use gameStore's getUserId method - if (!userId) { - console.error('User ID not found') - return + const currentTime = Date.now() + const timeElapsed = (currentTime - this.lastSavedTime) / 1000 + console.log(`Time elapsed (offline): ${timeElapsed} seconds`) + + let remainingTime = timeElapsed + const chunkDuration = 60 + + this.isSimulatingOffline = true + this.progress = 0 // Initialize progress + + const simulateOffline = () => { + if (remainingTime <= 0) { + this.lastSavedTime = currentTime + console.log('Offline progress simulation complete.') + this.isSimulatingOffline = false + this.progress = 100 // Set progress to 100% + resolve() + return + } + + const deltaTime = Math.min(chunkDuration, remainingTime) + this.updateCombat(deltaTime) + this.applyRegeneration(deltaTime) + this.handleLoot() + + remainingTime -= deltaTime + this.progress = Math.min(100, ((timeElapsed - remainingTime) / timeElapsed) * 100) // Update progress + + setTimeout(simulateOffline, 0) } - await setDoc(doc(db, 'adventure', userId), adventureState).then(() => { - console.log('Adventure state saved to Firestore') - }).catch((error) => { - console.error('Error saving adventure state to Firestore:', error) - }) + simulateOffline() } catch (error) { - console.error('Error saving adventure state to Firebase:', error) + console.error('Error during offline progress simulation:', error) + this.isSimulatingOffline = false + reject(error) } - }, + }) + }, - // Load adventure state from Firebase Firestore - async loadAdventureState() { - try { - const gameStore = useGameStore() // Access the gameStore - const userId = await gameStore.getUserId() // Use gameStore's getUserId method - if (!userId) { - console.error('User ID not found') - return - } + updateCombat(deltaTime) { + const combatTicks = Math.floor(deltaTime / (this.combatTick / 1000)) // Number of combat ticks - const docRef = doc(db, 'adventure', userId) - const docSnap = await getDoc(docRef) + for (let i = 0; i < combatTicks; i++) { + if (!this.enemySpawned) { + this.spawnRandomEnemy() // Spawn a new enemy if none exists + } - if (docSnap.exists()) { - const adventureState = docSnap.data() + // Army attacks the bug + const armyDamage = Math.max(this.armyAttack - this.bugDefense, 1) + this.bugHealth = Math.max(this.bugHealth - armyDamage, 0) - this.armyHealth = adventureState.armyHealth ?? this.armyHealth - this.armyMaxHealth = adventureState.armyMaxHealth ?? this.armyMaxHealth - this.armyAttack = adventureState.armyAttack ?? this.armyAttack - this.armyDefense = adventureState.armyDefense ?? this.armyDefense - this.armyRegen = adventureState.armyRegen ?? this.armyRegen - this.killCounts = adventureState.killCounts ?? this.killCounts - this.currentArea = adventureState.currentArea ?? this.currentArea + // Bug attacks the army + const bugDamage = Math.max(this.bugAttack - this.armyDefense, 1) + this.armyHealth = Math.max(this.armyHealth - bugDamage, 0) - console.log('Adventure state loaded from Firestore') - } else { - console.log('No adventure state found in Firestore') - } - } catch (error) { - console.error('Error loading adventure state from Firestore:', error) + // Check if either the army or the bug is defeated + if (this.armyHealth === 0) { + this.handlePlayerDefeat() + break // Stop combat if the player is defeated } - }, - // Reset adventure state and clear from Firebase Firestore - async resetAdventureState() { - try { - const gameStore = useGameStore() // Access the gameStore - const userId = await gameStore.getUserId() // Use gameStore's getUserId method - if (!userId) { - console.error('User ID not found') - return - } + if (this.bugHealth === 0) { + this.handleEnemyDefeat() + // After defeating an enemy, reset health for army (optional) + // this.armyHealth = this.armyMaxHealth + // Continue to next enemy + } + } + }, - // Clear the user's adventure state from Firestore - const docRef = doc(db, 'adventure', userId) - await deleteDoc(docRef) // Delete the document from Firestore - - // Reset the local adventure state - this.armyHealth = 100 - this.armyMaxHealth = 100 - this.armyAttack = 10 - this.armyDefense = 5 - this.armyRegen = 5 - this.killCounts = { - grasshopperKills: 0, - beetleKills: 0, - waspKills: 0, + handleLoot() { + if (this.bugHealth === 0 && this.enemySpawned) { + this.currentEnemy.dropOptions?.forEach((drop) => { + if (Math.random() < drop.chance) { + const amount = + Math.floor(Math.random() * (drop.amountBetween[1] - drop.amountBetween[0] + 1)) + + drop.amountBetween[0] + console.log(`Loot: +${amount} ${drop.name}`) + + // Only show toast notifications if not simulating offline progress + if (!this.isSimulatingOffline) { + const $toast = useToast() + $toast.success(`Loot: +${amount} ${drop.name}`) + } + + if (drop.name === 'Seeds') { + useGameStore().seeds += amount + } else { + const itemId = drop.name.toLowerCase().replace(/\s+/g, '-') + const item = useInventoryStore().getItemById(itemId) + if (item) { + this.handleItemDrop(item, amount) + } else { + console.error(`Item ${drop.name} not found in registry`) + } + } } + }) - console.log('Adventure state reset and cleared from Firestore') - } catch (error) { - console.error('Error resetting adventure state:', error) - } - }, + this.enemySpawned = false + } }, }, -) - +}) diff --git a/src/stores/gameStore.ts b/src/stores/gameStore.ts index 0812804..b872fe2 100644 --- a/src/stores/gameStore.ts +++ b/src/stores/gameStore.ts @@ -276,8 +276,21 @@ export const useGameStore = defineStore('gameStore', { }, updateResources(deltaTime) { - this.larvae = Math.min(this.larvae + this.larvaeProductionRate * this.queens * deltaTime / 60, this.maxLarvae) - this.seeds = Math.min(this.seeds + this.collectionRatePerAnt * this.ants * deltaTime / 60, this.maxSeeds) + // Update larvae, but only if there are queens + if (this.queens > 0) { + this.larvae = Math.min( + this.larvae + (this.larvaeProductionRate * this.queens * deltaTime) / 60, + this.maxLarvae, + ) + } + + // Update seeds, but only if there are ants + if (this.ants > 0) { + this.seeds = Math.min( + this.seeds + (this.collectionRatePerAnt * this.ants * deltaTime) / 60, + this.maxSeeds, + ) + } }, handleAutoCreations() { @@ -479,6 +492,13 @@ export const useGameStore = defineStore('gameStore', { // Recalculate based on upgrades, apply offline progress await this.calculateOfflineProgress() this.setupAdventureStats() + const adventureStore = useAdventureStore() + await adventureStore.calculateOfflineProgress() + + if (adventureStore.isFighting) { + adventureStore.startBattle() + } + this.loaded = true console.log('Game state loaded successfully') } catch (error) { diff --git a/src/views/Adventure.vue b/src/views/Adventure.vue index 6523c19..f0277d9 100644 --- a/src/views/Adventure.vue +++ b/src/views/Adventure.vue @@ -2,7 +2,7 @@

- Note: There's not progression offline yet, so you have to be active to progress. + Note: Offline progress has been implemented 09/10/2024.

diff --git a/src/views/Home.vue b/src/views/Home.vue index 7ab01d3..1bf7d45 100644 --- a/src/views/Home.vue +++ b/src/views/Home.vue @@ -1,6 +1,6 @@