├── .github └── workflows │ └── idle-wild-my-survival-saga.yml ├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── docs ├── CNAME ├── assets │ ├── css │ │ ├── index-Cx4m5gF6.css │ │ └── vendor-modules-F1JXWUuM.css │ └── js │ │ ├── index-BMGkEoj6.js │ │ └── vendor-modules-BJ6MjZ7a.js └── index.html ├── index.html ├── package.json ├── pnpm-lock.yaml ├── public └── CNAME ├── src ├── App.vue ├── components │ ├── AchievementSystem.vue │ ├── ActivityPanel.vue │ ├── BuildingPanel.vue │ ├── EventLog.vue │ ├── ExplorationPanel.vue │ ├── GameInterface.vue │ ├── PlayerStatus.vue │ ├── QuestSystem.vue │ ├── RandomEventSystem.vue │ ├── ResearchPanel.vue │ ├── ResourcePanel.vue │ ├── SkillTreeSystem.vue │ ├── TimeControl.vue │ ├── TradingSystem.vue │ └── WeatherSystem.vue ├── main.js ├── plugins │ ├── achievements.js │ ├── crypto.js │ ├── eventLibrary.js │ ├── explorationRegions.js │ ├── merchants.js │ ├── recipes.js │ ├── resource.js │ ├── skillTree.js │ └── weatherTypes.js └── stores │ ├── gameStore.js │ └── index.js └── vite.config.js /.github/workflows/idle-wild-my-survival-saga.yml: -------------------------------------------------------------------------------- 1 | name: 自动化创建Docker镜像 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | permissions: 12 | contents: read 13 | packages: write 14 | 15 | steps: 16 | - name: 检查代码 17 | uses: actions/checkout@v2 18 | 19 | - name: 登录 GitHub Container Registry 20 | uses: docker/login-action@v2 21 | with: 22 | registry: ghcr.io 23 | username: ${{ github.actor }} 24 | password: ${{ secrets.GITHUB_TOKEN }} 25 | 26 | - name: 构建Docker镜像 27 | run: docker build -t ghcr.io/${{ github.repository_owner }}/idle-wild-my-survival-saga:latest . 28 | 29 | - name: 推送到 GitHub Container Registry 30 | run: docker push ghcr.io/${{ github.repository_owner }}/idle-wild-my-survival-saga:latest 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:latest 2 | 3 | RUN mkdir -p /workspace 4 | 5 | WORKDIR /workspace 6 | 7 | RUN npm config set registry https://registry.npmmirror.com 8 | 9 | RUN cd /workspace 10 | 11 | RUN git clone https://github.com/setube/idle-wild-my-survival-saga.git 12 | 13 | RUN mv ./idle-wild-my-survival-saga/* . ; rm -rf ./idle-wild-my-survival-saga/ 14 | 15 | RUN npm install -g pnpm ; pnpm install ; npx vite build 16 | 17 | CMD ["npx", "vite", "preview", "--host", "0.0.0.0", "--port", "2543"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Creative Commons Attribution-NonCommercial 4.0 International Public License 2 | 3 | This work is licensed under the Creative Commons Attribution-NonCommercial 4.0 4 | International Public License. To view a copy of this license, visit 5 | https://creativecommons.org/licenses/by-nc/4.0/legalcode. 6 | 7 | You are free to: 8 | Share — copy and redistribute the material in any medium or format 9 | Adapt — remix, transform, and build upon the material 10 | 11 | Under the following terms: 12 | Attribution — You must give appropriate credit, provide a link to the license, 13 | and indicate if changes were made. You may do so in any reasonable manner, 14 | but not in any way that suggests the licensor endorses you or your use. 15 | 16 | NonCommercial — You may not use the material for commercial purposes. 17 | 18 | No additional restrictions — You may not apply legal terms or technological 19 | measures that legally restrict others from doing anything the license permits. 20 | 21 | Notice: 22 | This work is the original creation of Jun Qian (谦君). Source code available at: 23 | https://github.com/setube/idle-wild-my-survival-saga 24 | This license does not constitute a waiver of any copyright or related rights. 25 | 26 | When you share adaptations of this work, you must: 27 | - Provide prominent attribution to the original author 28 | - Retain this license document 29 | - Clearly indicate modifications made and dates 30 | - Distribute under the same CC BY-NC 4.0 license 31 | 32 | © 2025 Jun Qian - All rights reserved (except those granted by this license) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 我的荒野放置求生记 2 | ![游戏截图](https://i.miji.bid/2025/04/04/0917160f7f1173616432b3dfab50fc85.png) 3 | 4 | ## 项目简介 5 | 基于Vue3 + Pinia构建的生存模拟游戏,玩家需要在荒野中收集资源、建造设施、研究科技并应对天气变化。游戏包含完整的资源管理系统、技能成长系统和动态天气系统。 6 | 7 | ## 功能特性 8 | - 🏡 建筑系统:建造/升级庇护所、仓库、工作坊等设施 9 | - 🌟 技能成长:采集/制作/战斗/生存/研究五大技能体系 10 | - ⚙️ 科技树:解锁科技,开启高级制作配方 11 | - 🌦️ 动态天气:昼夜交替、季节变化影响游戏机制 12 | - 📊 状态管理:使用Pinia管理复杂游戏状态 13 | - 💾 游戏存档:支持本地存储和加密存档 14 | 15 | ## 技术栈 16 | - 前端框架:Vue 3 + Composition API 17 | - UI组件库:Element Plus 18 | - 状态管理:Pinia 19 | - 核心语言:JavaScript 20 | - 构建工具:Vite 21 | - 数据加密:CryptoJS 22 | 23 | ## 特别感谢 24 | - Vue.js 团队提供了优秀的前端框架 25 | - Element Plus 团队提供了高质量的UI组件 26 | - Vite 团队提供了高效的构建工具 27 | - Pinia 团队提供了简洁的状态管理方案 28 | 29 | ## 项目部署 30 | ### 安装项目 31 | ```bash 32 | npm install 33 | ``` 34 | 35 | ### 运行项目 36 | ```bash 37 | npm run dev 38 | ``` 39 | 40 | ### 编译项目 41 | ```bash 42 | npm run build 43 | ``` 44 | 45 | ## Docker 部署 46 | 47 | ### 构建镜像 48 | ```bash 49 | docker build -t ghcr.io/setube/idle-wild-my-survival-saga:latest . 50 | ``` 51 | ### 拉取镜像 52 | ```bash 53 | docker pull ghcr.io/setube/idle-wild-my-survival-saga:latest 54 | ``` 55 | ### 运行容器 56 | ```bash 57 | docker run -d -p 2543:80 --name idle-wild-my-survival-saga ghcr.io/setube/idle-wild-my-survival-saga:latest 58 | ``` 59 | 60 | 61 | ## 版权声明 62 | 知识共享署名-非商业性使用 4.0 国际许可协议 63 | 64 | 本作品采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可。 65 | 要查看此许可协议的副本,请访问 http://creativecommons.org/licenses/by-nc/4.0/。 66 | 67 | 您自由地: 68 | 共享 — 在任何媒介以任何形式复制、发行本作品 69 | 改编 — 修改、转换或以本作品为基础进行创作 70 | 71 | 惟须遵守以下条件: 72 | 署名 — 您必须给出适当的署名,提供指向本许可协议的链接,同时标明是否(对原始作品)作了修改。您可以用任何合理的方式来署名,但不得以任何方式暗示许可人为您或您的使用背书。 73 | 74 | 非商业性使用 — 您不得将本作品用于商业目的。 75 | 76 | 没有附加限制 — 您不得适用法律术语或者技术措施从而限制其他人做许可协议允许的事情。 77 | 78 | 声明: 79 | 本作品是作者(谦君)的原创作品,项目源码地址:https://github.com/setube/idle-wild-my-survival-saga 80 | 本授权条款不得被视为或解释为对任何版权的放弃或其他限制。 81 | 82 | 当您分享本作品的改编版本时,您必须: 83 | - 在显著位置标注原作者的署名 84 | - 保留本许可协议文档 85 | - 明确说明修改内容及修改日期 86 | - 使用相同的 CC BY-NC 4.0 协议进行分发 87 | 88 | © 2025 谦君 - 保留所有权利(根据本许可协议授予的权限除外) 89 | -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | idle-wild-my-survival-saga.wenzi.games -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 我的荒野放置求生记
-------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | 我的荒野放置求生记 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "idle-wild-my-survival-saga", 3 | "title": "我的荒野放置求生记", 4 | "private": true, 5 | "version": "1.0.0", 6 | "type": "module", 7 | "scripts": { 8 | "dev": "vite --port 2543", 9 | "build": "vite build", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "@element-plus/icons-vue": "^2.3.1", 14 | "crypto-js": "^4.2.0", 15 | "element-plus": "^2.9.7", 16 | "file-saver": "^2.0.5", 17 | "lodash-es": "^4.17.21", 18 | "pinia": "^3.0.1", 19 | "vite-plugin-bundle-obfuscator": "^1.4.2", 20 | "vue": "^3.5.13", 21 | "vue-router": "4" 22 | }, 23 | "devDependencies": { 24 | "@vitejs/plugin-vue": "^5.2.1", 25 | "terser": "^5.39.0", 26 | "unplugin-auto-import": "^19.1.2", 27 | "unplugin-vue-components": "^28.4.1", 28 | "vite": "^6.2.0" 29 | } 30 | } -------------------------------------------------------------------------------- /public/CNAME: -------------------------------------------------------------------------------- 1 | idle-wild-my-survival-saga.wenzi.games -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 22 | 23 | 71 | 72 | -------------------------------------------------------------------------------- /src/components/AchievementSystem.vue: -------------------------------------------------------------------------------- 1 | 71 | 72 | 113 | 114 | -------------------------------------------------------------------------------- /src/components/BuildingPanel.vue: -------------------------------------------------------------------------------- 1 | 344 | 345 | 416 | 417 | -------------------------------------------------------------------------------- /src/components/EventLog.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 18 | 19 | -------------------------------------------------------------------------------- /src/components/PlayerStatus.vue: -------------------------------------------------------------------------------- 1 | 73 | 74 | 147 | 148 | -------------------------------------------------------------------------------- /src/components/QuestSystem.vue: -------------------------------------------------------------------------------- 1 | 421 | 422 | 550 | 551 | -------------------------------------------------------------------------------- /src/components/RandomEventSystem.vue: -------------------------------------------------------------------------------- 1 | 107 | 108 | 137 | 138 | -------------------------------------------------------------------------------- /src/components/ResearchPanel.vue: -------------------------------------------------------------------------------- 1 | 340 | 341 | 436 | 437 | -------------------------------------------------------------------------------- /src/components/ResourcePanel.vue: -------------------------------------------------------------------------------- 1 | 83 | 84 | 138 | 139 | -------------------------------------------------------------------------------- /src/components/TimeControl.vue: -------------------------------------------------------------------------------- 1 | 91 | 92 | 119 | 120 | -------------------------------------------------------------------------------- /src/components/TradingSystem.vue: -------------------------------------------------------------------------------- 1 | 172 | 173 | 275 | 276 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | import ElementPlus from 'element-plus' 4 | import 'element-plus/dist/index.css' 5 | import 'element-plus/theme-chalk/dark/css-vars.css' 6 | import pinia from './stores' 7 | import * as ElementPlusIconsVue from '@element-plus/icons-vue' 8 | 9 | const app = createApp(App) 10 | 11 | app.use(ElementPlus) 12 | app.use(pinia) 13 | for (const [key, component] of Object.entries(ElementPlusIconsVue)) { 14 | app.component(key, component) 15 | } 16 | app.mount('#app') 17 | -------------------------------------------------------------------------------- /src/plugins/achievements.js: -------------------------------------------------------------------------------- 1 | export const achievements = [ 2 | { 3 | id: 'first_day', 4 | name: '新的开始', 5 | description: '在这个世界生存了一天', 6 | icon: '🌅', 7 | condition: (store) => store.player.days >= 1, 8 | reward: { exp: 10 }, 9 | unlocked: false 10 | }, 11 | { 12 | id: 'week_survivor', 13 | name: '一周生存者', 14 | description: '在这个世界生存了7天', 15 | icon: '📅', 16 | condition: (store) => store.player.days >= 7, 17 | reward: { exp: 30 }, 18 | unlocked: false 19 | }, 20 | { 21 | id: 'month_survivor', 22 | name: '月度生存者', 23 | description: '在这个世界生存了30天', 24 | icon: '🗓️', 25 | condition: (store) => store.player.days >= 30, 26 | reward: { exp: 100 }, 27 | unlocked: false 28 | }, 29 | { 30 | id: 'season_cycle', 31 | name: '四季循环', 32 | description: '经历了1个完整的四季循环', 33 | icon: '🔄', 34 | condition: (store) => store.player.days >= 120, 35 | reward: { exp: 200 }, 36 | unlocked: false 37 | }, 38 | { 39 | id: 'season_cycle-2', 40 | name: '四季循环-2', 41 | description: '经历了2个完整的四季循环', 42 | icon: '🔄', 43 | condition: (store) => store.player.days >= 240, 44 | reward: { exp: 200 }, 45 | unlocked: false 46 | }, 47 | { 48 | id: 'season_cycle-3', 49 | name: '四季循环-3', 50 | description: '经历了3个完整的四季循环', 51 | icon: '🔄', 52 | condition: (store) => store.player.days >= 360, 53 | reward: { exp: 200 }, 54 | unlocked: false 55 | }, 56 | { 57 | id: 'resource_collector', 58 | name: '资源收集者', 59 | description: '累计收集超过100单位的基础资源', 60 | icon: '📦', 61 | condition: (store) => { 62 | const basicResources = ['food', 'water', 'wood', 'stone'] 63 | return basicResources.reduce((sum, res) => sum + store.resources[res], 0) >= 100 64 | }, 65 | reward: { exp: 50 }, 66 | unlocked: false 67 | }, 68 | { 69 | id: 'resource_collector-2', 70 | name: '资源收集者-2', 71 | description: '累计收集超过200单位的基础资源', 72 | icon: '📦', 73 | condition: (store) => { 74 | const basicResources = ['food', 'water', 'wood', 'stone'] 75 | return basicResources.reduce((sum, res) => sum + store.resources[res], 0) >= 200 76 | }, 77 | reward: { exp: 50 }, 78 | unlocked: false 79 | }, 80 | { 81 | id: 'resource_collector-3', 82 | name: '资源收集者-3', 83 | description: '累计收集超过300单位的基础资源', 84 | icon: '📦', 85 | condition: (store) => { 86 | const basicResources = ['food', 'water', 'wood', 'stone'] 87 | return basicResources.reduce((sum, res) => sum + store.resources[res], 0) >= 300 88 | }, 89 | reward: { exp: 50 }, 90 | unlocked: false 91 | }, 92 | { 93 | id: 'master_gatherer', 94 | name: '采集大师', 95 | description: '采集技能达到5级', 96 | icon: '🧺', 97 | condition: (store) => store.newSkills.gathering.level >= 5, 98 | reward: { exp: 80 }, 99 | unlocked: false 100 | }, 101 | { 102 | id: 'master_gatherer-2', 103 | name: '采集大师-2', 104 | description: '采集技能达到20级', 105 | icon: '🧺', 106 | condition: (store) => store.newSkills.gathering.level >= 20, 107 | reward: { exp: 80 }, 108 | unlocked: false 109 | }, 110 | { 111 | id: 'master_gatherer-3', 112 | name: '采集大师-3', 113 | description: '采集技能达到50级', 114 | icon: '🧺', 115 | condition: (store) => store.newSkills.gathering.level >= 50, 116 | reward: { exp: 80 }, 117 | unlocked: false 118 | }, 119 | { 120 | id: 'master_crafter', 121 | name: '制作大师', 122 | description: '制作技能达到5级', 123 | icon: '🔨', 124 | condition: (store) => store.newSkills.crafting.level >= 5, 125 | reward: { exp: 80 }, 126 | unlocked: false 127 | }, 128 | { 129 | id: 'master_crafter-2', 130 | name: '制作大师-2', 131 | description: '制作技能达到20级', 132 | icon: '🔨', 133 | condition: (store) => store.newSkills.crafting.level >= 20, 134 | reward: { exp: 80 }, 135 | unlocked: false 136 | }, 137 | { 138 | id: 'master_crafter-3', 139 | name: '制作大师-3', 140 | description: '制作技能达到50级', 141 | icon: '🔨', 142 | condition: (store) => store.newSkills.crafting.level >= 50, 143 | reward: { exp: 80 }, 144 | unlocked: false 145 | }, 146 | { 147 | id: 'master_survivor', 148 | name: '生存大师', 149 | description: '生存技能达到5级', 150 | icon: '🏕️', 151 | condition: (store) => store.newSkills.survival.level >= 5, 152 | reward: { exp: 80 }, 153 | unlocked: false 154 | }, 155 | { 156 | id: 'master_survivor-2', 157 | name: '生存大师-2', 158 | description: '生存技能达到20级', 159 | icon: '🏕️', 160 | condition: (store) => store.newSkills.survival.level >= 20, 161 | reward: { exp: 80 }, 162 | unlocked: false 163 | }, 164 | { 165 | id: 'master_survivor-3', 166 | name: '生存大师-3', 167 | description: '生存技能达到50级', 168 | icon: '🏕️', 169 | condition: (store) => store.newSkills.survival.level >= 50, 170 | reward: { exp: 80 }, 171 | unlocked: false 172 | }, 173 | { 174 | id: 'master_researcher', 175 | name: '研究大师', 176 | description: '研究技能达到5级', 177 | icon: '🔬', 178 | condition: (store) => store.newSkills.research.level >= 5, 179 | reward: { exp: 80 }, 180 | unlocked: false 181 | }, 182 | { 183 | id: 'master_researcher-2', 184 | name: '研究大师-2', 185 | description: '研究技能达到20级', 186 | icon: '🔬', 187 | condition: (store) => store.newSkills.research.level >= 20, 188 | reward: { exp: 80 }, 189 | unlocked: false 190 | }, 191 | { 192 | id: 'master_researcher-3', 193 | name: '研究大师-3', 194 | description: '研究技能达到50级', 195 | icon: '🔬', 196 | condition: (store) => store.newSkills.research.level >= 50, 197 | reward: { exp: 80 }, 198 | unlocked: false 199 | }, 200 | { 201 | id: 'tech_enthusiast', 202 | name: '科技爱好者', 203 | description: '解锁10项科技', 204 | icon: '💡', 205 | condition: (store) => store.researched.length >= 10, 206 | reward: { exp: 100 }, 207 | unlocked: false 208 | }, 209 | { 210 | id: 'builder', 211 | name: '建设者', 212 | description: '建造3座建筑', 213 | icon: '🏗️', 214 | condition: (store) => store.buildings.length >= 3, 215 | reward: { exp: 70 }, 216 | unlocked: false 217 | }, 218 | { 219 | id: 'builder-2', 220 | name: '建设者-2', 221 | description: '建造5座建筑', 222 | icon: '🏗️', 223 | condition: (store) => store.buildings.length >= 5, 224 | reward: { exp: 70 }, 225 | unlocked: false 226 | }, 227 | { 228 | id: 'explorer', 229 | name: '探险家', 230 | description: '完成100次探索活动', 231 | icon: '🧭', 232 | condition: (store) => store.player.explorationCount >= 100, 233 | reward: { exp: 90 }, 234 | unlocked: false 235 | }, 236 | { 237 | id: 'explorer-2', 238 | name: '探险家-2', 239 | description: '完成500次探索活动', 240 | icon: '🧭', 241 | condition: (store) => store.player.explorationCount >= 500, 242 | reward: { exp: 90 }, 243 | unlocked: false 244 | }, 245 | { 246 | id: 'explorer-3', 247 | name: '探险家-3', 248 | description: '完成1000次探索活动', 249 | icon: '🧭', 250 | condition: (store) => store.player.explorationCount >= 1000, 251 | reward: { exp: 90 }, 252 | unlocked: false 253 | }, 254 | { 255 | id: 'relic_hunter', 256 | name: '遗物猎人', 257 | description: '收集3个古代遗物', 258 | icon: '🏺', 259 | condition: (store) => store.resources.ancientRelic >= 3, 260 | reward: { exp: 120 }, 261 | unlocked: false 262 | }, 263 | { 264 | id: 'weather_survivor', 265 | name: '气象生存者', 266 | description: '在极端天气中生存', 267 | icon: '⛈️', 268 | condition: (store) => store.achievements.extremeWeatherSurvived, 269 | reward: { exp: 60 }, 270 | unlocked: false 271 | }, 272 | { 273 | id: 'healthy_survivor', 274 | name: '健康生存者-1', 275 | description: '保持健康在90%以上连续7天', 276 | icon: '❤️', 277 | condition: (store) => store.achievements.healthyDays >= 7, 278 | reward: { exp: 70 }, 279 | unlocked: false 280 | }, 281 | { 282 | id: 'healthy_survivor_2', 283 | name: '健康生存者-2', 284 | description: '保持健康在90%以上连续30天', 285 | icon: '❤️', 286 | condition: (store) => store.achievements.healthyDays >= 30, 287 | reward: { exp: 70 }, 288 | unlocked: false 289 | }, 290 | { 291 | id: 'healthy_survivor_3', 292 | name: '健康生存者-3', 293 | description: '四季循环中持续保持健康在90%以上', 294 | icon: '❤️', 295 | condition: (store) => store.achievements.healthyDays >= 120, 296 | reward: { exp: 70 }, 297 | unlocked: false 298 | } 299 | ] -------------------------------------------------------------------------------- /src/plugins/crypto.js: -------------------------------------------------------------------------------- 1 | import CryptoJS from 'crypto-js' 2 | 3 | // 数据加密 4 | export const encryptData = (data) => { 5 | try { 6 | const jsonStr = JSON.stringify(data) 7 | return CryptoJS.AES.encrypt(jsonStr, __APP_NAME__).toString() 8 | } catch (error) { 9 | console.error('数据加密失败:', error) 10 | return null 11 | } 12 | } 13 | 14 | // 数据解密 15 | export const decryptData = (encryptedData) => { 16 | try { 17 | const bytes = CryptoJS.AES.decrypt(encryptedData, __APP_NAME__) 18 | const decryptedStr = bytes.toString(CryptoJS.enc.Utf8) 19 | return JSON.parse(decryptedStr) 20 | } catch (error) { 21 | console.error('数据解密失败:', error) 22 | return null 23 | } 24 | } -------------------------------------------------------------------------------- /src/plugins/eventLibrary.js: -------------------------------------------------------------------------------- 1 | export const eventTypes = { 2 | positive: { icon: '🍀', color: '#67C23A', title: '幸运事件' }, 3 | neutral: { icon: '⚖️', color: '#909399', title: '普通事件' }, 4 | negative: { icon: '⚠️', color: '#E6A23C', title: '危险事件' }, 5 | disaster: { icon: '🌋', color: '#F56C6C', title: '灾难事件' }, 6 | special: { icon: '✨', color: '#8E44AD', title: '特殊事件' } 7 | } 8 | 9 | export const eventLibrary = [ 10 | // 正面事件 11 | { 12 | id: 'wild_harvest', 13 | title: '野外丰收', 14 | description: '你在野外发现了一片未被发现的资源丰富区域。', 15 | type: 'positive', 16 | condition: (store) => true, // 无条件触发 17 | options: [ 18 | { 19 | text: '采集食物', 20 | effect: (store) => { 21 | const amount = Math.floor(Math.random() * 10) + 5 22 | store.addResource('food', amount) 23 | store.addToEventLog(`你采集了${amount}单位食物`) 24 | return `你采集了${amount}单位食物` 25 | } 26 | }, 27 | { 28 | text: '收集水源', 29 | effect: (store) => { 30 | const amount = Math.floor(Math.random() * 8) + 5 31 | store.addResource('water', amount) 32 | store.addToEventLog(`你收集了${amount}单位水`) 33 | return `你收集了${amount}单位水` 34 | } 35 | }, 36 | { 37 | text: '寻找草药', 38 | effect: (store) => { 39 | const amount = Math.floor(Math.random() * 5) + 2 40 | store.addResource('herb', amount) 41 | store.addToEventLog(`你找到了${amount}单位草药`) 42 | return `你找到了${amount}单位草药` 43 | } 44 | } 45 | ], 46 | weight: 10, 47 | minDay: 1 48 | }, 49 | { 50 | id: 'ancient_cache', 51 | title: '古代遗迹', 52 | description: '你发现了一个被掩埋的古代科技遗迹。', 53 | type: 'positive', 54 | condition: (store) => store.player.days >= 5, 55 | options: [ 56 | { 57 | text: '仔细研究', 58 | effect: (store) => { 59 | store.addResource('techFragment', 2) 60 | store.addSkillExp('research', 30) 61 | store.addToEventLog('你获得了2个科技碎片并提升了研究技能') 62 | return '你获得了2个科技碎片并提升了研究技能' 63 | } 64 | }, 65 | { 66 | text: '快速搜索', 67 | effect: (store) => { 68 | if (Math.random() < 0.7) { 69 | store.addResource('techFragment', 1) 70 | store.addResource('parts', 1) 71 | store.addToEventLog('你获得了1个科技碎片和1个零件') 72 | return '你获得了1个科技碎片和1个零件' 73 | } else { 74 | store.addToEventLog('你搜索时不小心触发了防护机制,一无所获') 75 | return '你搜索时不小心触发了防护机制,一无所获' 76 | } 77 | } 78 | } 79 | ], 80 | weight: 5, 81 | minDay: 5 82 | }, 83 | // 中性事件 84 | { 85 | id: 'wandering_trader', 86 | title: '流浪商人', 87 | description: '一位神秘的流浪商人来到了你的营地,提供一些交易。', 88 | type: 'neutral', 89 | condition: (store) => true, 90 | options: [ 91 | { 92 | text: '用5单位食物换取3单位草药', 93 | condition: (store) => store.resources.food >= 5, 94 | effect: (store) => { 95 | store.consumeResource('food', 5) 96 | store.addResource('herb', 3) 97 | store.addToEventLog('你用5单位食物换取了3单位草药') 98 | return '交易完成:-5食物,+3草药' 99 | } 100 | }, 101 | { 102 | text: '用8单位木材换取2单位工具', 103 | condition: (store) => store.resources.wood >= 8, 104 | effect: (store) => { 105 | store.consumeResource('wood', 8) 106 | store.addResource('tools', 2) 107 | store.addToEventLog('你用8单位木材换取了2单位工具') 108 | return '交易完成:-8木材,+2工具' 109 | } 110 | }, 111 | { 112 | text: '不进行交易', 113 | effect: (store) => { 114 | store.addToEventLog('你婉拒了商人的交易') 115 | return '你婉拒了商人的交易' 116 | } 117 | } 118 | ], 119 | weight: 8, 120 | minDay: 3 121 | }, 122 | { 123 | id: 'lost_traveler', 124 | title: '迷路的旅行者', 125 | description: '你遇到了一位迷路的旅行者,他看起来又饿又渴。', 126 | type: 'neutral', 127 | condition: (store) => store.player.days >= 4, 128 | options: [ 129 | { 130 | text: '分享食物和水', 131 | condition: (store) => store.resources.food >= 3 && store.resources.water >= 3, 132 | effect: (store) => { 133 | store.consumeResource('food', 3) 134 | store.consumeResource('water', 3) 135 | // 随机奖励 136 | const rewards = [ 137 | () => { 138 | store.addResource('medicine', 1) 139 | store.addToEventLog('旅行者感谢你的帮助,给了你1单位药品') 140 | return '旅行者感谢你的帮助,给了你1单位药品' 141 | }, 142 | () => { 143 | store.addResource('techFragment', 1) 144 | store.addToEventLog('旅行者感谢你的帮助,给了你1个科技碎片') 145 | return '旅行者感谢你的帮助,给了你1个科技碎片' 146 | }, 147 | () => { 148 | store.player.exp += store.player.expToNextLevel * 0.1 149 | store.addToEventLog('旅行者感谢你的帮助,分享了一些有趣的故事,你获得了许多幸存者经验') 150 | return '旅行者感谢你的帮助,分享了一些有趣的故事,你获得了许多幸存者经验' 151 | } 152 | ] 153 | return rewards[Math.floor(Math.random() * rewards.length)]() 154 | } 155 | }, 156 | { 157 | text: '无视他', 158 | effect: (store) => { 159 | store.player.health -= 5 160 | store.addToEventLog('你选择无视旅行者,这让你感到有些内疚') 161 | return '你选择无视旅行者,这让你感到有些内疚' 162 | } 163 | } 164 | ], 165 | weight: 7, 166 | minDay: 4 167 | }, 168 | // 负面事件 169 | { 170 | id: 'food_spoilage', 171 | title: '食物腐败', 172 | description: '你储存的一些食物因为保存不当而腐败了。', 173 | type: 'negative', 174 | condition: (store) => store.resources.food >= 5, 175 | options: [ 176 | { 177 | text: '丢弃腐败食物', 178 | effect: (store) => { 179 | const amount = Math.floor(store.resources.food * 0.3) 180 | store.consumeResource('food', amount) 181 | store.addToEventLog(`你丢弃了${amount}单位腐败的食物`) 182 | return `你丢弃了${amount}单位腐败的食物` 183 | } 184 | }, 185 | { 186 | text: '尝试挽救', 187 | effect: (store) => { 188 | if (store.newSkills.survival.level >= 3) { 189 | const amount = Math.floor(store.resources.food * 0.15) 190 | store.consumeResource('food', amount) 191 | store.addToEventLog(`凭借你的生存技能,你只损失了${amount}单位食物`) 192 | return `凭借你的生存技能,你只损失了${amount}单位食物` 193 | } else { 194 | const amount = Math.floor(store.resources.food * 0.4) 195 | store.consumeResource('food', amount) 196 | store.player.health -= 5 197 | store.addToEventLog(`你尝试挽救腐败食物,但失败了,损失了${amount}单位食物,还感到有些不适`) 198 | return `你尝试挽救腐败食物,但失败了,损失了${amount}单位食物,还感到有些不适` 199 | } 200 | } 201 | } 202 | ], 203 | weight: 6, 204 | minDay: 5 205 | }, 206 | { 207 | id: 'tool_break', 208 | title: '工具损坏', 209 | description: '你的一些工具在使用过程中损坏了。', 210 | type: 'negative', 211 | condition: (store) => store.resources.tools >= 1, 212 | options: [ 213 | { 214 | text: '尝试修复', 215 | effect: (store) => { 216 | if (store.newSkills.crafting.level >= 2 && store.resources.metal >= 1) { 217 | store.consumeResource('metal', 1) 218 | store.addToEventLog('你成功修复了损坏的工具') 219 | return '你成功修复了损坏的工具' 220 | } else { 221 | store.consumeResource('tools', 1) 222 | store.addToEventLog('你无法修复工具,损失了1单位工具') 223 | return '你无法修复工具,损失了1单位工具' 224 | } 225 | } 226 | }, 227 | { 228 | text: '放弃修复', 229 | effect: (store) => { 230 | store.consumeResource('tools', 1) 231 | store.addToEventLog('你放弃修复,损失了1单位工具') 232 | return '你放弃修复,损失了1单位工具' 233 | } 234 | } 235 | ], 236 | weight: 5, 237 | minDay: 6 238 | }, 239 | // 灾难事件 240 | { 241 | id: 'severe_storm', 242 | title: '强烈风暴', 243 | description: '一场强烈的风暴袭击了你的营地,造成了严重破坏。', 244 | type: 'disaster', 245 | condition: (store) => store.player.days >= 10, 246 | options: [ 247 | { 248 | text: '寻找庇护', 249 | effect: (store) => { 250 | const hasShelter = store.buildings.some(b => b.id === 'shelter' && b.level >= 2) 251 | if (hasShelter) { 252 | store.addToEventLog('你的高级庇护所提供了良好的保护,你安全度过了风暴') 253 | return '你的高级庇护所提供了良好的保护,你安全度过了风暴' 254 | } else { 255 | const healthLoss = Math.floor(Math.random() * 10) + 10 256 | store.player.health -= healthLoss 257 | // 随机损失资源 258 | const resources = ['food', 'water', 'wood', 'herb'] 259 | resources.forEach(res => { 260 | if (store.resources[res] > 0) { 261 | const lossAmount = Math.floor(store.resources[res] * 0.3) 262 | if (lossAmount > 0) { 263 | store.consumeResource(res, lossAmount) 264 | } 265 | } 266 | }) 267 | 268 | store.addToEventLog(`你勉强在风暴中生存下来,但损失了健康和资源`) 269 | return `你勉强在风暴中生存下来,但损失了健康和资源` 270 | } 271 | } 272 | }, 273 | { 274 | text: '加固营地', 275 | condition: (store) => store.resources.wood >= 5 && store.resources.stone >= 3, 276 | effect: (store) => { 277 | store.consumeResource('wood', 5) 278 | store.consumeResource('stone', 3) 279 | const healthLoss = Math.floor(Math.random() * 5) + 5 280 | store.player.health -= healthLoss 281 | // 减少资源损失 282 | const resources = ['food', 'water'] 283 | resources.forEach(res => { 284 | if (store.resources[res] > 0) { 285 | const lossAmount = Math.floor(store.resources[res] * 0.15) 286 | if (lossAmount > 0) { 287 | store.consumeResource(res, lossAmount) 288 | } 289 | } 290 | }) 291 | 292 | store.addSkillExp('survival', 20) 293 | store.addToEventLog('你成功加固了营地,减少了风暴造成的损失') 294 | return '你成功加固了营地,减少了风暴造成的损失' 295 | } 296 | } 297 | ], 298 | weight: 3, 299 | minDay: 10 300 | }, 301 | // 特殊事件 302 | { 303 | id: 'mysterious_stranger', 304 | title: '神秘来客', 305 | description: '一位神秘的来客拜访了你的营地,他似乎知道很多关于这个世界的秘密。', 306 | type: 'special', 307 | condition: (store) => store.player.days >= 15, 308 | options: [ 309 | { 310 | text: '询问生存技巧', 311 | effect: (store) => { 312 | store.addSkillExp('survival', 50) 313 | store.addToEventLog('神秘来客教给你一些高级生存技巧') 314 | return '神秘来客教给你一些高级生存技巧,你的生存技能得到提升' 315 | } 316 | }, 317 | { 318 | text: '询问世界秘密', 319 | effect: (store) => { 320 | store.addResource('techFragment', 3) 321 | store.player.health += 10 322 | store.addToEventLog('神秘来客向你透露了一些世界的秘密,并给了你一些科技碎片') 323 | return '神秘来客向你透露了一些世界的秘密,并给了你一些科技碎片' 324 | } 325 | }, 326 | { 327 | text: '保持警惕', 328 | effect: (store) => { 329 | store.addSkillExp('combat', 20) 330 | store.addToEventLog('你对神秘来客保持警惕,提高了你的战斗意识') 331 | return '你对神秘来客保持警惕,提高了你的战斗意识' 332 | } 333 | } 334 | ], 335 | weight: 2, 336 | minDay: 15 337 | } 338 | ] -------------------------------------------------------------------------------- /src/plugins/explorationRegions.js: -------------------------------------------------------------------------------- 1 | const getRandomInt = (min, max) => { 2 | min = Math.ceil(min); 3 | max = Math.floor(max); 4 | return Math.floor(Math.random() * (max - min)) + min; 5 | } 6 | 7 | export const explorationRegions = [ 8 | { 9 | id: 'forest', 10 | name: '森林', 11 | description: '茂密的森林,蕴含丰富的木材和草药资源', 12 | difficulty: 1, 13 | amount: getRandomInt(1, 20), 14 | unlockRequirements: { survival: 1 }, 15 | resources: ['wood', 'herb', 'food'], 16 | dangers: ['predator', 'storm'], 17 | image: '🌲', 18 | explorationTime: 300, // 秒 19 | energyCost: 30, 20 | resourceCost: { food: 2, water: 2 } 21 | }, 22 | { 23 | id: 'hills', 24 | name: '丘陵', 25 | description: '崎岖的丘陵地带,可以找到石头和少量金属', 26 | difficulty: 2, 27 | amount: getRandomInt(1, 20), 28 | unlockRequirements: { survival: 2 }, 29 | resources: ['stone', 'metal'], 30 | dangers: ['rockslide', 'predator'], 31 | image: '⛰️', 32 | explorationTime: 600, 33 | energyCost: 40, 34 | resourceCost: { food: 3, water: 3 } 35 | }, 36 | { 37 | id: 'ruins', 38 | name: '废墟', 39 | description: '古老的废墟,可能藏有珍贵的科技碎片和遗物', 40 | difficulty: 3, 41 | amount: getRandomInt(1, 3), 42 | unlockRequirements: { survival: 3, combat: 2 }, 43 | resources: ['metal', 'parts', 'techFragment', 'ancientRelic'], 44 | dangers: ['rockslide', 'radiation', 'hostiles'], 45 | image: '🏚️', 46 | explorationTime: 1200, 47 | energyCost: 50, 48 | resourceCost: { food: 5, water: 5, medicine: 1 } 49 | }, 50 | { 51 | id: 'cave', 52 | name: '洞穴', 53 | description: '黑暗的洞穴系统,蕴含丰富的矿物资源', 54 | difficulty: 4, 55 | amount: getRandomInt(1, 10), 56 | unlockRequirements: { survival: 4, combat: 3 }, 57 | resources: ['stone', 'metal', 'crystal'], 58 | dangers: ['rockslide', 'thirst', 'creatures'], 59 | image: '🕳️', 60 | explorationTime: 1800, 61 | energyCost: 60, 62 | resourceCost: { food: 6, water: 6, medicine: 2, tools: 1 } 63 | }, 64 | { 65 | id: 'wasteland', 66 | name: '荒漠', 67 | description: '危险的辐射区域,但可能有高级科技残骸', 68 | difficulty: 5, 69 | amount: getRandomInt(1, 10), 70 | unlockRequirements: { survival: 5, combat: 4 }, 71 | resources: ['metal', 'parts', 'techFragment', 'ancientRelic'], 72 | dangers: ['radiation', 'storm', 'hostiles', 'thirst'], 73 | image: '🏜️', 74 | explorationTime: 2400, 75 | energyCost: 70, 76 | resourceCost: { food: 8, water: 10, medicine: 3, tools: 2 } 77 | } 78 | ] -------------------------------------------------------------------------------- /src/plugins/merchants.js: -------------------------------------------------------------------------------- 1 | export const merchants = [ 2 | { 3 | id: 'wandering_trader', 4 | name: '流浪商人', 5 | icon: '🧙‍♂️', 6 | description: '定期出现的神秘商人,提供各种稀有资源', 7 | greeting: '你好,旅行者!我有一些稀有物品,你可能会感兴趣...', 8 | availability: { 9 | minDay: 5, 10 | frequency: 7, // 每7天出现一次 11 | duration: 1, // 持续1天 12 | }, 13 | sellItems: [ 14 | { id: 'rare_herb', name: '稀有草药', resourceId: 'rare_herb', buyPrice: { food: 10, water: 10, herb: 10 }, stock: 5, icon: '🌿', amount: 3 }, 15 | { id: 'advanced_parts', name: '高级零件', resourceId: 'advanced_parts', buyPrice: { parts: 10, tools: 5, metal: 8, wood: 15 }, stock: 2, icon: '🔧', amount: 1 }, 16 | { id: 'ancientRelic', name: '古代遗物', resourceId: 'ancientRelic', buyPrice: { crystal: 1 }, stock: 1, icon: '🏺', amount: 1 } 17 | ], 18 | buyItems: [ 19 | { id: 'sell_food', name: '食物', resourceId: 'food', sellPrice: { water: 1 }, icon: '🍖' }, 20 | { id: 'sell_water', name: '水', resourceId: 'water', sellPrice: { food: 1 }, icon: '💧' } 21 | ], 22 | specialTrades: [ 23 | { 24 | id: 'knowledge_exchange', 25 | name: '知识交换', 26 | description: '用你的资源换取宝贵的研究知识', 27 | inputs: { ancientRelic: 1, crystal: 1, techFragment: 2 }, 28 | outputs: { exp: 50 } 29 | } 30 | ] 31 | }, 32 | { 33 | id: 'settlement_trader', 34 | name: '定居点商人', 35 | icon: '👨‍🌾', 36 | description: '来自附近定居点的友好商人,提供基础资源交易', 37 | greeting: '欢迎!我们定居点有很多物资可以交换。', 38 | availability: { 39 | minDay: 10, 40 | frequency: 5, // 每5天出现一次 41 | duration: 2, // 持续2天 42 | }, 43 | sellItems: [ 44 | { id: 'bulk_food', name: '大量食物', resourceId: 'food', buyPrice: { wood: 15, stone: 10 }, stock: 30, icon: '🍗', amount: 20 }, 45 | { id: 'bulk_water', name: '大量水', resourceId: 'water', buyPrice: { wood: 15, stone: 10 }, stock: 30, icon: '🚰', amount: 20 }, 46 | { id: 'medicine_pack', name: '药品', resourceId: 'medicine', buyPrice: { food: 15, herb: 5 }, stock: 5, icon: '💊' } 47 | ], 48 | buyItems: [ 49 | { id: 'sell_wood', name: '木材', resourceId: 'wood', sellPrice: { food: 1 }, icon: '🌲' }, 50 | { id: 'sell_stone', name: '石头', resourceId: 'stone', sellPrice: { food: 1 }, icon: '🗿' }, 51 | { id: 'sell_metal', name: '金属', resourceId: 'metal', sellPrice: { food: 3 }, icon: '⚙️' } 52 | ], 53 | specialTrades: [ 54 | { 55 | id: 'community_support', 56 | name: '社区支持', 57 | description: '为定居点提供资源,获得他们的支持', 58 | inputs: { crystal: 1, food: 20, water: 20, medicine: 2 }, 59 | outputs: { maxHealth: 5, maxEnergy: 5 } 60 | } 61 | ] 62 | }, 63 | { 64 | id: 'mysterious_stranger', 65 | name: '精灵', 66 | icon: '🧚', 67 | description: '罕见的精灵,提供独特而危险的交易', 68 | greeting: '嘘...我有些特别的东西,但代价可能很高...', 69 | availability: { 70 | minDay: 20, 71 | frequency: 15, // 每15天出现一次 72 | duration: 1, // 持续1天 73 | }, 74 | sellItems: [ 75 | { id: 'advanced_tech', name: '科技碎片', resourceId: 'techFragment', buyPrice: { crystal: 1, ancientRelic: 2 }, stock: 3, icon: '💾', amount: 2 }, 76 | { id: 'rare_material', name: '水晶', resourceId: 'crystal', buyPrice: { metal: 15, tools: 2 }, stock: 3, icon: '💎', amount: 1 } 77 | ], 78 | buyItems: [ 79 | { id: 'sell_tech', name: '科技碎片', resourceId: 'techFragment', sellPrice: { food: 25, water: 25 }, icon: '💾' }, 80 | { id: 'sell_parts', name: '零件', resourceId: 'parts', sellPrice: { food: 15, metal: 5 }, icon: '⚙️' } 81 | ], 82 | specialTrades: [ 83 | { 84 | id: 'risky_experiment', 85 | name: '危险实验', 86 | description: '参与一项危险的实验,可能获得巨大收益或损失', 87 | inputs: { fuel: 10, medicine: 20, ancientRelic: 10, crystal: 10 }, 88 | outputs: { exp: 1000 } 89 | } 90 | ] 91 | }, 92 | { 93 | id: 'vampire_stranger', 94 | name: '吸血鬼', 95 | icon: '🧛', 96 | description: '罕见的吸血鬼,顾名思义', 97 | greeting: '虽然价格高但是值得...', 98 | availability: { 99 | minDay: 30, 100 | frequency: 30, // 每15天出现一次 101 | duration: 1, // 持续1天 102 | }, 103 | sellItems: [ 104 | { id: 'advanced_tech', name: '科技碎片', resourceId: 'techFragment', buyPrice: { ancientRelic: 4 }, stock: 3, icon: '💾', amount: 2 }, 105 | { id: 'rare_material', name: '水晶', resourceId: 'crystal', buyPrice: { techFragment: 4 }, stock: 3, icon: '💎', amount: 2 }, 106 | { id: 'rare_ancientRelic', name: '古代遗物', resourceId: 'ancientRelic', buyPrice: { crystal: 4 }, stock: 3, icon: '🏺', amount: 2 } 107 | ], 108 | buyItems: [], 109 | specialTrades: [] 110 | } 111 | ] -------------------------------------------------------------------------------- /src/plugins/recipes.js: -------------------------------------------------------------------------------- 1 | export const recipes = [ 2 | // 基础采集配方 3 | { 4 | id: 'gather_food', 5 | name: '采集食物', 6 | inputs: { energy: 10 }, 7 | outputs: { food: [5, 20] }, // [最小值, 最大值] 8 | duration: 60, // 秒 9 | skillRequired: { gathering: 1 }, 10 | category: 'gathering' 11 | }, 12 | { 13 | id: 'gather_water', 14 | name: '收集水', 15 | inputs: { energy: 10 }, 16 | outputs: { water: [5, 20] }, 17 | duration: 60, 18 | skillRequired: { gathering: 1 }, 19 | category: 'gathering' 20 | }, 21 | { 22 | id: 'gather_wood', 23 | name: '收集木材', 24 | inputs: { food: 5, water: 5, energy: 15 }, 25 | outputs: { wood: [5, 10] }, 26 | duration: 90, 27 | skillRequired: { gathering: 1 }, 28 | category: 'gathering' 29 | }, 30 | { 31 | id: 'gather_stone', 32 | name: '收集石头', 33 | inputs: { food: 5, water: 5, energy: 20 }, 34 | outputs: { stone: [5, 10] }, 35 | duration: 120, 36 | skillRequired: { gathering: 1 }, 37 | category: 'gathering' 38 | }, 39 | { 40 | id: 'gather_herb', 41 | name: '采集草药', 42 | inputs: { food: 5, water: 5, energy: 15 }, 43 | outputs: { herb: [5, 10] }, 44 | duration: 90, 45 | skillRequired: { gathering: 2 }, 46 | category: 'gathering' 47 | }, 48 | { 49 | id: 'gather_search_metal', 50 | name: '寻找金属', 51 | inputs: { food: 5, water: 5, energy: 25 }, 52 | outputs: { metal: [1, 10] }, 53 | duration: 150, 54 | skillRequired: { gathering: 3 }, 55 | category: 'gathering' 56 | }, 57 | { 58 | id: 'gather_rare_herb', 59 | name: '采集稀有草药', 60 | inputs: { food: 10, water: 10, energy: 30 }, 61 | outputs: { rare_herb: [1, 3] }, 62 | duration: 300, 63 | skillRequired: { gathering: 4 }, 64 | category: 'gathering' 65 | }, 66 | // 基础制作配方 67 | { 68 | id: 'craft_simple_tool', 69 | name: '制作简易工具', 70 | inputs: { energy: 15, wood: 5, stone: 3, metal: 2 }, 71 | outputs: { tools: 1 }, 72 | duration: 120, 73 | skillRequired: { crafting: 1 }, 74 | techRequired: 'basic_crafting', 75 | category: 'crafting' 76 | }, 77 | { 78 | id: 'craft_medicine', 79 | name: '制作药品', 80 | inputs: { energy: 15, herb: 5, water: 3, rare_herb: 2 }, 81 | outputs: { medicine: 1 }, 82 | duration: 180, 83 | skillRequired: { crafting: 2 }, 84 | techRequired: 'medicine_brewing', 85 | category: 'crafting' 86 | }, 87 | { 88 | id: 'craft_fuel', 89 | name: '制作燃料', 90 | inputs: { energy: 10, wood: 8, water: 10 }, 91 | outputs: { fuel: 2 }, 92 | duration: 150, 93 | skillRequired: { crafting: 2 }, 94 | category: 'crafting' 95 | }, 96 | { 97 | id: 'craft_parts', 98 | name: '制作零件', 99 | inputs: { energy: 20, metal: 5, tools: 1 }, 100 | outputs: { parts: 2 }, 101 | duration: 240, 102 | skillRequired: { crafting: 3 }, 103 | techRequired: 'metallurgy', 104 | category: 'crafting' 105 | }, 106 | { 107 | id: 'craft_advanced_parts', 108 | name: '制作高级零件', 109 | inputs: { parts: 5, energy: 20, metal: 5, tools: 1 }, 110 | outputs: { advanced_parts: 1 }, 111 | duration: 500, 112 | skillRequired: { crafting: 3 }, 113 | techRequired: 'advanced_tools', 114 | category: 'crafting' 115 | }, 116 | { 117 | id: 'craft_electronic_components', 118 | name: '制作电子元件', 119 | inputs: { advanced_parts: 2, parts: 5, energy: 20, metal: 5, tools: 1 }, 120 | outputs: { electronic_components: 2 }, 121 | duration: 500, 122 | skillRequired: { crafting: 5 }, 123 | techRequired: 'advanced_tools', 124 | category: 'crafting' 125 | }, 126 | ] 127 | 128 | export const technologies = [ 129 | // 基础科技 130 | { 131 | id: 'basic_survival', 132 | name: '基础生存', 133 | description: '掌握基本的生存技能', 134 | researched: true, // 默认已解锁 135 | cost: {}, 136 | researchTime: 60, 137 | unlocks: ['basic_crafting', 'water_collection'] 138 | }, 139 | { 140 | id: 'basic_crafting', 141 | name: '基础制作', 142 | description: '学习简单工具的制作方法', 143 | researched: false, 144 | cost: { techFragment: 1 }, 145 | unlocks: ['advanced_crafting', 'tool_making'], 146 | researchTime: 60, 147 | requirements: ['basic_survival'] 148 | }, 149 | { 150 | id: 'water_collection', 151 | name: '集水技术', 152 | description: '更有效地收集和储存水资源', 153 | researched: false, 154 | cost: { techFragment: 1 }, 155 | unlocks: ['water_purification'], 156 | researchTime: 60, 157 | requirements: ['basic_survival'] 158 | }, 159 | // 进阶科技 160 | { 161 | id: 'advanced_crafting', 162 | name: '进阶制作', 163 | description: '学习复杂物品的制作方法', 164 | researched: false, 165 | cost: { techFragment: 2 }, 166 | unlocks: ['metallurgy'], 167 | researchTime: 600, 168 | requirements: ['basic_crafting'] 169 | }, 170 | { 171 | id: 'tool_making', 172 | name: '工具制作', 173 | description: '制作更高效的工具', 174 | researched: false, 175 | cost: { techFragment: 2, wood: 15, stone: 10 }, 176 | unlocks: ['advanced_tools'], 177 | researchTime: 600, 178 | requirements: ['basic_crafting'] 179 | }, 180 | { 181 | id: 'water_purification', 182 | name: '水净化', 183 | description: '净化水源,减少疾病风险', 184 | researched: false, 185 | cost: { techFragment: 2, herb: 5 }, 186 | unlocks: ['medicine_brewing'], 187 | researchTime: 600, 188 | requirements: ['water_collection'] 189 | } 190 | ] 191 | 192 | export const availableBuildings = [ 193 | { 194 | id: 'shelter', 195 | name: '简易庇护所', 196 | description: '提供基本的居住场所,增加体力恢复速度', 197 | levels: [ 198 | { 199 | level: 1, 200 | cost: { wood: 10, stone: 5 }, 201 | effects: { energyRecovery: 1 }, 202 | requirements: { survival: 1 }, 203 | buildTime: 600 204 | }, 205 | { 206 | level: 2, 207 | cost: { wood: 20, stone: 15, metal: 5 }, 208 | effects: { energyRecovery: 2 }, 209 | requirements: { survival: 2, crafting: 1 }, 210 | buildTime: 1200 211 | }, 212 | { 213 | level: 3, 214 | cost: { wood: 40, stone: 30, metal: 15, tools: 2 }, 215 | effects: { energyRecovery: 3, maxHealth: 10 }, 216 | requirements: { survival: 5, crafting: 10 }, 217 | buildTime: 1800 218 | }, 219 | { 220 | level: 4, 221 | cost: { crystal: 5, techFragment: 5, wood: 100, stone: 100, metal: 100, tools: 20 }, 222 | effects: { energyRecovery: 5, maxHealth: 50 }, 223 | requirements: { survival: 10, crafting: 10 }, 224 | buildTime: 2400 225 | }, 226 | { 227 | level: 5, 228 | cost: { crystal: 10, techFragment: 10, wood: 150, stone: 150, metal: 150, tools: 30 }, 229 | effects: { energyRecovery: 10, maxHealth: 100 }, 230 | requirements: { survival: 20, crafting: 20 }, 231 | buildTime: 3000 232 | } 233 | ] 234 | }, 235 | { 236 | id: 'storage', 237 | name: '储物区', 238 | description: '增加资源存储上限', 239 | levels: [ 240 | { 241 | level: 1, 242 | cost: { wood: 15, stone: 5 }, 243 | effects: { storageMultiplier: 1.2 }, 244 | requirements: { gathering: 1 }, 245 | buildTime: 600 246 | }, 247 | { 248 | level: 2, 249 | cost: { wood: 30, stone: 15, metal: 5 }, 250 | effects: { storageMultiplier: 1.5 }, 251 | requirements: { gathering: 2, crafting: 1 }, 252 | buildTime: 1200 253 | }, 254 | { 255 | level: 3, 256 | cost: { wood: 50, stone: 30, metal: 15, tools: 3 }, 257 | effects: { storageMultiplier: 2 }, 258 | requirements: { gathering: 3, crafting: 2 }, 259 | buildTime: 1800 260 | }, 261 | { 262 | level: 4, 263 | cost: { crystal: 5, techFragment: 5, wood: 100, stone: 100, metal: 100, tools: 20 }, 264 | effects: { storageMultiplier: 2.5 }, 265 | requirements: { gathering: 10, crafting: 10 }, 266 | buildTime: 2400 267 | }, 268 | { 269 | level: 5, 270 | cost: { crystal: 10, techFragment: 10, wood: 125, stone: 125, metal: 125, tools: 25 }, 271 | effects: { storageMultiplier: 3 }, 272 | requirements: { gathering: 20, crafting: 20 }, 273 | buildTime: 3000 274 | } 275 | ] 276 | }, 277 | { 278 | id: 'workshop', 279 | name: '工作坊', 280 | description: '提高制作效率,解锁更多制作配方', 281 | levels: [ 282 | { 283 | level: 1, 284 | cost: { wood: 20, stone: 10, metal: 5 }, 285 | effects: { craftingSpeed: 1.1 }, 286 | requirements: { crafting: 1 }, 287 | buildTime: 600 288 | }, 289 | { 290 | level: 2, 291 | cost: { wood: 35, stone: 20, metal: 15, tools: 2 }, 292 | effects: { craftingSpeed: 1.25 }, 293 | requirements: { crafting: 2 }, 294 | buildTime: 1200 295 | }, 296 | { 297 | level: 3, 298 | cost: { wood: 60, stone: 40, metal: 30, tools: 5, parts: 3 }, 299 | effects: { craftingSpeed: 1.5 }, 300 | requirements: { crafting: 3, research: 1 }, 301 | buildTime: 1800 302 | }, 303 | { 304 | level: 4, 305 | cost: { crystal: 5, techFragment: 5, wood: 150, stone: 100, metal: 100, tools: 20, parts: 20 }, 306 | effects: { craftingSpeed: 2 }, 307 | requirements: { crafting: 10, research: 10 }, 308 | buildTime: 2400 309 | }, 310 | { 311 | level: 5, 312 | cost: { crystal: 10, techFragment: 10, metal: 150, tools: 30 }, 313 | effects: { craftingSpeed: 3 }, 314 | requirements: { crafting: 20, research: 20 }, 315 | buildTime: 3000 316 | } 317 | ] 318 | }, 319 | { 320 | id: 'garden', 321 | name: '菜园', 322 | description: '提供稳定的食物来源', 323 | levels: [ 324 | { 325 | level: 1, 326 | cost: { crystal: 1, wood: 10, stone: 5, water: 10 }, 327 | effects: { foodPerDay: 1 }, 328 | requirements: { gathering: 2 }, 329 | buildTime: 600 330 | }, 331 | { 332 | level: 2, 333 | cost: { crystal: 3, wood: 20, stone: 10, water: 20, tools: 1 }, 334 | effects: { foodPerDay: 2 }, 335 | requirements: { gathering: 3 }, 336 | buildTime: 1200 337 | }, 338 | { 339 | level: 3, 340 | cost: { crystal: 5, wood: 40, stone: 20, water: 30, tools: 3 }, 341 | effects: { foodPerDay: 3 }, 342 | requirements: { gathering: 4 }, 343 | buildTime: 1800 344 | }, 345 | { 346 | level: 4, 347 | cost: { crystal: 10, techFragment: 5, wood: 100, stone: 100, water: 100, tools: 30 }, 348 | effects: { foodPerDay: 4 }, 349 | requirements: { gathering: 10 }, 350 | buildTime: 2400 351 | }, 352 | { 353 | level: 5, 354 | cost: { crystal: 20, techFragment: 10, wood: 150, stone: 100, water: 150, tools: 30 }, 355 | effects: { foodPerDay: 5 }, 356 | requirements: { gathering: 20 }, 357 | buildTime: 3000 358 | } 359 | ] 360 | }, 361 | { 362 | id: 'well', 363 | name: '水井', 364 | description: '提供稳定的水源', 365 | levels: [ 366 | { 367 | level: 1, 368 | cost: { crystal: 1, wood: 5, stone: 15 }, 369 | effects: { waterPerDay: 1 }, 370 | requirements: { survival: 2 }, 371 | buildTime: 600 372 | }, 373 | { 374 | level: 2, 375 | cost: { crystal: 3, wood: 10, stone: 30, tools: 1 }, 376 | effects: { waterPerDay: 2 }, 377 | requirements: { survival: 3 }, 378 | buildTime: 1200 379 | }, 380 | { 381 | level: 3, 382 | cost: { crystal: 5, wood: 20, stone: 50, metal: 10, tools: 2 }, 383 | effects: { waterPerDay: 3 }, 384 | requirements: { survival: 4 }, 385 | buildTime: 1800 386 | }, 387 | { 388 | level: 4, 389 | cost: { crystal: 10, techFragment: 5, wood: 100, stone: 100, metal: 100, tools: 30 }, 390 | effects: { waterPerDay: 4 }, 391 | requirements: { survival: 10 }, 392 | buildTime: 2400 393 | }, 394 | { 395 | level: 5, 396 | cost: { crystal: 20, techFragment: 10, wood: 150, stone: 150, metal: 100, tools: 30 }, 397 | effects: { waterPerDay: 5 }, 398 | requirements: { survival: 20 }, 399 | buildTime: 3000 400 | } 401 | ] 402 | }, 403 | { 404 | id: 'medicinalGarden', 405 | name: '药草园', 406 | description: '种植和培育草药', 407 | levels: [ 408 | { 409 | level: 1, 410 | cost: { wood: 15, water: 15, herb: 5 }, 411 | effects: { herbPerDay: 2 }, 412 | requirements: { gathering: 3 }, 413 | buildTime: 600 414 | }, 415 | { 416 | level: 2, 417 | cost: { wood: 25, water: 25, herb: 10, tools: 2 }, 418 | effects: { herbPerDay: 4, medicinePerDay: 1 }, 419 | requirements: { gathering: 4, research: 2 }, 420 | buildTime: 1200 421 | }, 422 | { 423 | level: 3, 424 | cost: { wood: 40, water: 40, herb: 20, tools: 4 }, 425 | effects: { herbPerDay: 7, medicinePerDay: 2 }, 426 | requirements: { gathering: 5, research: 3 }, 427 | buildTime: 1800 428 | }, 429 | { 430 | level: 4, 431 | cost: { crystal: 5, techFragment: 5, wood: 100, water: 100, herb: 90, tools: 30 }, 432 | effects: { herbPerDay: 10, medicinePerDay: 3 }, 433 | requirements: { gathering: 10, research: 10 }, 434 | buildTime: 2400 435 | }, 436 | { 437 | level: 5, 438 | cost: { crystal: 10, techFragment: 10, wood: 150, water: 150, herb: 90, tools: 30 }, 439 | effects: { herbPerDay: 13, medicinePerDay: 4 }, 440 | requirements: { gathering: 20, research: 20 }, 441 | buildTime: 3000 442 | } 443 | ] 444 | }, 445 | { 446 | id: 'forge', 447 | name: '锻造坊', 448 | description: '加工金属,制作工具和零件', 449 | levels: [ 450 | { 451 | level: 1, 452 | cost: { wood: 20, stone: 30, metal: 15 }, 453 | effects: { toolsPerDay: 1 }, 454 | requirements: { crafting: 3 }, 455 | buildTime: 600 456 | }, 457 | { 458 | level: 2, 459 | cost: { wood: 30, stone: 50, metal: 30, tools: 3 }, 460 | effects: { toolsPerDay: 2, partsPerDay: 1 }, 461 | requirements: { crafting: 4, research: 2 }, 462 | buildTime: 1200 463 | }, 464 | { 465 | level: 3, 466 | cost: { wood: 50, stone: 80, metal: 50, tools: 5, fuel: 10 }, 467 | effects: { toolsPerDay: 3, partsPerDay: 2 }, 468 | requirements: { crafting: 5, research: 3 }, 469 | buildTime: 1800 470 | }, 471 | { 472 | level: 4, 473 | cost: { crystal: 5, techFragment: 5, wood: 100, stone: 150, metal: 100, tools: 30, fuel: 60 }, 474 | effects: { toolsPerDay: 4, partsPerDay: 3 }, 475 | requirements: { crafting: 10, research: 10 }, 476 | buildTime: 2400 477 | }, 478 | { 479 | level: 5, 480 | cost: { crystal: 10, techFragment: 10, wood: 100, stone: 150, metal: 100, tools: 30, electronic_components: 30, fuel: 60 }, 481 | effects: { toolsPerDay: 5, partsPerDay: 4 }, 482 | requirements: { crafting: 20, research: 20 }, 483 | buildTime: 3000 484 | } 485 | ] 486 | }, 487 | { 488 | id: 'lumberMill', 489 | name: '伐木场', 490 | description: '专业化的木材生产设施,提高木材产量', 491 | levels: [ 492 | { 493 | level: 1, 494 | cost: { wood: 30, stone: 20, tools: 2 }, 495 | effects: { woodPerDay: 1 }, 496 | requirements: { gathering: 3, crafting: 2 }, 497 | buildTime: 1200 498 | }, 499 | { 500 | level: 2, 501 | cost: { wood: 50, stone: 30, metal: 10, tools: 4 }, 502 | effects: { woodPerDay: 3 }, 503 | requirements: { gathering: 4, crafting: 3 }, 504 | buildTime: 1800 505 | }, 506 | { 507 | level: 3, 508 | cost: { wood: 80, stone: 50, metal: 20, tools: 6, parts: 5 }, 509 | effects: { woodPerDay: 5 }, 510 | requirements: { gathering: 5, crafting: 4 }, 511 | buildTime: 2400 512 | }, 513 | { 514 | level: 4, 515 | cost: { crystal: 5, techFragment: 5, wood: 120, stone: 80, metal: 40, tools: 10, parts: 10 }, 516 | effects: { woodPerDay: 7 }, 517 | requirements: { gathering: 10, crafting: 10 }, 518 | buildTime: 3000 519 | }, 520 | { 521 | level: 5, 522 | cost: { crystal: 10, techFragment: 10, wood: 150, stone: 100, metal: 50, tools: 15, parts: 15 }, 523 | effects: { woodPerDay: 10 }, 524 | requirements: { gathering: 20, crafting: 20 }, 525 | buildTime: 3600 526 | } 527 | ] 528 | }, 529 | { 530 | id: 'mine', 531 | name: '采矿场', 532 | description: '专业化的矿石开采设施,提高矿石与金属产量', 533 | levels: [ 534 | { 535 | level: 1, 536 | cost: { wood: 20, stone: 30, tools: 3 }, 537 | effects: { stonePerDay: 1, metalPerDay: 1 }, 538 | requirements: { gathering: 4, crafting: 2 }, 539 | buildTime: 1500 540 | }, 541 | { 542 | level: 2, 543 | cost: { wood: 30, stone: 50, metal: 15, tools: 5 }, 544 | effects: { stonePerDay: 3, metalPerDay: 1 }, 545 | requirements: { gathering: 5, crafting: 3 }, 546 | buildTime: 2100 547 | }, 548 | { 549 | level: 3, 550 | cost: { wood: 50, stone: 80, metal: 25, tools: 8, parts: 5 }, 551 | effects: { stonePerDay: 5, metalPerDay: 2 }, 552 | requirements: { gathering: 6, crafting: 4 }, 553 | buildTime: 2700 554 | }, 555 | { 556 | level: 4, 557 | cost: { crystal: 5, techFragment: 5, wood: 100, stone: 120, metal: 50, tools: 12, parts: 10 }, 558 | effects: { stonePerDay: 7, metalPerDay: 2 }, 559 | requirements: { gathering: 10, crafting: 10 }, 560 | buildTime: 3300 561 | }, 562 | { 563 | level: 5, 564 | cost: { crystal: 10, techFragment: 10, wood: 120, stone: 150, metal: 80, tools: 15, parts: 15 }, 565 | effects: { stonePerDay: 10, metalPerDay: 5 }, 566 | requirements: { gathering: 20, crafting: 20 }, 567 | buildTime: 3900 568 | } 569 | ] 570 | } 571 | ] 572 | -------------------------------------------------------------------------------- /src/plugins/resource.js: -------------------------------------------------------------------------------- 1 | export const resourceLimits = { 2 | food: 50, 3 | water: 50, 4 | wood: 50, 5 | stone: 50, 6 | metal: 50, 7 | herb: 30, 8 | rare_herb: 30, 9 | medicine: 20, 10 | tools: 10, 11 | parts: 10, 12 | advanced_parts: 10, 13 | electronic_components: 10, 14 | crystal: 10, 15 | fuel: 20, 16 | ancientRelic: 5, 17 | techFragment: 5, 18 | } 19 | 20 | export const resources = { 21 | food: 50, 22 | water: 50, 23 | wood: 0, 24 | stone: 0, 25 | metal: 0, 26 | herb: 0, 27 | rare_herb: 0, 28 | // 高级资源 29 | medicine: 1, 30 | tools: 0, 31 | parts: 0, 32 | advanced_parts: 0, 33 | electronic_components: 0, 34 | fuel: 0, 35 | // 特殊资源 36 | crystal: 0, 37 | ancientRelic: 0, 38 | techFragment: 0, 39 | } -------------------------------------------------------------------------------- /src/plugins/skillTree.js: -------------------------------------------------------------------------------- 1 | export const skillTree = { 2 | // 采集技能 3 | gathering: { 4 | name: '采集', 5 | icon: '🌿', 6 | description: '提高资源采集效率和发现稀有资源的几率', 7 | skills: [ 8 | { 9 | id: 'efficient_gathering', 10 | name: '高效采集', 11 | description: '提高基础资源采集效率15%', 12 | level: 1, 13 | maxLevel: 3, 14 | effects: { gatheringEfficiency: 0.15 }, 15 | cost: { exp: 200 }, 16 | requires: null, 17 | duration: 600 18 | }, 19 | { 20 | id: 'conservation', 21 | name: '资源保存', 22 | description: '采集活动消耗的体力减少10%', 23 | level: 0, 24 | maxLevel: 2, 25 | effects: { gatheringEnergyCost: -0.1 }, 26 | cost: { exp: 400 }, 27 | requires: { gathering: 3, skills: { efficient_gathering: 3 } }, 28 | duration: 1200 29 | }, 30 | { 31 | id: 'rare_herb_finding', 32 | name: '稀有草药寻觅', 33 | description: '采集草药时有15%几率额外获得稀有草药', 34 | level: 0, 35 | maxLevel: 2, 36 | effects: { rareHerbChance: 0.15 }, 37 | cost: { exp: 500 }, 38 | requires: { gathering: 4, skills: { conservation: 2 } }, 39 | duration: 1800 40 | }, 41 | { 42 | id: 'master_gatherer', 43 | name: '采集大师', 44 | description: '所有采集活动产出增加25%', 45 | level: 0, 46 | maxLevel: 1, 47 | effects: { gatheringYield: 0.25 }, 48 | cost: { exp: 1000 }, 49 | requires: { gathering: 5, skills: { efficient_gathering: 3, conservation: 2, rare_herb_finding: 2 } }, 50 | duration: 2400 51 | } 52 | ] 53 | }, 54 | // 制作技能 55 | crafting: { 56 | name: '制作', 57 | icon: '🔨', 58 | description: '提高物品制作效率和质量', 59 | skills: [ 60 | { 61 | id: 'efficient_crafting', 62 | name: '高效制作', 63 | description: '制作物品时间减少15%', 64 | level: 0, 65 | maxLevel: 3, 66 | effects: { craftingSpeed: 0.15 }, 67 | cost: { exp: 200 }, 68 | requires: null, 69 | duration: 600 70 | }, 71 | { 72 | id: 'resource_saving', 73 | name: '资源节约', 74 | description: '制作物品时有10%几率不消耗部分材料', 75 | level: 0, 76 | maxLevel: 3, 77 | effects: { resourceSaving: 0.1 }, 78 | cost: { exp: 300 }, 79 | requires: { crafting: 2, skills: { efficient_crafting: 3 } }, 80 | duration: 1200 81 | }, 82 | { 83 | id: 'quality_crafting', 84 | name: '精良制作', 85 | description: '制作物品时有15%几率获得额外产出', 86 | level: 0, 87 | maxLevel: 2, 88 | effects: { extraCraftingOutput: 0.15 }, 89 | cost: { exp: 450 }, 90 | requires: { crafting: 3, skills: { efficient_crafting: 3, resource_saving: 3 } }, 91 | duration: 1800 92 | }, 93 | { 94 | id: 'tool_specialist', 95 | name: '工具专家', 96 | description: '制作工具时耐久度增加20%', 97 | level: 0, 98 | maxLevel: 2, 99 | effects: { toolDurability: 0.2 }, 100 | cost: { exp: 500 }, 101 | requires: { crafting: 4, skills: { efficient_crafting: 3, resource_saving: 3, quality_crafting: 2 } }, 102 | duration: 2400 103 | }, 104 | { 105 | id: 'master_craftsman', 106 | name: '制作大师', 107 | description: '解锁高级制作配方,制作物品质量大幅提升', 108 | level: 0, 109 | maxLevel: 1, 110 | effects: { unlockAdvancedRecipes: true, craftingQuality: 0.3 }, 111 | cost: { exp: 1000 }, 112 | requires: { crafting: 5, skills: { efficient_crafting: 3, resource_saving: 3, quality_crafting: 2, tool_specialist: 2 } }, 113 | duration: 3000 114 | } 115 | ] 116 | }, 117 | // 生存技能 118 | survival: { 119 | name: '生存', 120 | icon: '🏕️', 121 | description: '提高生存能力和资源管理', 122 | skills: [ 123 | { 124 | id: 'efficient_metabolism', 125 | name: '高效代谢', 126 | description: '食物和水的消耗速度减少10%', 127 | level: 0, 128 | maxLevel: 3, 129 | effects: { foodConsumption: -0.1, waterConsumption: -0.1 }, 130 | cost: { exp: 200 }, 131 | requires: null, 132 | duration: 600 133 | }, 134 | { 135 | id: 'weather_adaptation', 136 | name: '气候适应', 137 | description: '恶劣天气对你的影响减少15%', 138 | level: 0, 139 | maxLevel: 2, 140 | effects: { weatherResistance: 0.15 }, 141 | cost: { exp: 300 }, 142 | requires: { survival: 2, skills: { efficient_metabolism: 3 } }, 143 | duration: 1200 144 | }, 145 | { 146 | id: 'energy_conservation', 147 | name: '体力保存', 148 | description: '所有活动的体力消耗减少10%', 149 | level: 0, 150 | maxLevel: 2, 151 | effects: { energyConsumption: -0.1 }, 152 | cost: { exp: 400 }, 153 | requires: { survival: 3, skills: { efficient_metabolism: 3, weather_adaptation: 2 } }, 154 | duration: 1800 155 | }, 156 | { 157 | id: 'natural_healing', 158 | name: '自然恢复', 159 | description: '健康的自然恢复速度提高20%', 160 | level: 0, 161 | maxLevel: 2, 162 | effects: { healthRecovery: 0.2 }, 163 | cost: { exp: 500 }, 164 | requires: { survival: 4, skills: { efficient_metabolism: 3, weather_adaptation: 2, energy_conservation: 2 } }, 165 | duration: 2400 166 | }, 167 | { 168 | id: 'survival_expert', 169 | name: '生存专家', 170 | description: '最大健康和增加15%,所有生存属性提升', 171 | level: 0, 172 | maxLevel: 1, 173 | effects: { maxHealth: 0.15, allSurvivalStats: 0.1 }, 174 | cost: { exp: 1000 }, 175 | requires: { survival: 5, skills: { efficient_metabolism: 3, weather_adaptation: 2, energy_conservation: 2, natural_healing: 2 } }, 176 | duration: 3000 177 | } 178 | ] 179 | }, 180 | // 研究技能 181 | research: { 182 | name: '研究', 183 | icon: '🔬', 184 | description: '提高科技研究效率和解锁特殊能力', 185 | skills: [ 186 | { 187 | id: 'quick_learning', 188 | name: '快速学习', 189 | description: '研究科技所需时间减少15%', 190 | level: 0, 191 | maxLevel: 3, 192 | effects: { researchSpeed: 0.15 }, 193 | cost: { exp: 200 }, 194 | requires: null, 195 | duration: 600 196 | }, 197 | { 198 | id: 'resource_recycling', 199 | name: '资源回收', 200 | description: '研究科技时有15%几率不消耗部分材料', 201 | level: 0, 202 | maxLevel: 2, 203 | effects: { researchResourceSaving: 0.15 }, 204 | cost: { exp: 450 }, 205 | requires: { research: 3, skills: { quick_learning: 3 } }, 206 | duration: 1200 207 | }, 208 | { 209 | id: 'advanced_theory', 210 | name: '高级理论', 211 | description: '解锁高级科技研究路径', 212 | level: 0, 213 | maxLevel: 1, 214 | effects: { unlockAdvancedTech: true }, 215 | cost: { exp: 600 }, 216 | requires: { research: 4, skills: { quick_learning: 3, resource_recycling: 2 } }, 217 | duration: 1800 218 | }, 219 | { 220 | id: 'scientific_genius', 221 | name: '科学天才', 222 | description: '所有研究活动效率提高25%,有几率发现突破性科技', 223 | level: 0, 224 | maxLevel: 1, 225 | effects: { allResearchBonus: 0.25, breakthroughChance: 0.1 }, 226 | cost: { exp: 1000 }, 227 | requires: { research: 5, skills: { quick_learning: 3, resource_recycling: 2, advanced_theory: 1 } }, 228 | duration: 2400 229 | } 230 | ] 231 | } 232 | } 233 | 234 | export const skills = { 235 | // 采集 236 | gathering: { 237 | name: 'gathering', 238 | level: 1, 239 | exp: 0, 240 | expToNextLevel: 100 241 | }, 242 | // 制作 243 | crafting: { 244 | name: 'crafting', 245 | level: 1, 246 | exp: 0, 247 | expToNextLevel: 100 248 | }, 249 | // 战斗 250 | combat: { 251 | name: 'combat', 252 | level: 1, 253 | exp: 0, 254 | expToNextLevel: 100 255 | }, 256 | // 生存 257 | survival: { 258 | name: 'survival', 259 | level: 1, 260 | exp: 0, 261 | expToNextLevel: 100 262 | }, 263 | // 研究 264 | research: { 265 | name: 'research', 266 | level: 1, 267 | exp: 0, 268 | expToNextLevel: 100 269 | }, 270 | } -------------------------------------------------------------------------------- /src/plugins/weatherTypes.js: -------------------------------------------------------------------------------- 1 | export const weatherTypes = { 2 | // 基础天气 3 | clear: { 4 | name: '晴朗', 5 | icon: '☀️', 6 | description: '天气晴朗,阳光明媚', 7 | color: '#f9d71c', 8 | probability: 0.25, 9 | duration: { min: 4, max: 12 }, 10 | animation: 'weather-clear', 11 | effects: { 12 | gatheringEfficiency: 1.1, 13 | energyConsumption: 1.0, 14 | waterConsumption: 1.1, 15 | foodConsumption: 1.0, 16 | explorationEfficiency: 1.1 17 | }, 18 | seasonModifiers: { 19 | spring: 1.0, 20 | summer: 1.5, 21 | autumn: 1.0, 22 | winter: 0.5, 23 | }, 24 | }, 25 | cloudy: { 26 | name: '多云', 27 | icon: '☁️', 28 | animation: 'weather-cloudy', 29 | description: '天空被云层覆盖,阳光被遮挡', 30 | color: '#b5b5b5', 31 | probability: 0.2, 32 | duration: { min: 3, max: 10 }, 33 | effects: { 34 | gatheringEfficiency: 1.0, 35 | energyConsumption: 1.0, 36 | waterConsumption: 0.9, 37 | foodConsumption: 1.0, 38 | explorationEfficiency: 1.0 39 | }, 40 | seasonModifiers: { 41 | spring: 1.2, 42 | summer: 1.0, 43 | autumn: 1.2, 44 | winter: 1.0, 45 | }, 46 | }, 47 | rainy: { 48 | name: '雨天', 49 | icon: '🌧️', 50 | description: '下着雨,地面湿滑,能见度降低', 51 | color: '#5d8aa8', 52 | probability: 0.15, 53 | animation: 'weather-rainy', 54 | duration: { min: 2, max: 8 }, 55 | effects: { 56 | gatheringEfficiency: 0.8, 57 | energyConsumption: 1.2, 58 | waterConsumption: 0.7, 59 | foodConsumption: 1.1, 60 | explorationEfficiency: 0.7 61 | }, 62 | seasonModifiers: { 63 | spring: 1.5, 64 | summer: 1.0, 65 | autumn: 1.2, 66 | winter: 0.3, 67 | }, 68 | }, 69 | // 扩展天气类型 70 | foggy: { 71 | name: '雾天', 72 | icon: '🌫️', 73 | description: '浓雾弥漫,能见度极低', 74 | color: '#d3d3d3', 75 | animation: 'weather-foggy', 76 | probability: 0.1, 77 | duration: { min: 2, max: 6 }, 78 | effects: { 79 | gatheringEfficiency: 0.7, 80 | energyConsumption: 1.1, 81 | waterConsumption: 1.0, 82 | foodConsumption: 1.0, 83 | explorationEfficiency: 0.5 84 | }, 85 | seasonModifiers: { 86 | spring: 1.2, 87 | summer: 0.5, 88 | autumn: 1.5, 89 | winter: 1.2, 90 | }, 91 | }, 92 | windy: { 93 | name: '大风', 94 | icon: '🌬️', 95 | description: '强风呼啸,行动受阻', 96 | color: '#a5a5a5', 97 | probability: 0.12, 98 | animation: 'weather-windy', 99 | duration: { min: 3, max: 7 }, 100 | effects: { 101 | gatheringEfficiency: 0.8, 102 | energyConsumption: 1.3, 103 | waterConsumption: 1.2, 104 | foodConsumption: 1.1, 105 | explorationEfficiency: 0.7 106 | }, 107 | seasonModifiers: { 108 | spring: 1.3, 109 | summer: 0.8, 110 | autumn: 1.5, 111 | winter: 1.0, 112 | }, 113 | }, 114 | stormy: { 115 | name: '暴风雨', 116 | icon: '⛈️', 117 | description: '雷电交加,暴雨倾盆', 118 | color: '#4682b4', 119 | probability: 0.08, 120 | animation: 'weather-heavy-rain', 121 | duration: { min: 1, max: 5 }, 122 | effects: { 123 | gatheringEfficiency: 0.5, 124 | energyConsumption: 1.5, 125 | waterConsumption: 0.5, 126 | foodConsumption: 1.2, 127 | explorationEfficiency: 0.3 128 | }, 129 | seasonModifiers: { 130 | spring: 1.0, 131 | summer: 1.5, 132 | autumn: 1.0, 133 | winter: 0.2, 134 | }, 135 | events: [ 136 | { 137 | id: 'lightning_strike', 138 | name: '雷击', 139 | probability: 0.05, 140 | effect: (store) => { 141 | // 随机损失一些健康 142 | const damage = Math.floor(Math.random() * 10) + 5 143 | store.player.health = Math.max(1, store.player.health - damage) 144 | store.addToEventLog( 145 | `暴风雨中你被雷电击中,损失了${damage}点健康!` 146 | ) 147 | }, 148 | }, 149 | ], 150 | }, 151 | heatwave: { 152 | name: '热浪', 153 | icon: '🔥', 154 | description: '酷热难耐,水分流失加快', 155 | color: '#ff7f50', 156 | probability: 0.07, 157 | animation: 'weather-hot', 158 | duration: { min: 2, max: 4 }, 159 | effects: { 160 | gatheringEfficiency: 0.7, 161 | energyConsumption: 1.4, 162 | waterConsumption: 1.8, 163 | foodConsumption: 1.1, 164 | explorationEfficiency: 0.6 165 | }, 166 | seasonModifiers: { 167 | spring: 0.2, 168 | summer: 2.0, 169 | autumn: 0.3, 170 | winter: 0.0, 171 | }, 172 | events: [ 173 | { 174 | id: 'dehydration', 175 | name: '脱水', 176 | probability: 0.1, 177 | effect: (store) => { 178 | // 如果水资源不足,会损失健康 179 | if (store.resources.water < 5) { 180 | const damage = Math.floor(Math.random() * 5) + 3 181 | store.player.health = Math.max(1, store.player.health - damage) 182 | store.addToEventLog( 183 | `热浪中你因缺水而脱水,损失了${damage}点健康!` 184 | ) 185 | } 186 | }, 187 | }, 188 | ], 189 | }, 190 | blizzard: { 191 | name: '暴风雪', 192 | icon: '❄️', 193 | description: '寒风凛冽,大雪纷飞', 194 | color: '#e0ffff', 195 | probability: 0.06, 196 | animation: 'weather-cold', 197 | duration: { min: 1, max: 3 }, 198 | effects: { 199 | gatheringEfficiency: 0.4, 200 | energyConsumption: 1.7, 201 | waterConsumption: 0.8, 202 | foodConsumption: 1.5, 203 | explorationEfficiency: 0.2 204 | }, 205 | seasonModifiers: { 206 | spring: 0.1, 207 | summer: 0.0, 208 | autumn: 0.2, 209 | winter: 2.0, 210 | }, 211 | events: [ 212 | { 213 | id: 'hypothermia', 214 | name: '低温症', 215 | probability: 0.15, 216 | effect: (store) => { 217 | // 如果没有足够的燃料,会损失健康 218 | if (store.resources.fuel < 3) { 219 | const healthDamage = Math.floor(Math.random() * 8) + 5 220 | store.player.health = Math.max(1, store.player.health - healthDamage) 221 | store.addToEventLog(`暴风雪中你因缺乏燃料而患上低温症,损失了${healthDamage}点健康!`) 222 | } 223 | }, 224 | }, 225 | ], 226 | }, 227 | sandstorm: { 228 | name: '沙尘暴', 229 | icon: '🏜️', 230 | description: '沙尘肆虐,呼吸困难', 231 | color: '#d2b48c', 232 | probability: 0.05, 233 | animation: 'weather-sandstorm', 234 | duration: { min: 1, max: 4 }, 235 | effects: { 236 | gatheringEfficiency: 0.3, 237 | energyConsumption: 1.6, 238 | waterConsumption: 1.5, 239 | foodConsumption: 1.2, 240 | explorationEfficiency: 0.3 241 | }, 242 | seasonModifiers: { 243 | spring: 0.5, 244 | summer: 1.5, 245 | autumn: 0.5, 246 | winter: 0.1, 247 | }, 248 | events: [ 249 | { 250 | id: 'lost_resources', 251 | name: '资源损失', 252 | probability: 0.2, 253 | effect: (store) => { 254 | // 随机损失一些资源 255 | const resources = ['food', 'water', 'wood', 'herb'] 256 | const randomResource = 257 | resources[Math.floor(Math.random() * resources.length)] 258 | const lossAmount = Math.floor(Math.random() * 5) + 3 259 | if (store.resources[randomResource] >= lossAmount) { 260 | store.resources[randomResource] -= lossAmount 261 | store.addToEventLog( 262 | `沙尘暴摧毁了你的一些${store.getResourceName( 263 | randomResource 264 | )},损失了${lossAmount}单位!` 265 | ) 266 | } 267 | }, 268 | }, 269 | ], 270 | }, 271 | auroral: { 272 | name: '极光', 273 | icon: '🌌', 274 | description: '天空中出现绚丽的极光', 275 | color: '#9370db', 276 | probability: 0.03, 277 | animation: 'weather-aurora', 278 | duration: { min: 3, max: 6 }, 279 | effects: { 280 | gatheringEfficiency: 1.0, 281 | energyConsumption: 0.9, 282 | waterConsumption: 1.0, 283 | foodConsumption: 0.9, 284 | explorationEfficiency: 1.2 285 | }, 286 | seasonModifiers: { 287 | spring: 0.2, 288 | summer: 0.1, 289 | autumn: 0.3, 290 | winter: 1.8, 291 | }, 292 | events: [ 293 | { 294 | id: 'inspiration', 295 | name: '灵感迸发', 296 | probability: 0.3, 297 | effect: (store) => { 298 | // 获得额外的经验 299 | const expGain = Math.floor(Math.random() * 15) + 10 300 | store.addExperience(expGain) 301 | store.addToEventLog(`极光的美景给你带来灵感,获得了${expGain}点幸存者经验!`) 302 | }, 303 | }, 304 | ], 305 | }, 306 | rainbow: { 307 | name: '彩虹', 308 | icon: '🌈', 309 | description: '雨后天晴,天空中出现美丽的彩虹', 310 | color: '#ff69b4', 311 | probability: 0.04, 312 | animation: 'weather-rainbow', 313 | duration: { min: 1, max: 3 }, 314 | effects: { 315 | gatheringEfficiency: 1.2, 316 | energyConsumption: 0.8, 317 | waterConsumption: 0.9, 318 | foodConsumption: 0.9, 319 | explorationEfficiency: 1.3 320 | }, 321 | seasonModifiers: { 322 | spring: 1.5, 323 | summer: 1.0, 324 | autumn: 1.0, 325 | winter: 0.2, 326 | }, 327 | events: [ 328 | { 329 | id: 'lucky_find', 330 | name: '幸运发现', 331 | probability: 0.25, 332 | effect: (store) => { 333 | // 随机获得一些资源 334 | const resources = ['food', 'water', 'wood', 'stone', 'herb', 'metal'] 335 | const randomResource = 336 | resources[Math.floor(Math.random() * resources.length)] 337 | const gainAmount = Math.floor(Math.random() * 8) + 5 338 | store.addResource(randomResource, gainAmount) 339 | store.addToEventLog( 340 | `彩虹的祝福让你幸运地发现了${gainAmount}单位${store.getResourceName( 341 | randomResource 342 | )}!` 343 | ) 344 | }, 345 | }, 346 | ], 347 | }, 348 | } 349 | 350 | // 根据季节获取天气概率分布 351 | export const getWeatherProbabilities = (season) => { 352 | const probabilities = {} 353 | for (const [weatherType, data] of Object.entries(weatherTypes)) { 354 | // 基础概率 * 季节修正 355 | const seasonModifier = data.seasonModifiers 356 | ? data.seasonModifiers[season] || 1.0 357 | : 1.0 358 | probabilities[weatherType] = data.probability * seasonModifier 359 | } 360 | // 归一化概率总和为1 361 | const totalProbability = Object.values(probabilities).reduce( 362 | (sum, p) => sum + p, 363 | 0 364 | ) 365 | for (const weatherType in probabilities) { 366 | probabilities[weatherType] /= totalProbability 367 | } 368 | return probabilities 369 | } 370 | 371 | // 随机选择天气类型 372 | export const selectRandomWeather = (season, currentWeather = null) => { 373 | const probabilities = getWeatherProbabilities(season) 374 | // 如果提供了当前天气,稍微降低再次选择相同天气的概率 375 | if (currentWeather && probabilities[currentWeather]) { 376 | probabilities[currentWeather] *= 0.5 377 | // 重新归一化 378 | const totalProbability = Object.values(probabilities).reduce( 379 | (sum, p) => sum + p, 380 | 0 381 | ) 382 | for (const weatherType in probabilities) { 383 | probabilities[weatherType] /= totalProbability 384 | } 385 | } 386 | // 随机选择天气 387 | const random = Math.random() 388 | let cumulativeProbability = 0 389 | for (const [weatherType, probability] of Object.entries(probabilities)) { 390 | cumulativeProbability += probability 391 | if (random <= cumulativeProbability) { 392 | return weatherType 393 | } 394 | } 395 | // 默认返回晴朗天气 396 | return 'clear' 397 | } 398 | 399 | // 获取天气持续时间 400 | export const getWeatherDuration = (weatherType) => { 401 | const weather = weatherTypes[weatherType] 402 | if (!weather || !weather.duration) return 6 // 默认6小时 403 | const { min, max } = weather.duration 404 | return Math.floor(Math.random() * (max - min + 1)) + min 405 | } 406 | 407 | // 处理天气特殊事件 408 | export const processWeatherEvents = (store, weatherType) => { 409 | const weather = weatherTypes[weatherType] 410 | if (!weather || !weather.events) return 411 | for (const event of weather.events) { 412 | if (Math.random() <= event.probability) event.effect(store) 413 | } 414 | } 415 | -------------------------------------------------------------------------------- /src/stores/gameStore.js: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { omit } from 'lodash-es' 3 | import { encryptData, decryptData } from '../plugins/crypto' 4 | import { skillTree, skills } from '../plugins/skillTree' 5 | import { merchants } from '../plugins/merchants' 6 | import { resources, resourceLimits } from '../plugins/resource' 7 | 8 | export const useGameStore = defineStore('game', { 9 | state: () => ({ 10 | // 玩家基本信息 11 | player: { 12 | level: 1, 13 | exp: 0, 14 | expToNextLevel: 100, 15 | health: 100, 16 | maxHealth: 100, 17 | energy: 100, 18 | maxEnergy: 100, 19 | // 生存天数 20 | days: 0, 21 | // 探索次数 22 | explorationCount: 0, 23 | }, 24 | // 技能系统 25 | skillTreeEffects: { 26 | // 采集效果 27 | gatheringEfficiency: 0, 28 | gatheringEnergyCost: 0, 29 | rareHerbChance: 0, 30 | gatheringYield: 0, 31 | // 制作效果 32 | craftingSpeed: 0, 33 | resourceSaving: 0, 34 | extraCraftingOutput: 0, 35 | toolDurability: 0, 36 | craftingQuality: 0, 37 | unlockAdvancedRecipes: false, 38 | // 生存效果 39 | foodConsumption: 0, 40 | waterConsumption: 0, 41 | weatherResistance: 0, 42 | energyConsumption: 0, 43 | healthRecovery: 0, 44 | allSurvivalStats: 0, 45 | // 研究效果 46 | researchSpeed: 0, 47 | techFragmentYield: 0, 48 | researchResourceSaving: 0, 49 | unlockAdvancedTech: false, 50 | allResearchBonus: 0, 51 | breakthroughChance: 0, 52 | // 战斗效果 53 | damageBonus: 0, 54 | damageReduction: 0, 55 | criticalChance: 0, 56 | retreatEnergyCost: 0, 57 | allCombatStats: 0, 58 | unlockSpecialCombat: false 59 | }, 60 | // 已解锁的技能 61 | unlockedSkills: {}, 62 | // 季节系统 63 | season: { 64 | // 季节长度(天) 65 | seasonLength: 30, 66 | // 季节效果 67 | effects: { 68 | foodGrowthRate: 1.0, 69 | herbGrowthRate: 1.0, 70 | energyConsumption: 1.0, 71 | waterConsumption: 1.0 72 | } 73 | }, 74 | // 天气系统 75 | weather: { 76 | current: 'clear', // 当前天气类型 77 | duration: 6, // 持续时间(小时) 78 | nextChangeDay: 1, // 下次变化的天数 79 | nextChangeHour: 6, // 下次变化的小时 80 | effects: { 81 | gatheringEfficiency: 1.0, // 采集效率修正 82 | energyConsumption: 1.0, // 体力消耗修正 83 | waterConsumption: 1.0, // 水消耗修正 84 | foodConsumption: 1.0, // 食物消耗修正 85 | explorationEfficiency: 1.0 // 探索效率修正 86 | } 87 | }, 88 | // 今天是否已经触发了事件 89 | eventTriggered: false, 90 | // 基础资源 91 | resources, 92 | // 资源上限 93 | resourceLimits, 94 | // 技能等级 95 | newSkills: skills, 96 | // 已解锁的建筑 97 | buildings: [], 98 | // 当前进行中的活动 99 | currentActivities: [], 100 | // 等待中的活动队列 101 | pendingActivities: [], 102 | // 当前进行中的研究 103 | researchActivities: [], 104 | // 等待中的研究队列 105 | pendingResearchActivities: [], 106 | // 当前进行中的探索 107 | explorationActivities: [], 108 | // 等待中的探索队列 109 | pendingExplorationActivities: [], 110 | // 当前进行中的建筑 111 | buildingActivities: [], 112 | // 等待中的建筑队列 113 | pendingBuildingActivities: [], 114 | // 当前进行中的技能 115 | skillActivities: [], 116 | // 等待中的技能队列 117 | pendingSkillActivities: [], 118 | // 游戏时间 119 | gameTime: { 120 | day: 1, 121 | hour: 6, // 游戏从早上6点开始 122 | minute: 0, 123 | // 时间流逝速度,实际秒:游戏分钟 124 | timeScale: 1, // 1秒 = 1分钟游戏时间 125 | // 游戏开始的时间戳 126 | startTime: Date.now(), 127 | // 当前游戏时间戳 128 | get timestamp() { 129 | return Date.now() 130 | } 131 | }, 132 | // 已研究 133 | researched: [], 134 | recipes: [], 135 | // 游戏设置 136 | settings: { 137 | autoSave: true, 138 | darkMode: false, 139 | soundEnabled: true, 140 | notificationsEnabled: true, 141 | }, 142 | // 事件日志 143 | eventLog: [], 144 | // 成就系统 145 | achievements: { 146 | // 已解锁的成就ID列表 147 | unlocked: [], 148 | // 成就相关的计数器 149 | explorationCount: 0, 150 | extremeWeatherSurvived: false, 151 | healthyDays: 0, 152 | // 其他成就相关的状态 153 | resourcesCollected: { 154 | food: 0, 155 | water: 0, 156 | wood: 0, 157 | stone: 0, 158 | metal: 0, 159 | herb: 0 160 | } 161 | }, 162 | // 游戏状态 163 | gameState: 'playing', // playing, paused, gameover 164 | // 任务系统 165 | activeQuests: [], // 进行中的任务 166 | completedQuests: [] // 已完成的任务 167 | }), 168 | getters: { 169 | // 计算玩家总体实力 170 | playerPower: (state) => { 171 | return Object.values(state.skills).reduce((sum, level) => sum + level, 0) 172 | }, 173 | // 计算资源总量 174 | totalResources: (state) => { 175 | return Object.values(state.resources).reduce((sum, amount) => sum + amount, 0) 176 | }, 177 | // 计算当前时间字符串 178 | currentTimeString: (state) => { 179 | const { day, hour, minute } = state.gameTime 180 | return `第${day}天 ${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}` 181 | }, 182 | // 检查资源是否足够 183 | hasEnoughResources: (state) => (requirements) => { 184 | for (const [resource, amount] of Object.entries(requirements)) { 185 | if (state.resources[resource] < amount) return false 186 | } 187 | return true 188 | }, 189 | }, 190 | actions: { 191 | // 初始化游戏 192 | initGame() { 193 | // 重置游戏状态 194 | this.$reset() 195 | localStorage.removeItem(__APP_NAME__) 196 | this.saveGame() 197 | this.loadGame() 198 | this.addToEventLog('你醒来了,发现自己身处一片荒野...') 199 | }, 200 | // 保存游戏 201 | saveGame() { 202 | const filteredState = omit(this.$state, ['eventLog']) 203 | const encryptedData = encryptData(filteredState) 204 | if (encryptedData) { 205 | try { 206 | const encodedAppName = btoa(`+++${__APP_NAME__}`) 207 | localStorage.setItem(__APP_NAME__, `${encryptedData}${encodedAppName}`) 208 | this.addToEventLog('游戏数据已保存') 209 | } catch (error) { 210 | this.addToEventLog('数据保存失败:', error) 211 | } 212 | } else { 213 | this.addToEventLog('数据加密失败') 214 | } 215 | }, 216 | // 加载游戏 217 | loadGame() { 218 | const data = localStorage.getItem(__APP_NAME__) 219 | if (data) { 220 | const encodedAppName = btoa(`+++${__APP_NAME__}`) 221 | const saveData = data.replace(encodedAppName, '') 222 | if (saveData) { 223 | try { 224 | this.$state = decryptData(saveData) 225 | this.resetSkillEffects() 226 | this.initBuildingEffects() 227 | this.fixSkills() 228 | this.addToEventLog('游戏已加载') 229 | return true 230 | } catch (error) { 231 | this.addToEventLog('数据加载失败:', error) 232 | } 233 | } 234 | } 235 | return false 236 | }, 237 | // 初始化建筑资源上限效果 238 | initBuildingEffects() { 239 | // 遍历所有建筑应用永久效果 240 | for (const building of this.buildings) { 241 | if (!building.effects) continue 242 | // 应用存储上限效果 243 | if (building.effects.storageMultiplier) { 244 | for (const resource in resourceLimits) { 245 | this.resourceLimits[resource] = resourceLimits[resource] * building.effects.storageMultiplier 246 | if (this.resources[resource] > this.resourceLimits[resource]) { 247 | this.resources[resource] = this.resourceLimits[resource] 248 | } 249 | } 250 | } 251 | } 252 | }, 253 | // 修复技能问题 254 | fixSkills() { 255 | // 初始化修复技能问题 256 | const skillsArray = Object.values(this.newSkills) 257 | const fixedSkills = {} 258 | Object.keys(this.newSkills).forEach((key, index) => { 259 | const item = skillsArray[index] 260 | fixedSkills[key] = typeof item === 'string' ? Object.values(skills)[index] : item 261 | }) 262 | this.newSkills = fixedSkills 263 | }, 264 | // 重置错误的技能效果 265 | resetSkillEffects() { 266 | for (const skillId in this.skillTreeEffects) { 267 | if (typeof this.skillTreeEffects[skillId] === 'number') { 268 | const skillData = this.findSkillEffectById(skillId) 269 | if (skillData) { 270 | const { effects, maxLevel } = skillData 271 | for (const [effect, value] of Object.entries(effects)) { 272 | if (this.skillTreeEffects[value[0]] !== undefined) { 273 | if (typeof value[1] === 'number') { 274 | const targetValue = value[1] * maxLevel 275 | // 处理正效果(上限) 276 | if (value[1] > 0 && this.skillTreeEffects[value[0]] > targetValue) { 277 | this.skillTreeEffects[value[0]] = parseFloat(targetValue.toFixed(2)) 278 | } 279 | // 处理负效果(下限) 280 | else if (value[1] < 0 && this.skillTreeEffects[value[0]] < targetValue) { 281 | this.skillTreeEffects[value[0]] = parseFloat(targetValue.toFixed(2)) 282 | } 283 | } 284 | } 285 | } 286 | } 287 | } 288 | } 289 | }, 290 | findSkillEffectById(skillId) { 291 | for (const branch of Object.values(skillTree)) { 292 | for (const skill of branch.skills) { 293 | for (const [effect, value] of Object.entries(skill.effects)) { 294 | if (effect === skillId) { 295 | return { 296 | effects: Object.entries(skill.effects), // 获取键值对 297 | maxLevel: skill.maxLevel // 获取 maxLevel 298 | } 299 | } 300 | } 301 | } 302 | } 303 | return null // 如果未找到,返回 null 304 | }, 305 | // 添加资源 306 | addResource(resource, amount) { 307 | if (!this.resources.hasOwnProperty(resource)) return false 308 | // 确保不超过上限 309 | const newAmount = this.resources[resource] + amount 310 | this.resources[resource] = Math.min(newAmount, this.resourceLimits[resource]) 311 | return true 312 | }, 313 | // 消耗资源 314 | consumeResource(resource, amount) { 315 | if (!this.resources.hasOwnProperty(resource)) return false 316 | if (this.resources[resource] < amount) return false 317 | this.resources[resource] -= amount 318 | return true 319 | }, 320 | // 增加技能经验 321 | addSkillExp(skill, exp) { 322 | this.newSkills[skill].exp += exp 323 | this.addToEventLog(`你获得了${exp}点${this.getResourceName(skill)}技能经验`) 324 | if (this.newSkills[skill].exp >= this.newSkills[skill].expToNextLevel) { 325 | this.newSkills[skill].exp -= this.newSkills[skill].expToNextLevel 326 | this.newSkills[skill].level += 1 327 | // 增加下一级所需经验 328 | this.newSkills[skill].expToNextLevel = Math.floor(this.newSkills[skill].expToNextLevel * 1.5) 329 | this.addToEventLog(`${this.getResourceName(skill)}技能提升到${this.newSkills[skill].level}级!`) 330 | } 331 | this.saveGame() 332 | }, 333 | // 计算当前可用的商人 334 | availableMerchants() { 335 | const currentDay = this.gameTime.day 336 | return merchants.filter(merchant => { 337 | // 检查是否达到最小天数要求 338 | if (currentDay < merchant.availability.minDay) return false 339 | // 计算商人是否在当前日期出现 340 | const daysSinceMinDay = currentDay - merchant.availability.minDay 341 | const cyclePosition = daysSinceMinDay % merchant.availability.frequency 342 | return cyclePosition < merchant.availability.duration 343 | }) 344 | }, 345 | // 获取资源名称 346 | getResourceName(resourceKey) { 347 | const resourceNames = { 348 | exp: '幸存者经验', 349 | maxHealth: '最大健康', 350 | maxEnergy: '最大体力', 351 | health: '健康', 352 | energy: '体力', 353 | food: '食物', 354 | water: '水', 355 | wood: '木材', 356 | stone: '石头', 357 | metal: '金属', 358 | herb: '草药', 359 | medicine: '药品', 360 | tools: '工具', 361 | parts: '零件', 362 | fuel: '燃料', 363 | gathering: '采集', 364 | crafting: '制作', 365 | combat: '战斗', 366 | survival: '生存', 367 | research: '研究', 368 | predator: '野兽袭击', 369 | storm: '遭遇风暴', 370 | rockslide: '遭遇坍塌', 371 | radiation: '受到辐射', 372 | hostiles: '遭遇敌对人员', 373 | thirst: '消耗额外水资源', 374 | creatures: '遭遇奇怪的生物', 375 | ancientRelic: '古代遗物', 376 | techFragment: '科技碎片', 377 | advanced_parts: '高级零件', 378 | electronic_components: '电子元件', 379 | rare_herb: '稀有草药', 380 | crystal: '水晶', 381 | explorationCount: '探索次数', 382 | } 383 | return resourceNames[resourceKey] || resourceKey 384 | }, 385 | // 检查是否需要更新天气 386 | checkWeatherChange() { 387 | const currentDay = this.gameTime.day 388 | const currentHour = this.gameTime.hour 389 | // 生成天气 390 | if (currentDay > this.weather.nextChangeDay || 391 | (currentDay === this.weather.nextChangeDay && 392 | currentHour >= this.weather.nextChangeHour)) { 393 | 394 | // 获取当前季节 395 | const day = this.gameTime.day 396 | const seasonLength = 30 // 每个季节30天 397 | const seasonIndex = Math.floor((day - 1) % (seasonLength * 4) / seasonLength) 398 | const seasons = ['spring', 'summer', 'autumn', 'winter'] 399 | const currentSeason = seasons[seasonIndex] 400 | // 各季节天气概率 401 | const weatherProbabilities = { 402 | spring: { 403 | clear: 0.3, 404 | cloudy: 0.3, 405 | rainy: 0.25, 406 | foggy: 0.1, 407 | windy: 0.05 408 | }, 409 | summer: { 410 | clear: 0.4, 411 | cloudy: 0.2, 412 | rainy: 0.15, 413 | hot: 0.15, 414 | storm: 0.1 415 | }, 416 | autumn: { 417 | clear: 0.25, 418 | cloudy: 0.3, 419 | rainy: 0.2, 420 | foggy: 0.15, 421 | windy: 0.1 422 | }, 423 | winter: { 424 | clear: 0.2, 425 | cloudy: 0.2, 426 | cold: 0.3, 427 | snow: 0.2, 428 | windy: 0.1 429 | } 430 | } 431 | // 获取当前季节的天气概率 432 | const probabilities = weatherProbabilities[currentSeason] 433 | // 随机选择天气 434 | let random = Math.random() 435 | let cumulativeProbability = 0 436 | let selectedWeather = 'clear' // 默认晴天 437 | for (const [weather, probability] of Object.entries(probabilities)) { 438 | cumulativeProbability += probability 439 | if (random <= cumulativeProbability) { 440 | selectedWeather = weather 441 | break 442 | } 443 | } 444 | // 更新天气状态 445 | const oldWeather = this.weather.current 446 | this.weather.current = selectedWeather 447 | // 设置天气持续时间(4-8小时) 448 | this.weather.duration = 4 + Math.floor(Math.random() * 5) 449 | // 更新下次天气变化时间 450 | let nextHour = this.gameTime.hour + this.weather.duration 451 | let nextDay = this.gameTime.day 452 | while (nextHour >= 24) { 453 | nextHour -= 24 454 | nextDay += 1 455 | } 456 | this.weather.nextChangeDay = nextDay 457 | this.weather.nextChangeHour = nextHour 458 | const weatherEffects = { 459 | clear: '视野良好,采集效率+10%', 460 | cloudy: '温度适宜,体力消耗-5%', 461 | rainy: '水资源收集+20%,移动速度-10%', 462 | foggy: '视野受限,探索效率-20%', 463 | windy: '体力消耗+10%,有机会发现特殊资源', 464 | hot: '水分消耗+30%,体力恢复-20%', 465 | cold: '食物消耗+30%,体力恢复-20%', 466 | snow: '移动速度-30%,采集效率-20%', 467 | storm: '无法外出,有触发灾害风险', 468 | heavyRain: '水资源收集+50%,采集效率-30%,有触发洪水风险' 469 | } 470 | // 只有当天气变化时才记录日志 471 | if (oldWeather !== selectedWeather) this.addToEventLog(`天气变为${this.getWeatherName()},${weatherEffects[this.weather.current] || ''}`) 472 | // 重置天气效果 473 | this.weather.effects = { 474 | gatheringEfficiency: 1.0, 475 | energyConsumption: 1.0, 476 | waterConsumption: 1.0, 477 | foodConsumption: 1.0, 478 | explorationEfficiency: 1.0 479 | } 480 | } 481 | }, 482 | // 获取天气名称 483 | getWeatherName() { 484 | const weatherNames = { 485 | clear: '晴朗', 486 | cloudy: '多云', 487 | rainy: '小雨', 488 | foggy: '雾天', 489 | windy: '大风', 490 | hot: '酷热', 491 | cold: '寒冷', 492 | snow: '降雪', 493 | storm: '风暴', 494 | heavyRain: '暴雨' 495 | } 496 | return weatherNames[this.weather.current] || '未知' 497 | }, 498 | // 触发随机事件 499 | triggerRandomEvent() { 500 | // 基础事件 501 | const basicEvents = [ 502 | { 503 | id: 'rain', name: '下雨了', effect: () => { 504 | this.addResource('water', 10) 505 | this.addToEventLog('下雨了,你收集了一些雨水') 506 | }, 507 | weight: 10 // 权重,决定事件触发概率 508 | }, 509 | { 510 | id: 'animal', name: '野生动物', effect: () => { 511 | if (this.newSkills.combat > 2) { 512 | this.addResource('food', 15) 513 | this.addToEventLog('你成功猎到了一只野兔,获得了食物') 514 | } else { 515 | this.addToEventLog('你看到一只野兔,但它跑得太快了') 516 | } 517 | }, 518 | weight: 8 519 | }, 520 | { 521 | id: 'stranger', name: '陌生人', effect: () => { 522 | this.addToEventLog('你遇到了一个陌生人,他给了你一些建议就离开了') 523 | this.addSkillExp('survival', 20) 524 | }, 525 | weight: 6 526 | }, 527 | { 528 | id: 'wild_fruits', name: '野果丰收', effect: () => { 529 | this.addResource('food', 8) 530 | this.addToEventLog('你发现了一片野果丛,收获了不少食物') 531 | }, 532 | weight: 10 533 | }, 534 | { 535 | id: 'herb_discovery', name: '草药发现', effect: () => { 536 | this.addResource('herb', 5) 537 | this.addToEventLog('你发现了一片罕见的草药,这对制作药品很有帮助') 538 | }, 539 | weight: 7 540 | }, 541 | ] 542 | // 危险事件 543 | const dangerEvents = [ 544 | { 545 | id: 'storm', name: '暴风雨', effect: () => { 546 | // 检查是否有庇护所 547 | const hasShelter = this.buildings.some(b => b.id === 'shelter' && b.level >= 1) 548 | if (hasShelter) { 549 | this.addToEventLog('一场暴风雨来袭,但你的庇护所提供了良好的保护') 550 | this.player.health -= this.player.health * 0.05 // 仍有轻微影响 551 | } else { 552 | this.addToEventLog('一场暴风雨来袭,你被淋得浑身湿透,健康都受到了影响') 553 | this.player.health -= this.player.health * 0.1 554 | } 555 | }, 556 | weight: 5, 557 | minDay: 3 // 最早在第3天触发 558 | }, 559 | { 560 | id: 'illness', name: '疾病', effect: () => { 561 | if (this.resources.medicine > 0) { 562 | this.consumeResource('medicine', 1) 563 | this.addToEventLog('你感到身体不适,但幸好有药品治疗,很快就恢复了') 564 | } else { 565 | this.player.health -= this.player.health * 0.15 566 | this.player.energy -= this.player.energy * 0.2 567 | this.addToEventLog('你生病了,没有药品治疗,健康状况恶化') 568 | } 569 | }, 570 | weight: 4, 571 | minDay: 5 572 | }, 573 | { 574 | id: 'predator', name: '掠食者', effect: () => { 575 | if (this.newSkills.combat >= 3) { 576 | this.addToEventLog('一只野兽袭击了你,但你成功击退了它,还获得了一些食物') 577 | this.addResource('food', 20) 578 | this.addSkillExp('combat', 20) 579 | } else { 580 | this.player.health -= this.player.health * 0.2 581 | this.addToEventLog('一只野兽袭击了你,你勉强逃脱,但受了伤') 582 | } 583 | }, 584 | weight: 3, 585 | minDay: 7 586 | }, 587 | ] 588 | // 幸运事件 589 | const luckyEvents = [ 590 | { 591 | id: 'abandoned_supplies', name: '废弃物资', effect: () => { 592 | this.addResource('food', 10) 593 | this.addResource('water', 10) 594 | this.addResource('medicine', 1) 595 | this.addToEventLog('你发现了一些废弃的物资,获得了食物、水和药品') 596 | }, 597 | weight: 3, 598 | minDay: 4 599 | }, 600 | { 601 | id: 'tech_discovery', name: '科技发现', effect: () => { 602 | this.addResource('techFragment', 2) 603 | this.addToEventLog('你发现了一些古老的科技碎片,这对研究很有帮助') 604 | }, 605 | weight: 2, 606 | minDay: 10 607 | }, 608 | { 609 | id: 'ancient_cache', name: '古代宝藏', effect: () => { 610 | this.addResource('ancientRelic', 1) 611 | this.addResource('metal', 15) 612 | this.addResource('parts', 3) 613 | this.addToEventLog('你发现了一个古代文明的宝藏,获得了珍贵的资源') 614 | }, 615 | weight: 1, 616 | minDay: 15 617 | }, 618 | ] 619 | // 根据游戏天数选择可用事件 620 | let availableEvents = [...basicEvents] 621 | if (this.gameTime.day >= 3) availableEvents = availableEvents.concat(dangerEvents.filter(e => this.gameTime.day >= (e.minDay || 0))) 622 | if (this.gameTime.day >= 4) availableEvents = availableEvents.concat(luckyEvents.filter(e => this.gameTime.day >= (e.minDay || 0))) 623 | // 计算总权重 624 | const totalWeight = availableEvents.reduce((sum, event) => sum + (event.weight || 1), 0) 625 | // 25%概率触发随机事件 626 | if (Math.random() < 0.25) { 627 | // 根据权重随机选择事件 628 | let randomWeight = Math.random() * totalWeight 629 | let selectedEvent = null 630 | for (const event of availableEvents) { 631 | randomWeight -= (event.weight || 1) 632 | if (randomWeight <= 0) { 633 | selectedEvent = event 634 | break 635 | } 636 | } 637 | if (selectedEvent) selectedEvent.effect() 638 | } 639 | }, 640 | // 游戏结束 641 | gameOver() { 642 | this.gameState = 'gameover' 643 | this.saveGame() 644 | this.addToEventLog('你没能生存下来...') 645 | }, 646 | // 添加事件日志 647 | addToEventLog(message) { 648 | const timestamp = `${this.gameTime.day}天 ${this.gameTime.hour}:${this.gameTime.minute}` 649 | this.eventLog.unshift({ timestamp, message }) 650 | // 限制日志长度 651 | if (this.eventLog.length > 100) this.eventLog.pop() 652 | }, 653 | }, 654 | }) -------------------------------------------------------------------------------- /src/stores/index.js: -------------------------------------------------------------------------------- 1 | import { createPinia } from 'pinia' 2 | 3 | const pinia = createPinia() 4 | 5 | export default pinia -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import vue from '@vitejs/plugin-vue' 3 | import AutoImport from 'unplugin-auto-import/vite' 4 | import Components from 'unplugin-vue-components/vite' 5 | import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' 6 | import pkg from './package.json' 7 | import vitePluginBundleObfuscator from 'vite-plugin-bundle-obfuscator' 8 | 9 | export default defineConfig({ 10 | define: { 11 | __APP_NAME__: JSON.stringify(pkg.name), 12 | __APP_TITLE__: JSON.stringify(pkg.title), 13 | __APP_VERSION__: JSON.stringify(pkg.version), 14 | }, 15 | base: './', 16 | build: { 17 | outDir: 'docs', 18 | minify: 'terser', 19 | chunkSizeWarningLimit: 800, 20 | rollupOptions: { 21 | output: { 22 | manualChunks: (id) => { 23 | if (id.includes('node_modules')) return 'vendor' 24 | }, 25 | chunkFileNames: 'assets/js/[name]-[hash].js', 26 | entryFileNames: 'assets/js/[name]-[hash].js', 27 | assetFileNames: () => { 28 | return 'assets/[ext]/[name]-[hash].[ext]' 29 | } 30 | } 31 | }, 32 | terserOptions: { 33 | compress: { 34 | drop_console: false, 35 | drop_debugger: true 36 | } 37 | } 38 | }, 39 | plugins: [ 40 | vue(), 41 | AutoImport({ 42 | resolvers: [ElementPlusResolver()] 43 | }), 44 | Components({ 45 | resolvers: [ElementPlusResolver()] 46 | }), 47 | vitePluginBundleObfuscator({ 48 | log: false, 49 | enable: true, 50 | options: { 51 | log: false, 52 | compact: true, 53 | stringArray: true, 54 | renameGlobals: false, 55 | selfDefending: false, 56 | debugProtection: false, 57 | rotateStringArray: true, 58 | deadCodeInjection: false, 59 | stringArrayEncoding: ['none'], 60 | disableConsoleOutput: true, 61 | stringArrayThreshold: 0.75, 62 | controlFlowFlattening: false, 63 | unicodeEscapeSequence: true, 64 | identifierNamesGenerator: 'hexadecimal' 65 | }, 66 | autoExcludeNodeModules: true 67 | }) 68 | ], 69 | worker: { 70 | format: 'es' 71 | } 72 | }) 73 | --------------------------------------------------------------------------------