Compare commits

...

425 Commits

Author SHA1 Message Date
wy
17b58c7924 优化起飞功能错误处理,取消网络拦截,避免官方功能被影响,更新版本至1.2.4 2025-04-07 16:03:01 +08:00
wy
4ae5ba1e46 Fix 2025-03-11 14:54:00 +08:00
d3b85ec361 快捷动作【REFILL】修复 2024-04-07 08:32:07 +08:00
6234424aa6 快捷动作【REFILL】修复 2024-04-03 09:33:54 +08:00
2285b3f41e v1.2.0 2024-03-29 09:56:49 +08:00
92173c57ec - BS估算缓存机制修复
- 快捷功能【快速犯罪】界面优化
2024-03-29 09:44:06 +08:00
2eb1fbf087 ### 添加
- 引入了BS估算功能

### 修改

- 快捷功能【快速犯罪】去除了烦人的通知
2024-03-27 16:54:55 +08:00
4d92efa48b 优化task逻辑 2024-03-21 15:22:19 +08:00
f66b165eb7 readme修正 2024-03-20 17:13:46 +08:00
5d42062001 ### 修改
- 快捷功能的【喝啤酒】移动至【快速犯罪】中
- profile页面中在线状态调整
2024-03-20 17:09:12 +08:00
234022c80c ### 添加
- 快捷功能-PI存钱

### 修改

- 上次动作的url判断修复
- profile页面中添加了更明显的上次动作时间
- 快速取钱功能添加了常用输入
2024-03-15 16:06:23 +08:00
5ec20fa327 更新 2024-01-08 11:11:09 +08:00
773332f406 快速犯罪中添加自定义选项 2024-01-05 17:44:43 +08:00
46a1339d5c 圣诞小镇掉落物记录表格中的undefined错误修复 2023-12-22 16:16:40 +08:00
ab0a1f2fdd Merge remote-tracking branch 'gitlab/dev' into dev 2023-12-08 14:50:22 +08:00
4121fd9ed0 更新 2023-12-08 14:49:35 +08:00
1c04624903 Update 2 files
- /README_ZHCN.md
- /README.md
2023-11-29 13:42:08 +00:00
64c906f064 更新 2023-11-29 17:55:36 +08:00
53756f53a7 更新 2023-09-19 11:05:28 +08:00
201dcb9ba5 更新 2023-09-19 10:54:30 +08:00
ad36cba92e 更新 2023-09-13 16:58:16 +08:00
27dfc7aedb 更新 2023-09-13 16:54:58 +08:00
c48165cd78 更新 2023-09-11 11:30:12 +08:00
876f49fb25 更新 2023-09-08 17:09:31 +08:00
b41b1696fc 更新菜单样式 2023-09-08 14:11:07 +08:00
2bcd3a83e4 更新 2023-08-23 15:40:13 +08:00
9c1db27ebe 更新 2023-06-27 16:57:16 +08:00
e7effb0881 更新 2023-06-26 18:13:47 +08:00
8146b165f9 更新 2023-06-19 17:27:58 +08:00
55ff6e7a5a 更新 2023-06-16 13:40:51 +08:00
a29fa0d9c8 更新 2023-06-16 10:44:30 +08:00
0a255f0e51 更新 2023-06-16 10:43:40 +08:00
207bea46ca 更新 2023-06-15 15:41:05 +08:00
d30e4f0d96 更新 2023-06-14 18:02:59 +08:00
d788227ae4 更新 2023-06-13 08:53:12 +08:00
3104ea2b53 更新 2023-06-12 17:47:44 +08:00
0c6ab02e8d 更新 2023-06-07 16:20:52 +08:00
ccf30c5dca 更新 2023-06-06 09:41:27 +08:00
412198358d 更新 2023-06-05 15:36:06 +08:00
302006530e 更新 2023-06-02 19:34:48 +08:00
7b661965a9 更新 2023-06-01 11:06:30 +08:00
8d8b78c6a1 更新 2023-05-31 18:31:03 +08:00
9b8bab4a92 更新 2023-05-31 11:36:50 +08:00
75834b5cef 更新 2023-05-30 16:27:50 +08:00
0e5e3180c9 更新 2023-05-26 10:40:29 +08:00
aa9d6dbaf3 更新 2023-05-04 10:36:33 +08:00
a4c2ed2463 更新 2023-04-28 14:13:49 +08:00
529c789315 更新 2023-04-24 11:07:54 +08:00
1ef3784e3d 更新 2023-04-17 16:56:51 +08:00
07755e81b3 更新 2023-04-17 16:53:44 +08:00
003056192e 更新 2023-04-10 10:34:41 +08:00
a4d6b581d7 更新 2023-04-10 10:33:57 +08:00
4b51e156bb 更新 2023-04-07 16:53:18 +08:00
e623d6fd14 更新 2023-04-04 12:02:14 +08:00
d707d983fb 结构调整 2023-04-03 18:00:41 +08:00
1a9d58c2b3 PDA bug,重新发布 2023-04-03 11:51:17 +08:00
dfde341070 更新 2023-03-24 18:23:41 +08:00
220b2b87a6 更新 2023-03-03 17:33:11 +08:00
00b0a0e783 更新 2023-03-03 17:32:40 +08:00
ed066f8565 更新 2023-03-03 15:35:43 +08:00
2a43fa33ab 更新 2023-03-02 18:12:29 +08:00
3c988ca0e5 Add CONTRIBUTING 2023-03-01 11:11:08 +00:00
f0ccfb4e21 Add LICENSE 2023-03-01 11:10:40 +00:00
10708e7f14 更新 2023-02-28 18:25:34 +08:00
791567bf37 更新 2023-02-26 03:20:03 +08:00
f28dbce227 Merge branch 'import-solidjs' into 'dev'
add vue

See merge request JJins/wuhu-torn-helper!1
2023-02-25 10:32:28 +00:00
da8bed9529 更新 2023-02-25 13:53:40 +08:00
ee8b660539 更新 2023-02-23 16:34:46 +08:00
7e52b9c382 更新 2023-02-01 18:21:45 +08:00
001e72d27b 更新 2023-02-01 09:44:59 +08:00
1e151060f3 更新 2023-01-18 11:29:11 +08:00
6a0d0e064a 更新 2023-01-09 18:07:20 +08:00
82c01b18de 更新 2022-12-22 10:52:05 +08:00
e4b89e56c0 更新 2022-12-22 10:50:06 +08:00
870686032d 更新 2022-12-22 10:43:33 +08:00
8c092a622a Merge remote-tracking branch 'gitlab/dev' into dev 2022-12-20 15:52:28 +08:00
b8a7791d5f 边栏助手-圣诞小镇页面开启 2022-12-20 15:52:15 +08:00
e9599ba1ab 更新 2022-12-20 12:38:45 +08:00
b8bb19e6a6 更新 2022-12-20 11:19:07 +08:00
11b33016db 更新 2022-12-20 11:15:46 +08:00
fc65669e07 更新 2022-12-20 00:45:03 +08:00
7edb8b55c1 更新 2022-12-20 00:39:38 +08:00
5ab84be8c8 更新 2022-12-20 00:36:28 +08:00
7d3c5bfd11 更新 2022-12-20 00:33:51 +08:00
8db92c76bf 更新 2022-12-20 00:29:16 +08:00
40c167504b 更新 2022-12-20 00:20:13 +08:00
30fbbcafc0 更新 2022-12-20 00:16:52 +08:00
93d9401c4b 更新 2022-12-19 23:23:48 +08:00
d1297dd13b 更新 2022-12-19 23:21:06 +08:00
b50fabd890 更新 2022-12-19 22:55:08 +08:00
2e104654bd Merge remote-tracking branch 'gitlab/dev' into dev 2022-12-19 22:32:54 +08:00
271c16c1d6 更新 2022-12-19 22:32:15 +08:00
ae1f95658d 更新 2022-12-08 16:34:52 +08:00
ce7d9885cd 仓库整理 2022-12-08 16:20:02 +08:00
92c807aa86 更新 2022-12-07 17:32:37 +08:00
ec7b52aa92 更新 2022-12-06 22:17:05 +08:00
f929b5c6b1 更新 2022-12-06 11:40:22 +08:00
975f9f2e80 更新 2022-12-06 10:39:18 +08:00
e756cb190e 更新 2022-12-06 00:09:55 +08:00
374b2b9a08 更新 2022-12-04 22:38:16 +08:00
a62d908054 更新 2022-11-30 17:27:28 +08:00
2e3b0a4ca1 更新 2022-11-25 15:49:24 +08:00
7ae676782d 更新 2022-11-22 15:30:42 +08:00
06e2fae5cc 更新 2022-11-22 15:28:46 +08:00
ffc5013cae 更新 2022-11-15 20:17:40 +08:00
4220ce577c 更新 2022-11-10 18:05:07 +08:00
700151510b 更新 2022-11-08 15:55:24 +08:00
49933f7a7e 更新 2022-11-08 15:40:17 +08:00
95ca6914a9 更新 2022-11-04 17:33:19 +08:00
f5e4a5cfe3 更新 2022-11-03 16:34:58 +08:00
0b6c2cda4f 更新 2022-10-31 10:47:30 +08:00
be9e202802 更新 2022-10-26 02:34:30 +08:00
d7e678b6dd 更新 2022-10-26 01:37:54 +08:00
8b22f3615b 更新 2022-10-25 10:36:18 +08:00
e9b55bf694 更新 2022-10-24 17:54:13 +08:00
e08ddf7efe 更新 2022-10-24 17:51:03 +08:00
c51a050256 更新 2022-10-24 17:45:08 +08:00
acc995c4a2 更新 2022-10-24 17:31:28 +08:00
a7bd4bc838 新一天时区判断 2022-10-21 10:12:33 +08:00
7e236f7cd0 更新 2022-10-20 17:24:18 +08:00
bba1335130 更新 2022-10-19 18:33:24 +08:00
39576c86ba 更新 2022-10-19 18:05:12 +08:00
59c4240c93 更新 2022-10-18 18:57:44 +07:00
7033476b19 更新 2022-10-18 18:04:50 +08:00
d893c8ac32 更新 2022-10-17 18:09:20 +08:00
bb770d8e2e 更新 2022-10-17 15:19:18 +08:00
f37641a955 更新 2022-10-14 18:08:16 +08:00
ec60b88cbf 更新 2022-10-14 16:13:59 +08:00
e417311b81 更新 2022-10-14 16:13:08 +08:00
d7aa4cf021 更新 2022-10-13 18:05:15 +08:00
d8631c8d7f 更新 2022-10-12 18:04:30 +08:00
6f6712ee1b 更新 2022-10-12 18:03:32 +08:00
efcd95586d 更新 2022-10-11 18:13:08 +08:00
760504a124 UI调整 2022-10-11 18:12:20 +08:00
0f9bc62039 UI调整 2022-10-11 18:11:53 +08:00
4d287ff83f 更新 2022-10-10 18:13:09 +08:00
32462d2f10 更新 2022-10-10 18:12:17 +08:00
0797f498eb 更新 2022-10-09 17:57:48 +08:00
c010c488d6 TS重构 2022-10-09 17:56:16 +08:00
dd411a65fc TS重构 2022-10-09 11:06:35 +08:00
56b02ebf5e TS重构 2022-10-05 16:23:03 +08:00
3963f1c6e4 TS重构 2022-10-05 16:05:48 +08:00
6e92fa774a 更新 2022-10-02 02:46:44 +08:00
493d09a20c CHANGELOG.md 2022-10-02 01:41:51 +08:00
24586162d6 CHANGELOG.md 2022-10-01 23:33:43 +08:00
f808a803fa CHANGELOG.md 2022-10-01 23:33:28 +08:00
e1eac27a91 0.5.2 2022-10-01 23:01:44 +08:00
ada12c546c TS重构 2022-10-01 18:37:48 +08:00
842f69c691 TS重构 2022-10-01 15:38:24 +08:00
60e2c96282 TS重构 2022-09-30 18:16:52 +08:00
4f71a18a1e TS重构 2022-09-29 19:18:25 +08:00
3f1b6239ca TS重构 2022-09-28 19:54:28 +08:00
bb83b98a23 TS重构 2022-09-27 19:31:14 +08:00
f00148b708 TS重构 2022-09-27 11:58:39 +08:00
a97bc2cd01 TS重构 2022-09-26 19:10:40 +08:00
e6b3477c71 TS重构 2022-09-23 18:23:09 +08:00
6b85937b46 TS重构 2022-09-23 18:15:45 +08:00
8591a3b844 仓库整理 2022-09-21 18:50:01 +08:00
42827f9a52 TS重构 2022-09-21 18:47:52 +08:00
c1ba5c04ec TS重构 2022-09-20 19:18:21 +08:00
17c295c13e TS重构 2022-09-19 18:31:24 +08:00
7d494b8757 更新 2022-09-16 00:24:36 +08:00
44d6c283c7 TS重构 2022-09-15 18:20:29 +08:00
e7bece004f TS重构 2022-09-15 12:02:26 +08:00
26c9227461 TS重构 2022-09-14 18:14:52 +08:00
8b540b46fb TS重构 2022-09-13 18:11:39 +08:00
28fac2d8c5 TS重构 2022-09-13 18:10:23 +08:00
5534776e77 TS重构 2022-09-11 17:05:49 +08:00
cd38bd1b36 TS重构 2022-09-11 00:55:20 +08:00
a1d1c06632 TS重构 2022-09-11 00:52:00 +08:00
a5f0a82211 TS重构 2022-09-09 18:03:47 +08:00
d1c5d22f29 TS重构 2022-09-08 18:13:24 +08:00
e8bff038dd 代码清理 2022-09-08 16:35:17 +08:00
3e2e523e14 更新 2022-09-08 16:20:53 +08:00
a5b7bb8d66 更新 2022-09-08 16:19:55 +08:00
73ef110497 更新 2022-09-08 00:46:56 +08:00
2cdbf18750 更新 2022-09-08 00:46:13 +08:00
e854c4351d 更新 2022-09-07 18:04:07 +08:00
482c50a237 更新 2022-09-06 21:37:37 +08:00
2dbd19e2d0 更新 2022-09-06 21:36:08 +08:00
c88f22440d 更新 2022-09-06 21:34:16 +08:00
7f208b33f4 更新 2022-09-02 21:53:00 +08:00
3b32ab27bf TS重构、错误修正 2022-09-02 21:48:07 +08:00
347b343e8d 更新 2022-07-23 18:51:48 +08:00
3b628eac48 更新 2022-07-23 18:50:40 +08:00
903cae5dad 更新 2022-07-20 16:12:03 +08:00
2bdb7ccb60 更新 2022-07-15 14:58:12 +08:00
cd1c5e0174 更新 2022-07-15 11:03:52 +08:00
d4699b5983 更新 2022-07-15 11:01:38 +08:00
7d783b700c 更新 2022-07-11 23:15:26 +08:00
6c33d187d7 更新 2022-07-11 23:11:40 +08:00
7eb1b1846d 更新 2022-07-11 19:02:20 +08:00
7b18a8a38e 更新 2022-07-11 17:30:54 +08:00
597819af99 更新 2022-07-10 21:07:25 +08:00
ecd4e0d146 更新 2022-07-10 20:42:12 +08:00
ab4cdbb958 更新 2022-07-10 20:34:39 +08:00
6a6c125055 更新 2022-07-10 20:32:38 +08:00
a175777f79 更新 2022-07-09 00:27:46 +08:00
fd9cc52ff4 更新 2022-07-09 00:24:45 +08:00
e90c7a0095 更新 2022-07-09 00:24:38 +08:00
2e1d6e87fb 更新 2022-07-09 00:23:37 +08:00
b265365ead 更新历史 2022-07-06 11:01:04 +08:00
2ec9af9e67 更新历史 2022-07-03 16:10:40 +08:00
1347dea770 更新 2022-07-03 16:09:19 +08:00
925056d674 更新 2022-07-03 01:28:47 +08:00
9537013886 更新 2022-07-03 01:26:26 +08:00
8f881a2790 更新历史 2022-07-03 01:23:11 +08:00
6333a6b003 更新历史 2022-07-03 01:22:48 +08:00
447433cb2f 版本更新 2022-07-03 01:17:31 +08:00
e2e746e6ea 格式化、添加用户脚本调试模板 2022-07-02 21:55:52 +08:00
cdce46984b Update. 2022-07-02 21:44:54 +08:00
3d53c6ea3f 更新 2022-06-25 23:08:13 +08:00
a2a54d9043 版本更新 2022-06-25 16:01:12 +08:00
4a6a2b86c7 版本更新 2022-06-25 01:27:37 +08:00
2b4d9d6395 版本更新 2022-06-25 01:20:23 +08:00
fcb9a678b3 自动压缩js大小 2022-06-19 01:31:27 +08:00
bdcdb5babb 仓库清理 2022-06-18 21:00:21 +08:00
d24f4e9464 Update release.min.user.js 2022-06-17 16:38:01 +00:00
c7ace76090 错误修复 2022-06-18 00:35:46 +08:00
782bea5832 添加:加载时间、更多的选项 2022-06-17 17:22:56 +08:00
b19e4d06c8 添加:公司页面自动转跳存钱、增加快速犯罪选项、增加常用链接选项 2022-06-12 23:08:08 +08:00
7965d0efdc 添加:存钱框悬浮(公司、帮派)
修复:光速跑路无法关闭的错误
2022-06-12 18:20:54 +08:00
e0f128c0fd 添加:修改了点击4条的行为:分别对应锻炼、犯罪、物品(加成物品)、物品(医疗)
修复:光速跑路无法关闭的错误现已修复
2022-05-27 15:14:53 +08:00
1ac36e42b2 添加:修改了点击4条的行为:分别对应锻炼、犯罪、物品(加成物品)、物品(医疗)
修复:光速跑路无法关闭的错误现已修复
2022-05-27 14:39:26 +08:00
565a626cb3 修改一键起飞,添加往返时间估计、显示药CD 2022-04-05 04:20:11 +08:00
bf0a4b55c9 添加pt一键购买开关
中菜单现已折叠部分设置
完善一键起飞的内容,修复有关错误
2022-04-01 21:11:14 +08:00
428c9d9519 增加一键起飞 2022-03-31 20:34:16 +08:00
0ef4b25e0c 增加pt一键购买(NS抄来的) 2022-03-31 16:05:14 +08:00
1808c1932c 修复bug,调整css 2022-03-11 08:52:15 +08:00
e92ab14999 修复叠E助手bug,添加BnB商店加入啤酒的功能 2022-03-09 16:35:42 +08:00
5fb2133ce0 修复价格监视bug,修改css样式 2022-03-09 00:29:51 +08:00
c818730095 调整翻译逻辑,添加一些菜单的说明,健身房页面添加了叠E保护开关 2022-03-08 17:24:17 +08:00
bd73bf0281 修复节日的错误 2022-03-03 13:56:39 +08:00
12cdc90dde 修复节日的错误 2022-03-03 13:54:49 +08:00
a1078a0489 修改了通知样式 2022-03-03 11:28:07 +08:00
a668fbc56e 修改了样式 2022-02-25 21:31:31 +08:00
05ebda213d 性能优化,修复一些翻译错误,添加XAN价格监视 2022-02-23 17:24:00 +08:00
1262fd17c7 修复多次烦人的通知 2022-02-22 20:55:51 +08:00
229d22fe43 修复通知错误 2022-02-22 20:23:44 +08:00
492c22af1a 增加物品监视 2022-02-22 20:16:51 +08:00
f7a419879c 修复通知错误,现在飞花库存可以更快的加载了 2022-02-21 17:26:33 +08:00
e7b8d4961e 修复通知错误 2022-02-20 21:18:31 +08:00
0619bf15df 调整啤酒小助手的通知样式,修复危险功能开关的错误,加入系统通知支持;
替换PDA下飞贼助手的数据源,现在同样使用实时数据
2022-02-20 16:43:46 +08:00
561a7a053b 调整本地数据查询方式,修复啤酒小助手的错误 2022-02-18 16:48:39 +08:00
9785ea8b8b 添加查看NNB功能,修复啤酒小助手的错误,调整显示飞花库存 2022-02-17 23:32:40 +08:00
a9d2a1831a 添加显示活动详情,啤酒提醒通知中添加了转跳链接 2022-02-15 18:25:38 +08:00
c0c0afda83 调整菜单内容,修复了飞行闹钟的错误,添加显示节日和节日详情 2022-02-14 18:07:08 +08:00
5cf471b779 添加叠E保护 2022-02-11 16:58:51 +08:00
8a533e5f9b 修复捡垃圾助手的错误,调整样式 2022-02-03 19:49:49 +08:00
360d3ee92e 修复小窗犯罪的错误,添加用户名与id,添加捡垃圾助手(默认不开启) 2022-02-03 17:13:44 +08:00
811826046b 修复闹钟提醒的错误,添加今日不再提醒 2022-01-30 03:13:51 +08:00
7ae326df50 修复闹钟提醒的错误,添加今日不再提醒 2022-01-30 01:34:56 +08:00
333799dd06 修复闹钟提醒的错误,添加今日不再提醒 2022-01-30 00:36:01 +08:00
23ee97d208 调整界面样式,添加常用链接,添加啤酒提醒 2022-01-29 23:56:37 +08:00
0911e49d8d Merge remote-tracking branch 'origin/dev' into dev
# Conflicts:
#	torn-trans-zhcn.user.js
2022-01-29 23:51:47 +08:00
aa61787106 调整界面样式,添加常用链接,添加啤酒提醒 2022-01-29 23:50:21 +08:00
a295919070 飞贼小助手现可在所有页面加载 2022-01-28 15:34:49 +08:00
aca31a559b 调整样式、减少初始设置的通知 2022-01-28 01:12:49 +08:00
feae11dd78 增加通知 2022-01-27 18:11:42 +08:00
f6a6317a13 添加载入伞佬的飞贼小助手 2022-01-26 17:22:51 +08:00
2d6a7aa1eb 小窗口快速crime错误修复、优化边缘设置按钮 2022-01-18 17:32:44 +08:00
42b7ff9e85 小窗口快速crime错误修复 2022-01-17 17:52:13 +08:00
19a37715e0 小窗口快速crime手机版错误修复 2022-01-16 18:43:52 +08:00
7a230deadc 添加小窗口快速crime 2022-01-16 17:32:40 +08:00
a5c7cbc342 修复设置开关的错误 2022-01-14 00:44:52 +08:00
eec9a49f7a 修复设置开关的错误 2022-01-14 00:42:22 +08:00
ca9665ca72 调整飞行闹钟的样式 2022-01-13 23:11:21 +08:00
2149eb30a0 添加飞行闹钟 2022-01-13 00:28:54 +08:00
49a16c2516 添加危险行为警告开关 2022-01-11 14:40:49 +08:00
9ec49b06d5 添加自动开打和结束战斗 2022-01-10 16:39:49 +08:00
56852a1229 添加生存手册的链接、添加了NPC Loot时间表 2022-01-10 15:43:57 +08:00
ae5d624624 不缓存库存图 2022-01-08 17:47:26 +08:00
b3c2ffd3fa 修改了“Flexible Body Armor”的物品名翻译
增加了飞花库存图
2022-01-08 17:36:25 +08:00
2109456501 可以开打时声音提示
非12月隐藏小镇相关
添加自动刷新间隔
2022-01-07 17:42:57 +08:00
e23b6cd3bf 修复光速跑路bug 2022-01-06 18:29:19 +08:00
c754b12c06 增加更新选项,关闭光速跑路功能等待更多的测试结果 2022-01-06 16:09:08 +08:00
4fbac7495a 修复“光速跑路”无法关闭的bug 2022-01-05 22:45:44 +08:00
c8016a930d 增加最新版本图片与更新历史 2022-01-05 18:16:15 +08:00
180126000a 增加最新版本图片与更新历史 2022-01-05 18:15:38 +08:00
048cac1ef2 增加了“攻击界面自刷新” 2022-01-05 00:52:35 +08:00
9a5b727054 增加了“光速拔刀”、“光速跑路”功能 2022-01-04 17:38:49 +08:00
4b34e8d3d2 增加了设置区域的自动生成、增加了start fight按钮重新定位、增加了loader2攻击错误页面的转跳 2021-12-30 22:00:36 +08:00
b98663abb9 修复小镇提示的错误 2021-12-29 16:22:55 +08:00
e79f094fce 修复小镇提示的错误,添加脚本的功能配置 2021-12-29 00:11:04 +08:00
b1f09a502a 添加了左侧悬浮图标、设置选项、动态更新 2021-12-27 21:09:27 +08:00
13bfce86ed 小镇提示日期错误修复 2021-12-25 14:22:42 +08:00
d64bcb682a 小镇提示错误修复 2021-12-24 17:15:34 +08:00
a4b91dcc96 小镇提示逻辑改写 2021-12-24 17:11:50 +08:00
57894c2a42 修复了小镇提示的部分bug 2021-12-24 15:45:21 +08:00
dcefc6b164 增加了小镇提示选项和历史记录 2021-12-23 23:09:55 +08:00
8e2c250b1d 添加了圣诞小镇有掉落物时的声音效果 2021-12-22 14:56:05 +08:00
4e78d137df 添加了圣诞小镇有掉落物时的颜色渐变效果 2021-12-22 01:30:30 +08:00
058bbd8c8e 修复了圣诞小镇物品掉落名称不全的问题 2021-12-21 21:45:52 +08:00
9d0b1c4c14 修改了profile页面的日期翻译错误,优化代码 2021-12-21 12:52:35 +08:00
96713042fe 优化了小镇掉落物品的显示样式 2021-12-19 16:59:30 +08:00
8d794d8c66 添加添加圣诞小镇附近掉落信息 2021-12-18 17:03:50 +08:00
ba0f9ca038 添加日历页面翻译(未完成)
添加圣诞小镇解密助手
2021-12-16 17:34:01 +08:00
b70853da9e 调整了sellout slayer任务的助手说明
增加两个任务物品名称翻译
2021-12-13 17:34:45 +08:00
d0f1d2b325 增加适配npc pt商店及卖出框的标题 2021-12-11 17:02:53 +08:00
5bb8ada426 修复npc商店手机页面不适配问题 2021-12-11 16:14:11 +08:00
28363bd87a 修复报纸日期翻译问题 2021-12-11 15:23:36 +08:00
fad8478579 优化了页标题右侧按钮翻译
调整了物品页面、展柜页面物品详情翻译
增加了npc商人页面的翻译
更改了标题翻译匹配的字典
2021-12-10 19:12:19 +08:00
fa874f4b1a 更新股票页面、完善物品名翻译 2021-12-09 18:05:09 +08:00
aeb79ec9d3 更新股票页面 2021-12-09 14:34:25 +08:00
56bcda1938 优化物品页面 2021-12-08 17:30:01 +08:00
582b044b16 添加展柜、更新crime快速操作 2021-12-07 18:15:29 +08:00
70ca63d8b2 更新任务 2021-12-05 22:22:24 +08:00
7e2d2289de 更新任务 2021-12-05 22:19:38 +08:00
32f151fa49 更新物品名、任务 2021-12-05 21:49:27 +08:00
bcca17112a 更新crime快速操作 2021-12-03 17:25:08 +08:00
3082449508 修改物品页面翻译逻辑 2021-12-02 20:39:25 +08:00
70ce199f4f 修改物品页面翻译逻辑 2021-12-01 20:20:09 +08:00
54437b3129 添加起飞提示、修正任务提示错误 2021-12-01 00:45:58 +08:00
ec4ec94f7b 更新物品翻译 2021-11-30 22:01:32 +08:00
85ade8a6c1 添加crimes页面快速操作 2021-11-30 13:03:35 +08:00
18796e8614 更新物品、设置、pc页面 2021-11-29 19:39:54 +08:00
5fa098ead8 更新版本号 2021-11-29 00:04:27 +08:00
ddf96690de 更新任务页面,添加任务助手 2021-11-29 00:00:18 +08:00
de0b14f9b5 更新个人资料页面 2021-11-26 11:57:15 +08:00
6861c1bc04 更新悬赏页面 2021-11-25 22:00:21 +08:00
d470f64c1c 更新个人资料页面 2021-11-25 13:19:55 +08:00
25a8d5c68e 更新个人资料页面 2021-11-24 21:41:53 +08:00
04f5e187c2 更新股票页面 2021-11-24 18:14:51 +08:00
0f92a6c813 更新股票页面 2021-11-24 17:44:00 +08:00
3575b33cbd 更新股票页面 2021-11-24 12:32:50 +08:00
b9e240a4c4 更新股票页面 2021-11-23 19:01:32 +08:00
deff52881b 更新个人资料页面 2021-11-22 21:25:43 +08:00
1a22651131 更新个人资料页面 2021-11-22 19:39:57 +08:00
058fc901e3 更新通知 2021-11-21 20:26:12 +08:00
3f8d74e1d2 更新通知 2021-11-20 13:35:43 +08:00
e087fe9e47 更新通知 2021-11-19 23:52:34 +08:00
7c90052609 更新通知 2021-11-18 19:49:09 +08:00
9d80ef1932 更新通知 2021-11-18 19:29:04 +08:00
222e84b2ea 修复通知 2021-11-18 12:30:19 +08:00
a513c90e14 更新版本号 字段调整 2021-11-17 11:50:55 +08:00
854559d510 迷你资料卡修复 2021-11-16 17:58:59 +08:00
f3d5e18696 更新版本号、通知、房屋页面 2021-11-16 17:48:28 +08:00
695d22bb23 更新版本号、房产页面更新、主页翻译逻辑修改、字段修正 2021-11-16 11:35:40 +08:00
fb7195a523 awards页面更新 2021-11-14 18:05:27 +08:00
8ea4aceb7a 格式化 版本号调整 2021-11-14 17:54:17 +08:00
a866df68f7 更新迷你资料卡 2021-11-14 17:48:51 +08:00
846abad5b0 更新awards页面、可读性格式调整 2021-11-14 16:00:03 +08:00
ea52b6aa5c 更新awards页面 2021-11-14 15:57:53 +08:00
798c3bccda Merge remote-tracking branch 'gitee/dev' into dev.gitee 2021-11-14 03:27:44 +08:00
f12d8e3168 更新awards页面 2021-11-14 03:27:38 +08:00
刘昱彤
e68b23ec4d version revised 2021-11-14 02:51:47 +08:00
刘昱彤
728f47bc8a Merge remote-tracking branch 'origin/dev' into dev 2021-11-14 02:49:44 +08:00
刘昱彤
4ae6ed51ac 资金流动页面 2021-11-14 02:49:25 +08:00
刘昱彤
35bd4bd77e 资金流动页面 2021-11-14 02:49:06 +08:00
9b9d781241 Merge remote-tracking branch 'gitee/dev' into dev.gitee 2021-11-13 19:47:22 +08:00
2ad1a6cb04 更新awards页面 2021-11-13 19:47:10 +08:00
刘昱彤
4196bb8d9b ”领地“改成“地盘” 2021-11-13 18:49:26 +08:00
刘昱彤
3367870e58 帮派页面优化 2021-11-13 18:18:22 +08:00
刘昱彤
7247ec213c 帮派页面优化 2021-11-13 18:13:55 +08:00
刘昱彤
38cbe786f4 住院理由优化 2021-11-13 02:12:33 +08:00
刘昱彤
291331e60e 住院理由集合翻译 2021-11-13 02:07:43 +08:00
60e9ffad31 Merge remote-tracking branch 'gitee/dev' into dev.gitee 2021-11-12 23:22:16 +08:00
4e81b91ba2 添加awards页面翻译 2021-11-12 23:22:04 +08:00
刘昱彤
b42d0ee75a 住院理由翻译优化 2021-11-12 23:21:33 +08:00
刘昱彤
a29cf1dd56 住院理由翻译 2021-11-12 23:12:59 +08:00
aea223b22c 更新edu页面 2021-11-12 21:41:40 +08:00
刘昱彤
54b8d9a951 医院翻译优化 2021-11-12 17:55:32 +08:00
刘昱彤
fabc47512f Merge remote-tracking branch 'origin/dev' into dev 2021-11-12 17:29:55 +08:00
刘昱彤
d56427aaa2 医院翻译 2021-11-12 17:29:41 +08:00
2b14ad1af1 增加聊天框翻译 2021-11-12 17:25:47 +08:00
d1a61a7076 gym增加翻译字段 完善页面逻辑 2021-11-12 15:17:35 +08:00
cd4330fa4f 高级搜索现已翻译 gym逻辑调整 更新版本 2021-11-12 12:00:01 +08:00
57eea7b056 修复通知的标题链接 现可显示通知个数 2021-11-12 11:42:14 +08:00
ccd5e1e202 更新版本号 2021-11-11 21:08:16 +08:00
eeef884832 更新通知页面和通知翻译函数 2021-11-11 20:36:08 +08:00
3ee6724f18 Merge remote-tracking branch 'gitee/dev' into dev.gitee 2021-11-11 19:28:10 +08:00
688f7244e0 更新header 2021-11-11 19:27:53 +08:00
刘昱彤
02b211e57f Merge remote-tracking branch 'origin/dev' into dev 2021-11-11 18:10:29 +08:00
刘昱彤
215c22435b 通知字典以及通知选择栏翻译 2021-11-11 18:09:56 +08:00
ad36146166 更新city gym页面 2021-11-11 17:02:48 +08:00
c50f4080a3 更新city 2021-11-11 16:40:40 +08:00
b237a9a0dc 更新city补全字段 2021-11-11 16:36:46 +08:00
1f18027522 更新gym 2021-11-11 16:04:16 +08:00
刘昱彤
6e49502dd7 Merge remote-tracking branch 'origin/dev' into dev 2021-11-11 15:23:49 +08:00
572e68e43e 更新gym 2021-11-10 20:25:09 +08:00
AshleyLiuuuuu
3c39493b3f todo修改 2021-11-10 16:24:10 +08:00
AshleyLiuuuuu
9a37349494 城市快速链接 2021-11-10 16:19:35 +08:00
AshleyLiuuuuu
c51c5a56fe 健身房属性以及状态值 2021-11-10 15:43:51 +08:00
1677f3a45a 更新版本号 2021-11-10 11:59:54 +08:00
a9dde19476 更新飞行页面和标题汉化方式 2021-11-10 11:59:25 +08:00
beae66100e 更新 2021-11-09 23:23:01 +08:00
158e2f670d 更新报纸页面 2021-11-09 23:22:32 +08:00
e190a5cb89 gym页面bug修复 2021-11-09 19:23:40 +08:00
f88e140655 更新edu页面 2021-11-09 18:43:55 +08:00
AshleyLiuuuuu
a0c240aae0 近期攻击翻译优化 2021-11-09 18:23:00 +08:00
6fe46f9adb 更新edu页面 2021-11-09 17:11:15 +08:00
4b3701dce2 更新gym edu页面 2021-11-09 15:43:05 +08:00
AshleyLiuuuuu
7ce378928c 健身房翻译优化 2021-11-09 15:33:28 +08:00
AshleyLiuuuuu
916cd346a4 近期攻击信息翻译 2021-11-09 15:22:48 +08:00
fa4369e9c9 更新健身房页面 2021-11-09 00:09:43 +08:00
AshleyLiuuuuu
ade9757b37 Merge remote-tracking branch 'origin/dev' into dev 2021-11-08 18:08:30 +08:00
AshleyLiuuuuu
93419aeec3 已知翻译优化以及近期攻击信息翻译 2021-11-08 18:08:08 +08:00
213ad75f97 格式调整 2021-11-08 17:34:35 +08:00
2ecc87e4fb 更新city页面 2021-11-08 17:31:20 +08:00
fe7c4012f2 更新租房买房 2021-11-08 15:34:36 +08:00
1e738b081f 更新 2021-11-08 14:42:48 +08:00
51a709047a 调整通知,更新报纸、房屋交易 2021-11-08 01:06:38 +08:00
c603a85c8d 更新版本号 2021-11-06 22:07:36 +08:00
dd94eb0a17 更新房屋买卖租赁页面 2021-11-06 21:19:20 +08:00
a8132fc553 更新property页面 2021-11-06 21:04:53 +08:00
36096527c6 更新房屋买卖租赁页面 2021-11-06 20:17:48 +08:00
852bf471f0 更新帮派职位变动通知 2021-11-06 15:33:56 +08:00
402f6fd111 字段修复 2021-11-06 02:19:11 +08:00
f72f2cbf06 修复逻辑错误 2021-11-06 01:22:29 +08:00
4010b3e9db 更新房屋购买与租赁 2021-11-06 01:18:14 +08:00
e47467f2bb 修改版本号 2021-11-05 20:52:23 +08:00
2eba35a3a5 修改边栏逻辑 添加超时 2021-11-05 16:55:05 +08:00
27b273aef7 更新主页部分 2021-11-05 16:10:44 +08:00
7536e63892 修改飞行部分 2021-11-05 11:20:18 +08:00
f01b969c08 更新主页部分
更新版本号,发布
2021-11-04 21:48:03 +08:00
810f8b070b 更新主页
更新版本号,发布
2021-11-04 21:47:15 +08:00
AshleyLiuuuuu
5497c8139f 飞行界面翻译优化以及戒毒翻译 2021-11-04 18:55:37 +08:00
AshleyLiuuuuu
187e43ab7b Defined user event(zh) while traveling. 2021-11-04 17:53:57 +08:00
a1acb729bc 更新版本号,发布更新 2021-11-04 17:34:02 +08:00
c8c97ee75d 更新通知:solo attack 2021-11-04 09:16:25 +00:00
f97c387be8 更新通知:病毒 交易 2021-11-04 06:23:31 +00:00
475435d625 upload 2021-11-03 14:11:28 +00:00
10b3e3245c 更新通知:赛车 还贷 收到钱物 bazaar 彩票 捞人 2021-11-03 14:07:00 +00:00
5b57539732 更新通知部分 2021-11-03 13:56:00 +00:00
c2faf00855 更新 2021-11-03 07:18:36 +00:00
262 changed files with 72001 additions and 123 deletions

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
/node_modules
/.fleet
/src/dist/bundle.min.js
/src/dist/bundle.js
/dist
auto-imports.d.ts
components.d.ts
aws.xml

8
.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

20
.idea/codeStyles/Project.xml generated Normal file
View File

@ -0,0 +1,20 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<JSCodeStyleSettings version="0">
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
<option name="SPACES_WITHIN_IMPORTS" value="true" />
<option name="SPACES_WITHIN_INTERPOLATION_EXPRESSIONS" value="true" />
</JSCodeStyleSettings>
<JetCodeStyleSettings>
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<TypeScriptCodeStyleSettings version="0">
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
<option name="SPACES_WITHIN_IMPORTS" value="true" />
<option name="SPACES_WITHIN_INTERPOLATION_EXPRESSIONS" value="true" />
</TypeScriptCodeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</codeStyleSettings>
</code_scheme>
</component>

5
.idea/codeStyles/codeStyleConfig.xml generated Normal file
View File

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>

8
.idea/dictionaries/Liwanyi.xml generated Normal file
View File

@ -0,0 +1,8 @@
<component name="ProjectDictionaryState">
<dictionary name="Liwanyi">
<words>
<w>wuhu</w>
<w>zhong</w>
</words>
</dictionary>
</component>

View File

@ -0,0 +1,66 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="AliAccessStaticViaInstance" enabled="false" level="BLOCKER" enabled_by_default="false" />
<inspection_tool class="AliArrayNamingShouldHaveBracket" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AliControlFlowStatementWithoutBraces" enabled="false" level="BLOCKER" enabled_by_default="false" />
<inspection_tool class="AliDeprecation" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AliEqualsAvoidNull" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AliLongLiteralsEndingWithLowercaseL" enabled="false" level="BLOCKER" enabled_by_default="false" />
<inspection_tool class="AliMissingOverrideAnnotation" enabled="false" level="BLOCKER" enabled_by_default="false" />
<inspection_tool class="AliWrapperTypeEquality" enabled="false" level="BLOCKER" enabled_by_default="false" />
<inspection_tool class="AlibabaAbstractClassShouldStartWithAbstractNaming" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaAbstractMethodOrInterfaceMethodMustUseJavadoc" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidApacheBeanUtilsCopy" enabled="false" level="BLOCKER" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidCallStaticSimpleDateFormat" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidCommentBehindStatement" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidComplexCondition" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidConcurrentCompetitionRandom" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidDoubleOrFloatEqualCompare" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidManuallyCreateThread" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidMissUseOfMathRandom" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidNegationOperator" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidNewDateGetTime" enabled="false" level="BLOCKER" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidPatternCompileInMethod" enabled="false" level="BLOCKER" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidReturnInFinally" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidStartWithDollarAndUnderLineNaming" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaAvoidUseTimer" enabled="false" level="BLOCKER" enabled_by_default="false" />
<inspection_tool class="AlibabaBigDecimalAvoidDoubleConstructor" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaBooleanPropertyShouldNotStartWithIs" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaClassCastExceptionWithSubListToArrayList" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaClassCastExceptionWithToArray" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaClassMustHaveAuthor" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaClassNamingShouldBeCamel" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaCollectionInitShouldAssignCapacity" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaCommentsMustBeJavadocFormat" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaConcurrentExceptionWithModifyOriginSubList" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaConstantFieldShouldBeUpperCase" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaCountDownShouldInFinally" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaDontModifyInForeachCircle" enabled="false" level="BLOCKER" enabled_by_default="false" />
<inspection_tool class="AlibabaEnumConstantsMustHaveComment" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaExceptionClassShouldEndWithException" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaIbatisMethodQueryForList" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaLockShouldWithTryFinally" enabled="false" level="BLOCKER" enabled_by_default="false" />
<inspection_tool class="AlibabaLowerCamelCaseVariableNaming" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaMethodReturnWrapperType" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaMethodTooLong" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaPackageNaming" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaPojoMustOverrideToString" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaPojoMustUsePrimitiveField" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaPojoNoDefaultValue" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaRemoveCommentedCode" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaServiceOrDaoClassShouldEndWithImpl" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaStringConcat" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaSwitchStatement" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaTestClassShouldEndWithTestNaming" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaThreadLocalShouldRemove" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaThreadPoolCreation" enabled="false" level="BLOCKER" enabled_by_default="false" />
<inspection_tool class="AlibabaThreadShouldSetName" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaTransactionMustHaveRollback" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaUndefineMagicConstant" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaUnsupportedExceptionWithModifyAsList" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="AlibabaUseQuietReferenceNotation" enabled="false" level="MAJOR" enabled_by_default="false" />
<inspection_tool class="AlibabaUseRightCaseForDateFormat" enabled="false" level="CRITICAL" enabled_by_default="false" />
<inspection_tool class="MapOrSetKeyShouldOverrideHashCodeEquals" enabled="false" level="CRITICAL" enabled_by_default="false" />
</profile>
</component>

6
.idea/misc.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="Python 3.8 (fstock)" project-jdk-type="Python SDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

8
.idea/modules.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/torncity-zhcn-translate.iml" filepath="$PROJECT_DIR$/.idea/torncity-zhcn-translate.iml" />
</modules>
</component>
</project>

6
.idea/smartfox_info.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SmartFoxProjectConfig">
<option name="projectInspectionClosed" value="true" />
</component>
</project>

14
.idea/torncity-zhcn-translate.iml generated Normal file
View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.fleet" />
<excludeFolder url="file://$MODULE_DIR$/misc" />
<excludeFolder url="file://$MODULE_DIR$/dist" />
<excludePattern pattern="release.min.user.js" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

14
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,14 @@
{
// 使 IntelliSense
//
// 访: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"command": "npm run rollup",
"name": "rollup",
"request": "launch",
"type": "node-terminal"
}
]
}

1246
CHANGELOG.md Normal file

File diff suppressed because it is too large Load Diff

1
CONTRIBUTING.md Normal file
View File

@ -0,0 +1 @@

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 JJins
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1 +1,23 @@
# torncity-zhcn-translate # Wuhu Torn Helper
[![LICENSE](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
[中文](README_ZHCN.md)
[CHANGELOG(CN)](CHANGELOG.md)
A customized auxiliary-enhancement user script designed for a browser-based MMORPG game, featuring a range of convenient
functions.
This script does not include any automation-related code.
## Build
npm init
npm run rollup
## Use
[release.min.user.js](release.min.user.js)
Please install with Tampermonkey (for PC browser) or TornPDA.

20
README_ZHCN.md Normal file
View File

@ -0,0 +1,20 @@
# 芜湖助手 Torncity 翻译插件
[![LICENSE](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
[CHANGELOG](CHANGELOG.md)
一个为浏览器网页MMORPG游戏定制的辅助增强用户脚本包含了一系列便携功能。
此脚本不包含自动化相关代码。
## 编译
npm init
npm run rollup
## 使用
[release.min.user.js](https://gitlab.com/JJins/wuhu-torn-helper/-/raw/dev/README_ZHCN.md)
请使用 Tampermonkey (浏览器) 或 TornPDA 安装。

39
build.mjs Normal file
View File

@ -0,0 +1,39 @@
/**
* 此脚本用于加入userscript meta
* 并生成日期时间与版本号
*/
import { readFileSync, writeFileSync } from "fs";
import { prodConfig } from "./rollup.config.js";
let date = new Date();
let version = process.env.npm_package_version;
let formattedDateTime = `${ date.getFullYear() }${ ('0' + (date.getMonth() + 1)).slice(-2) }${ ('0' + date.getDate()).slice(-2) }${ ('0' + date.getHours()).slice(-2) }${ ('0' + date.getMinutes()).slice(-2) }`;
let metaData =
`// ==UserScript==
// @lastmodified ${ formattedDateTime }
// @name 芜湖助手
// @namespace WOOH
// @version ${ version }
// @description 托恩,起飞!
// @author Woohoo[2687093] Sabrina_Devil[2696209]
// @match https://www.torn.com/*
// @downloadURL https://gitlab.com/JJins/wuhu-torn-helper/-/raw/dev/release.min.user.js
// @grant GM_xmlhttpRequest
// @grant unsafeWindow
// @connect yata.yt
// @connect github.io
// @connect gitlab.com
// @connect staticfile.org
// @connect gitee.com
// ==/UserScript==
`
const data = readFileSync('./' + prodConfig.output.file, 'utf8');
writeFileSync(
'./release.min.user.js',
metaData + data.replace('$$WUHU_DEV_VERSION$$', version),
'utf8'
);
// rmSync('./' + prodConfig.output.file);
console.log(`版本 ${ version } 构建完成`);

6
css-module.d.ts vendored Normal file
View File

@ -0,0 +1,6 @@
// declare module "*.module.css" {
// const css: string;
// const classes: { [key: string]: string };
// export default classes;
// export { css };
// }

21
custom-injector.js Normal file
View File

@ -0,0 +1,21 @@
export const customInjector = (varName) => {
let rt = ((__var) => {
const inject = (ob) => {
if (document && document.head) {
ob?.disconnect();
const style = document.createElement('style');
style.setAttribute('type', 'text/css');
style.innerHTML = __var;
document.head.appendChild(style);
}
};
if (document && document.head) {
inject();
} else {
new MutationObserver((_, ob) => {
inject(ob);
}).observe(document.documentElement, { childList: true });
}
}).toString();
return `(${ rt })(${ varName })`;
};

129
global.d.ts vendored Normal file
View File

@ -0,0 +1,129 @@
declare interface String {
contains(keywords: RegExp | string): boolean;
/* 翻译 */
// 时分秒转换
replaceHMS(): string;
// 数词转换 a an some
numWordTrans(): string;
}
declare interface Window {
$?: JQueryStatic;
jQuery?: JQueryStatic;
WHPARAMS?: any;
hasWHQuickFlyOpt?: boolean;
// 插件运行标识
WHTRANS?: number;
Vue?: Function;
/**
*
*/
unsafeWindow?: Window & typeof globalThis;
/**
* google
*/
_gaUserPrefs?: unknown;
GM_xmlhttpRequest(init: GM_RequestParams): void;
GM_getValue(k: string, def: any): unknown;
GM_setValue(k: string, v: any): void;
/**
* TORN自带
*/
ReactDOM?: any;
dataLayer?: unknown;
eval(exc: string): void;
addRFC(url: URL | string): string;
getAction(opt: TornGetActionParams): void;
initializeTooltip(selector: string, elemId: string): void;
renderMiniProfile(node: Element, props: any): never;
/**
* PDA自带
*/
PDA_httpGet(url: URL | string): Promise<PDA_Response>;
PDA_httpPost(url: URL | string, init: any, body: any): Promise<PDA_Response>;
// TODO 临时测试用
// [key: string]: unknown;
}
declare interface GM_RequestParams {
method?: string,
url?: URL | string,
data?: any,
headers?: any,
onload?: Function,
onerror?: Function,
ontimeout?: Function,
}
declare interface PDA_Response {
responseText: string
}
declare interface Element {
innerText?: string;
src?: string;
}
declare interface Notification {
id?: number;
}
declare interface Array<T> {
fest_date_dict?: { [key: string]: { name: string, eff: string } };
fest_date_list?: string[];
[key: string]: any;
}
declare interface Navigator {
userAgentData?: any;
}
declare interface TornGetActionParams {
type: 'post' | 'get',
action?: string,
data?: {
step?: string,
id?: number,
key?: string,
type?: string
},
success: Function,
before?: Function
}
declare module "*.html" {
const html: string;
export default html;
}
declare module "*.module.css" {
const css: string;
// const classes: { [key: string]: string };
// export default classes;
export default css;
// export { css };
}
declare function GM_xmlhttpRequest(init: any): void;
declare var unsafeWindow: Window & typeof globalThis;
declare type Constructor<T = any> = new (...args: any[]) => T;
declare interface ClassType<T> {
new(...args: unknown[]): T
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

15
misc/fetch_torn_items.py Normal file
View File

@ -0,0 +1,15 @@
import json
import requests
# URL = "https://jjins.github.io/item_price_raw.json"
URL = "https://script.google.com/macros/s/AKfycbyRfg1Cx2Jm3IuCWASUu8czKeP3wm5jKsie4T4bxwZHzXTmPbaw4ybPRA/exec?key=getItems"
resArr = requests.get(URL).json()['items']
obj = {}
for item in resArr:
obj[item[0]] = {'name': item[1], 'price': item[2]}
file = open('item_price_raw.json', 'w')
file.write(json.dumps(obj))
file.close()
print('物品价格表已更新')

118
misc/fstock.py Normal file
View File

@ -0,0 +1,118 @@
import json
from datetime import datetime, timezone, timedelta
import os
import requests
DEST_ARR = ['mex', 'cay', 'can', 'haw', 'uni', 'arg', 'swi', 'jap', 'chi', 'uae', 'sou']
DEST_TRANS = {
'mex': '', 'cay': '', 'can': '',
'haw': '', 'uni': '', 'arg': '',
'swi': '', 'jap': '', 'chi': '', 'uae': '', 'sou': '',
}
VALUED_ITEM_ARR = [
'Dahlia', 'Jaguar Plushie',
'Banana Orchid', 'Stingray Plushie',
'Crocus', 'Wolverine Plushie',
'Orchid', 'Large Suitcase',
'Red Fox Plushie', 'Nessie Plushie', 'Heather',
'Ceibo Flower', 'Monkey Plushie', 'Tear Gas',
'Chamois Plushie', 'Edelweiss',
'Cherry Blossom',
'Panda Plushie', 'Peony',
'Camel Plushie', 'Tribulus Omanense',
'Lion Plushie', 'African Violet', 'Xanax',
]
ITEM_TRANS = {
'Dahlia': '', 'Jaguar Plushie': '',
'Banana Orchid': '', 'Stingray Plushie': '',
'Crocus': '', 'Wolverine Plushie': '',
'Orchid': '', 'Large Suitcase': '大箱',
'Red Fox Plushie': '赤狐', 'Nessie Plushie': '水怪', 'Heather': '',
'Ceibo Flower': '', 'Monkey Plushie': '', 'Tear Gas': '催泪弹',
'Edelweiss': '', 'Chamois Plushie': '',
'Cherry Blossom': '',
'Peony': '', 'Panda Plushie': '',
'Tribulus Omanense': '', 'Camel Plushie': '',
'African Violet': '', 'Lion Plushie': '', 'Xanax': 'XAN',
}
HISTORY_FILE = 'stock_hist.json'
HISTORY_EXIST = os.path.exists(HISTORY_FILE)
UTC_8 = timezone(timedelta(hours=8))
URL = "https://yata.yt/api/v1/travel/export/"
resObj = requests.get(URL).json()["stocks"]
# 更新时间
lastUpdate = 0
for dest in DEST_ARR:
res_update = resObj[dest]["update"]
if lastUpdate < res_update:
lastUpdate = res_update
lastUpdate = datetime.fromtimestamp(lastUpdate).astimezone(UTC_8)
UPDATE_TIME_STR = lastUpdate.strftime('%H:%M:%S')
# 整理过的对象
stockObj = {}
for dest in DEST_ARR:
arr = []
for f_item in resObj[dest]['stocks']:
for v_item in VALUED_ITEM_ARR:
if f_item['name'] == v_item:
arr.append(f_item)
stockObj[dest] = arr
# 移除亏本的xan
# 加拿大
index = -1
for i in range(len(stockObj['can'])):
if stockObj['can'][i]['name'] == 'Xanax':
index = i
if index != -1:
del stockObj['can'][index]
# 英国
index = -1
for i in range(len(stockObj['uni'])):
if stockObj['uni'][i]['name'] == 'Xanax':
index = i
if index != -1:
del stockObj['uni'][index]
# 日本
index = -1
for i in range(len(stockObj['jap'])):
if stockObj['jap'][i]['name'] == 'Xanax':
index = i
if index != -1:
del stockObj['jap'][index]
# 读取库存历史
stockHistObj = {}
if HISTORY_EXIST:
print('历史文件存在')
with open(HISTORY_FILE, 'r') as load_f:
stockHistObj = json.load(load_f)
else:
stockHistObj['json'] = []
stockHistObj['json'].append({str(int(datetime.now().timestamp())): stockObj})
if len(stockHistObj['json']) > 100:
del stockHistObj['json'][0]
with open(HISTORY_FILE, 'w') as f:
json.dump(stockHistObj, f)
hist_arr = stockHistObj['json']
# 用于写入文件的列表
seq = ["更新时间: %s\n" % UPDATE_TIME_STR]
for dest in DEST_ARR:
seq_str = '%s ' % DEST_TRANS[dest]
for i in range(len(stockObj[dest])):
seq_str += '%s%s' % (ITEM_TRANS[stockObj[dest][i]['name']], stockObj[dest][i]['quantity'])
if i != len(stockObj[dest]) - 1:
seq_str += ' '
seq_str += '\n'
seq.append(seq_str)
# 写入文件
fo = open(file="stock.txt", mode="w", encoding="utf-8")
fo.writelines(seq)
fo.close()
print("花偶库存更新完成")

4658
misc/item_price_raw.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
// ==UserScript==
// @name Debug Userscript
// @namespace https://github.com/einverne/userscripts
// @version 0.1
// @description This is a debug script to load userscripts from local file system. NOTICE, you need to turn on Allow access to file URLs to @require local file https://www.tampermonkey.net/documentation.php
// @author Ein Verne
// @match http*://*
// @include http://*
// @include https://*
// @include *
// @grant GM_xmlhttpRequest
// @grant GM_addStyle
// @grant GM_getResourceText
// @require {{file path}}
// ==/UserScript==
(function () {
'use strict';
console.log("debug script start here");
// Your code here...
})();

16538
misc/vue.js Normal file

File diff suppressed because it is too large Load Diff

10740
misc/wuhu-torn-helper.js Normal file

File diff suppressed because it is too large Load Diff

13205
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

43
package.json Normal file
View File

@ -0,0 +1,43 @@
{
"name": "wuhu-torn-helper",
"version": "1.2.4",
"description": "芜湖助手",
"scripts": {
"release": "cross-env NODE_ENV=production rollup -c && node build.mjs",
"watch": "cross-env NODE_ENV=development rollup -c -w",
"rollup": "cross-env NODE_ENV=development rollup -c"
},
"devDependencies": {
"@element-plus/icons-vue": "^2.1.0",
"@rollup/plugin-alias": "^4.0.3",
"@rollup/plugin-commonjs": "^24.0.1",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^15.0.1",
"@rollup/plugin-replace": "^5.0.2",
"@rollup/plugin-terser": "^0.4.0",
"@rollup/plugin-typescript": "^8.5.0",
"@types/jquery": "^3.5.14",
"@types/node": "^20.6.0",
"@vitejs/plugin-vue": "^4.0.0",
"@vue/tsconfig": "^0.1.3",
"cross-env": "^7.0.3",
"element-plus": "^2.3.10",
"just-clone": "^6.2.0",
"npm": "^8.19.2",
"reflect-metadata": "^0.1.13",
"rollup": "^2.79.0",
"rollup-plugin-postcss": "^4.0.2",
"rollup-plugin-string-html": "^1.0.0",
"rollup-plugin-styles": "^4.0.0",
"rollup-plugin-typescript2": "^0.34.1",
"tslib": "^2.4.0",
"typescript": "^4.8.3",
"unplugin-auto-import": "^0.15.2",
"unplugin-element-plus": "^0.7.0",
"unplugin-icons": "^0.16.1",
"unplugin-vue-components": "^0.24.1",
"vant": "^4.1.2",
"vue": "^3.2.47"
},
"type": "module"
}

55
release.min.user.js Normal file

File diff suppressed because one or more lines are too long

131
rollup.config.js Normal file
View File

@ -0,0 +1,131 @@
// [!] Error: Unexpected token (Note that you need plugins to import files that are not JavaScript)
// src/vue/ItemPrice.vue?vue&type=script&lang.ts (35:13)
// TODO 官方提供ts插件在vue模版中使用ts语言时报错
// import typescript from "@rollup/plugin-typescript";
// TODO 在rollup watch模式中不更新vue模版ts部分代码
import typescript2 from "rollup-plugin-typescript2";
import json from "@rollup/plugin-json";
import html from "rollup-plugin-string-html";
import resolve from "@rollup/plugin-node-resolve";
import replace from "@rollup/plugin-replace";
import alias from "@rollup/plugin-alias";
import vue from "@vitejs/plugin-vue";
import styles from "rollup-plugin-styles";
import { customInjector } from "./custom-injector.js";
import terser from "@rollup/plugin-terser";
import clone from "just-clone";
import commonjs from '@rollup/plugin-commonjs';
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
// import { VantResolver } from 'unplugin-vue-components/resolvers';
import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
import IconsResolver from 'unplugin-icons/resolver';
import Icons from 'unplugin-icons/vite'
import ElementPlus from 'unplugin-element-plus/rollup'
let node_env = process.env.NODE_ENV;
let vuePath = node_env === 'production' ?
'vue/dist/vue.runtime.esm-browser.prod.js' :
'vue/dist/vue.runtime.esm-browser.js';
const devConfig = {
input: 'src/ts/index.ts',
output: {
file: 'dist/bundle.js',
format: 'iife',
name: 'bundle.js',
},
plugins: [
json(),
html({
include: ["**/*.html"],
minifier: {
includeAutoGeneratedTags: true,
removeAttributeQuotes: false,
removeComments: true,
removeRedundantAttributes: false,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
sortClassName: true,
useShortDoctype: true,
collapseWhitespace: true,
minifyCSS: true,
}
}),
// 根据环境更改vue源
alias({
entries: [
{ find: 'vue', replacement: vuePath },
]
}),
// 为vue替换环境变量
replace({
values: {
'process.env.NODE_ENV': () => JSON.stringify(node_env),
'__VUE_OPTIONS_API__': () => JSON.stringify(false),
'__VUE_PROD_DEVTOOLS__': () => JSON.stringify(true),
},
preventAssignment: true,
}),
// 引入node相关方法
resolve({
browser: true,
preferBuiltins: false,
}),
commonjs(),
vue({ isProduction: node_env === 'production' }),
AutoImport({
resolvers: [
ElementPlusResolver(),
IconsResolver({
prefix: 'Icon',
}),
],
}),
Components({
resolvers: [
IconsResolver({
enabledCollections: ['ep'],
}),
ElementPlusResolver()
],
// resolvers: [VantResolver()],
}),
Icons(),
ElementPlus(),
// 自定义注入器注入vue部分css
styles({
// modules: true,
// namedExports: true,
exclude: /static\/css\/.+\.css/,
mode: [
"inject",
(varName) => customInjector(varName),
],
minimize: true
}),
// 非vue部分css逻辑代码中手动注入
styles({
include: /static\/css\/.+\.css/,
// modules: true,
// namedExports: true,
mode: [
"inject",
() => ``,
],
minimize: true
}),
typescript2({
tsconfig: "./tsconfig.json",
}),
],
};
const prodConfig = clone(devConfig);
prodConfig.plugins.push(terser());
prodConfig.output.file = 'dist/bundle.min.js';
prodConfig.output.name = 'bundle.min.js';
export default [devConfig, prodConfig];
export { prodConfig };

7
src/shims-vue.d.ts vendored Normal file
View File

@ -0,0 +1,7 @@
/* eslint-disable */
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}
/* eslint-enable */

View File

@ -0,0 +1,82 @@
.wh-move-btn #defender div[class^="modal___"] {
display: block;
width: 0 !important;
left: -169px !important;
background: none;
}
.wh-move-btn #defender div[class^="dialog___"] {
border: 0;
width: 159px;
height: 96px;
max-width: unset;
}
.wh-move-btn #defender div[class^="colored___"] {
display: block;
padding: 0;
}
.wh-move-btn #defender div[class^="title___"] {
height: 0;
}
/* 此处限制宽度,否则人物模型图片会溢出遮挡武器栏 */
.wh-move-btn #defender div[class^="modelWrap___"] {
max-width: 100%;
}
.wh-move-btn #defender button {
width: 100%;
margin: 17px 0;
height: 60px;
}
/* 解决按钮图标负边距被上层元素限制遮挡问题 */
.wh-move-btn #defender div[class^="playerWindow___"] {
overflow: unset;
}
/* 手机端 */
@media screen and (max-width: 600px) {
.wh-move-btn #attacker div[class^="playerWindow___"] {
overflow: unset;
}
.wh-move-btn #attacker div[class^="modelWrap___"] {
max-width: 100%;
}
.wh-move-btn #attacker div[class^="modal___"] {
display: block;
width: 0;
top: CSSVAR;
left: -80px;
height: 0;
}
.wh-move-btn #attacker div[class^="dialog___"] {
border: 0;
width: 80px;
/* torn的规则限制90% */
max-width: unset;
height: CSSVAR;
}
.wh-move-btn #attacker div[class^="colored___"] {
display: block;
padding: 0;
}
.wh-move-btn #attacker div[class^="title___"] {
height: 0;
}
.wh-move-btn #attacker button {
width: 100%;
margin: 0;
height: 63px;
white-space: normal;
}
}

View File

@ -0,0 +1,57 @@
.wh-city-finds .leaflet-marker-pane img[src*="torn.com/images/items/"] {
display: block !important;
box-sizing: border-box;
width: 40px !important;
height: 40px !important;
left: -20px !important;
top: -20px !important;
padding: 10px 0;
border: none;
border-radius: 100%;
background-color: #d2d2d28c;
box-shadow: 0 0 10px 5px #000;
z-index: 999 !important;
}
.wh-city-finds .leaflet-marker-pane.leaflet-marker-icon.user-item-pinpoint.leaflet-clickable {
display: none !important;
}
/*#wh-city-finder-header{*/
/* background-color: #3f51b5;*/
/* color: white;*/
/* padding: 8px;*/
/* font-size: 15px;*/
/* border-radius: 4px 4px 0 0;*/
/* text-shadow: 0 0 2px black;*/
/* background-image: linear-gradient(90deg,transparent 50%,rgba(0,0,0,.07) 0);*/
/* background-size: 4px;*/
/*}*/
/*#wh-city-finder{*/
/* box-shadow: 0 0 3px 0px #696969;*/
/* border-radius: 4px;*/
/*}*/
/*#wh-city-finder-cont{*/
/* background: #616161;*/
/* padding: 8px;*/
/* color: #c7c7c7;*/
/* border-radius: 0 0 4px 4px;*/
/* font-size: 13px;*/
/*}*/
/*#wh-city-finder-cont span{*/
/* margin:2px 4px 2px 0;*/
/* padding:2px;*/
/* border-radius:2px;*/
/* background:green;*/
/* color:white;*/
/* display:inline-block;*/
/*}*/
.wh-city-finder-item {
margin: 2px 4px 2px 0;
padding: 2px;
border-radius: 2px;
background: green;
color: white;
display: inline-block;
}

View File

@ -0,0 +1,292 @@
.wh-hide {
display: none;
}
#wh-trans-icon {
user-select: none;
display: inline-block;
position: fixed;
top: 5px;
left: 5px;
z-index: 100010;
border-radius: 4px;
max-width: 220px;
box-shadow: 0 0 3px 1px #8484848f;
}
div#effectiveness-wrap {
overflow-y: hidden;
}
@media screen and (max-width: 600px) {
#wh-trans-icon {
top: 0;
left: 112px;
}
/* 冰蛙公司效率表 */
div#effectiveness-wrap {
margin-left: -76px;
margin-right: -76px;
}
}
#wh-trans-icon select {
width: 110px;
}
#wh-trans-icon a {
text-decoration: none;
color: #006599;
background: none;
}
#wh-trans-icon:not(.wh-icon-expanded):hover {
background: #f8f8f8;
}
#wh-trans-icon button {
margin: 0;
padding: 0;
border: 0;
cursor: pointer;
}
#wh-inittimer {
margin-top: 6px;
color: #b0b0b0;
}
#wh-gSettings div {
margin: 4px 0;
}
#wh-trans-icon .wh-container {
margin: 0;
padding: 0 16px 16px;
border: 0;
}
#wh-trans-icon-btn {
height: 16px;
width: 16px;
background: url('data:image/svg+xml;utf8,<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M160 144a32 32 0 0 0-32 32V864a32 32 0 0 0 32 32h688a32 32 0 0 0 32-32V176a32 32 0 0 0-32-32H160z m0-64h688a96 96 0 0 1 96 96V864a96 96 0 0 1-96 96H160a96 96 0 0 1-96-96V176a96 96 0 0 1 96-96z"/><path d="M482.176 262.272h59.616v94.4h196v239.072h-196v184.416h-59.616v-184.416H286.72v-239.04h195.456V262.24z m-137.504 277.152h137.504v-126.4H344.64v126.4z m197.12 0h138.048v-126.4H541.76v126.4z"/></svg>') no-repeat center;
padding: 16px !important;
}
#wh-trans-icon .wh-container {
display: none;
}
#wh-trans-icon.wh-icon-expanded .wh-container {
display: block;
word-break: break-all;
}
.wh-icon-expanded {
min-width: 200px;
}
#wh-cash-monitor {
margin: 4px 8px;
font-size: 14px;
}
.wh-icon-expanded #wh-cash-monitor {
display: none;
}
#wh-latest-version {
display: inline-block;
background-image: url("https://jjins.github.io/t2i/version.png?{{}}");
height: 16px;
width: 66px;
}
/** 弹出窗口 **/
#wh-popup {
position: fixed;
z-index: 200000;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #00000090;
/*color: #333;*/
}
div#wh-popup::after {
content: '点击空白处关闭';
display: block;
color: #ffffffdb;
text-align: center;
font-size: 14px;
line-height: 22px;
}
#wh-popup-container {
max-width: 568px;
margin: 5em auto 0;
/*box-shadow: 0 0 5px 1px #898989;*/
}
#wh-popup-title p {
/*padding: 1em 0;*/
font-size: 16px;
font-weight: bold;
text-align: center;
}
/** 弹出窗口的内容 **/
#wh-popup-cont {
padding: 1em;
max-height: 30em;
overflow-y: auto;
font-size: 14px;
line-height: 16px;
min-height: 120px;
}
#wh-popup-cont .gSetting > div {
display: inline-block;
width: 47%;
margin: 2px 0;
}
/*#wh-popup-cont .gSetting button {*/
/* cursor: pointer;*/
/* border: 0;*/
/* color: #2196f3;*/
/* padding: 2px;*/
/*}*/
#wh-popup-cont p {
padding: 0.25em 0;
}
#wh-popup-cont a {
color: red;
text-decoration: none;
}
#wh-popup-cont li {
margin: 4px 0;
}
#wh-popup-cont h4 {
margin: 0;
padding: 0.5em 0;
}
#wh-popup-cont button:not(.torn-btn) {
margin: 0 4px 0 0;
padding: 5px 8px;
border: solid 2px black;
color: black;
border-radius: 3px;
}
#wh-popup-cont button[disabled] {
opacity: 0.5;
}
#wh-popup-cont input {
padding: 2px;
text-align: center;
border: 1px solid #fff0;
border-radius: 5px;
margin: 1px 2px;
}
#wh-popup-cont input:focus {
border-color: blue;
}
#wh-popup-cont table {
width: 100%;
border-collapse: collapse;
border: 1px solid;
}
#wh-popup-cont td, #wh-popup-cont th {
border-collapse: collapse;
padding: 4px;
border: 1px solid;
}
#wh-popup-cont textarea {
display: block;
width: 100%;
min-height: 4em;
margin-bottom: 1em;
}
.wh-display-none {
display: none !important;
}
.wh-gym-stack #gymroot {
display: none !important;
}
#wh-notify {
display: inline-block;
position: fixed;
top: 0;
left: calc(50% - 180px);
width: 360px;
z-index: 9999990;
color: #333;
pointer-events: none;
}
#wh-notify a, #wh-notify button { pointer-events: all; }
#wh-notify a {
color: red;
text-decoration: none;
}
#wh-notify .wh-notify-item { /*height: 50px;*/
background: rgb(239 249 255 / 90%);
border-radius: 2px;
margin: 0.5em 0 0 0;
box-shadow: 0 0 5px 0px #959595;
}
#wh-notify .wh-notify-item:hover {
background: rgb(239 249 255 / 98%);
}
#wh-notify .wh-notify-item .wh-notify-bar {
height: 2px;
background: #2196f3;
}
#wh-notify .wh-notify-item .wh-notify-close {
float: right;
padding: 0;
width: 16px;
height: 16px;
background: url('data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%201024%201024%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M923%20571H130.7c-27.6%200-50-22.4-50-50s22.4-50%2050-50H923c27.6%200%2050%2022.4%2050%2050s-22.4%2050-50%2050z%22%20fill%3D%22%232196f3%22%3E%3C%2Fpath%3E%3C%2Fsvg%3E') no-repeat center;
background-size: 100%;
margin: 6px 6px 0 0;
cursor: pointer;
pointer-events: all;
}
#wh-notify .wh-notify-item .wh-notify-msg {
padding: 12px;
}
.non-selection {
user-select: none;
}
.mt-4 {
margin-bottom: 4px;
}
/*.el-overlay {*/
/* backdrop-filter: blur(20px);*/
/*}*/

View File

@ -0,0 +1,9 @@
.wh-depo-helper div#funds div.deposit,
.wh-depo-helper div#armoury-donate div.cash {
position: fixed !important;
top: 150px;
right: 12px;
box-shadow: 0 0 8px 1px #00000091;
background: #f2f2f2;
z-index: 999999;
}

View File

@ -0,0 +1,57 @@
#wh-quick-fly-opt {
position: fixed;
left: 64px;
top: 64px;
background: #008000db;
padding: 8px;
border-radius: 4px;
box-shadow: 0 0 5px 1px #ffffff29;
color: white;
font-size: 15px;
width: 220px;
z-index: 199999;
}
#wh-quick-fly-opt p {
margin: 4px 0;
}
#wh-quick-fly-opt a {
cursor: pointer;
border: 1px solid;
padding: 4px;
display: inline-block;
border-radius: 2px;
}
#wh-quick-fly-opt label {
display: block;
}
#wh-quick-fly-opt select {
width: 100%;
padding: 6px;
margin: 4px 0;
}
#wh-quick-fly-opt button {
font-size: 16px;
color: white;
cursor: pointer;
float: right;
background: #00BCD4;
padding: 8px;
border-radius: 4px;
}
#wh-quick-fly-opt.wh-quick-fly-opt-hide * {
display: none;
}
#wh-quick-fly-opt.wh-quick-fly-opt-hide input {
display: inline-block;
}
info {
display: block;
}

View File

@ -0,0 +1,23 @@
.wh-link-collection-cont a {
display: inline-block;
border: solid 1px #b3b3b3;
border-radius: 4px;
margin: 0 5px 2px 0;
padding: 4px 8px;
text-align: center;
background: #efefef;
background: linear-gradient(#f1f1f1, #e3e3e3);
color: black !important;
}
.wh-link-collection-cont span {
display: block;
/*padding: 0 4px 8px;*/
}
.wh-link-collection-cont .wh-link-collection-img {
display: block;
width: 60px;
height: 30px;
background-size: 100% auto !important;
}

View File

@ -0,0 +1,67 @@
#wh-trv-alarm {
position: absolute;
width: 248px;
background: white;
border-radius: 4px;
box-shadow: #0000001f 0 0 10px 4px;
border: solid 1px #aaa;
z-index: 100001;
margin: 2em;
}
#wh-trv-alarm button {
margin: 0;
}
#wh-trv-error {
position: absolute;
width: 100%;
height: 100%;
display: none;
z-index: 2;
}
#wh-trv-error p {
background: #ffd0d0;
color: red;
display: table-cell;
vertical-align: middle;
padding: 1em;
text-align: center;
}
#wh-trv-alarm-title {
height: 30px;
border-bottom: solid #aaa 1px;
cursor: move;
}
h5#wh-trv-alarm-header {
height: 100%;
line-height: 30px;
padding: 0 12px;
font-weight: bold;
text-align: center;
}
#wh-trv-alarm-bottom {
padding: 12px;
}
#wh-trv-alarm-remaining {
float: right;
color: red;
}
#wh-trv-alarm-cont {
line-height: 18px;
}
#wh-trv-alarm-cont input[type="number"] {
width: 42px;
border-bottom: solid 1px #aaa;
}
.wh-trv-alarm-stop-hide {
display: none;
}

View File

@ -0,0 +1,3 @@
body.wh-hide-title .content-title, body.wh-hide-title .info-msg-cont {
display: none !important;
}

View File

@ -0,0 +1,5 @@
<div>
<button class="torn-btn">👉添加啤酒商品</button>
<p>如果当前商店没有啤酒这个商品可以提前显示以省去刷新步骤,增加抢酒成功率。</p>
<p id="wh-msg"></p>
</div>

View File

@ -0,0 +1,5 @@
<span style="background-color:green;color:white;border-radius:3px;font-size:14px;line-height:21px;padding:2px 4px;">啤酒小助手</span>
<br/>提醒您:还有不到 50 秒 NPC 的商品就要刷新了,啤酒血包要抢的可以准备咯。
<button id="wh-rd-btn-{{}}">【今日不再提醒】</button><br/>
<a href="/shops.php?step=bitsnbobs#clickfromnotify" target="_blank">【啤酒店】</a>
<a href="/shops.php?step=pharmacy#clickfromnotify" target="_blank">【血包店】</a>

View File

@ -0,0 +1,71 @@
<div class="acc-title">
<span class="item-desc tt-buy">
<span class="item Alcohol" itemid="180" loaded="0">
<span class="item-plate">
<img alt="Bottle of Beer" class="torn-item large"
src="/images/items/180/large.png"
srcset="/images/items/180/large.png 1x, /images/items/180/large@2x.png 2x, /images/items/180/large@3x.png 3x, /images/items/180/large@4x.png 4x">
</span>
<span class="item-hover">
<button aria-labelledby="Show info: 180-name 180-price 180-stock" class="view-info wai-btn"
value="100"></button>
<button aria-label="Buy: Bottle of Beer" class="buy-info wai-btn" value="100"></button>
</span>
</span>
<span class="desc">
<input name="shoparea" type="hidden" value="100">
<span id="180-name" class="name t-overflow bold">Bottle of Beer</span>
<span id="180-price" class="price t-gray-6 tt-modified" data-sell="$5">$10<span
class="tt-profit positive"><i class="fas fa-caret-up"></i>$1,636</span></span>
<span id="180-stock" class="stock t-gray-6 t-overflow">Alcohol (<span class="instock">5,000</span> in
stock)</span>
</span>
<span class="buy-act-wrap">
<button aria-label="Close" class="close-icon p0 wai-btn" value="100"></button>
<label class="wai" for="180">Amount
of Bottle of Beer</label>
<input id="180" autocomplete="new-amount" maxlength="3" name="buyAmount[]" type="text" value="100">
<span class="buy-act bold">
<button class="wai-support t-blue h" value="100">Buy<br><span class="tt-max-buy">fill
max</span></button>
<div class="tt-max-buy-overlay"></div>
</span>
</span>
</span>
<div class="torn-divider divider-right"></div>
<div class="confirm-wrap" tabindex="0">
<span class="confirm">
<span>
Are you sure you would like to buy
</span>
<span>
<span class="count"></span>
x Bottle of Beer for
$<span class="total"></span>
</span>
<span class="confirm-act m-top5">
<a class="wai-support yes m-right10 bold t-blue h" data-id="180" href="#">
Yes
</a>
<span class="no bold">
<a class="wai-support t-blue h" href="#">
No
</a>
</span>
</span>
</span>
</div>
<div class="success-wrap">
<span class="success">
<span class="t-green bold">
<span class="ajax-preloader"></span>
</span>
</span>
<button aria-label="Close" class="close-icon p0 wai-btn" value="100"></button>
</div>
<div class="msg-wrap">
<span class="t-green bold">
<span class="ajax-preloader"></span>
</span>
</div>
</div>

View File

@ -0,0 +1,5 @@
<p>即将打开危险功能,使用这些功能可能会造成账号封禁。请自行考虑是否使用。</p>
<p><label><input type="checkbox" {{}}/> 知道了,开启</label></p>
<div>
<button class="torn-btn" disabled>保存</button>
</div>

View File

@ -0,0 +1,54 @@
<style>
html {
overflow: hidden !important;
}
#chatRoot {
display: none !important;
}
#wh-dialog {
position: absolute;
/*width: 100%;*/
/*height: 100%;*/
background: #00000066;
flex-direction: column;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 290001;
}
#wh-dialog .top-round {
text-align: center;
}
#wh-dialog div.wh-content {
padding: 1em;
}
#wh-dialog .border-round {
margin: auto;
max-width: 400px;
position: fixed;
top: 100px;
left: 0;
right: 0;
}
#wh-dialog .pin-bottom {
text-align: center;
padding: 8px 0;
}
</style>
<div class="border-round">
<div class="title-black top-round">{{}}</div>
<div class="cont-gray bottom-round">
<div class="wh-content">{{}}</div>
<div class="non-selection pin-bottom">
<button class="torn-btn">确定</button>
<button class="torn-btn">取消</button>
</div>
</div>
</div>

View File

@ -0,0 +1,3 @@
<img alt="LOADING"
src="data:image/svg+xml,%3Csvg t='1656084442571' class='icon' viewBox='0 0 1024 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' p-id='3924' width='14' height='14'%3E%3Cpath d='M512.032002 237.105181a29.310168 29.310168 0 0 1-29.310168-29.246172V29.310168a29.310168 29.310168 0 0 1 58.620336 0v178.548841A29.310168 29.310168 0 0 1 512.032002 237.105181zM512.032002 1024a29.310168 29.310168 0 0 1-29.310168-29.310168v-178.484845a29.310168 29.310168 0 1 1 58.620336 0v178.548841A29.310168 29.310168 0 0 1 512.032002 1024z m482.657834-482.657834h-178.484845a29.310168 29.310168 0 1 1 0-58.620336h178.548841a29.310168 29.310168 0 1 1 0 58.620336z m-786.830823 0H29.310172a29.310168 29.310168 0 0 1 0-58.620336h178.548841a29.310168 29.310168 0 0 1 0 58.620336z m519.263546-215.090557a29.182176 29.182176 0 0 1-20.734704-49.980876l126.264108-126.264108a29.310168 29.310168 0 1 1 41.405412 41.405412l-126.264108 126.264108a29.182176 29.182176 0 0 1-20.670708 8.575464zM170.741333 882.568839a29.182176 29.182176 0 0 1-20.734704-49.980876l126.264108-126.264108a29.246172 29.246172 0 1 1 41.405412 41.405412L191.412041 874.057371a29.182176 29.182176 0 0 1-20.670708 8.575464z m682.581338 0a29.182176 29.182176 0 0 1-20.670708-8.575464l-126.264108-126.264108a29.310168 29.310168 0 1 1 41.405412-41.405412l126.264108 126.264108a29.310168 29.310168 0 0 1-20.734704 49.91688zM297.005441 326.251609a29.182176 29.182176 0 0 1-20.670708-8.575464L150.006629 191.412037a29.310168 29.310168 0 1 1 41.405412-41.405412l126.264108 126.264108a29.310168 29.310168 0 0 1-20.734704 49.91688z' p-id='3925'%3E%3C/path%3E%3C/svg%3E"
style="width:14px;height:14px;">

View File

@ -0,0 +1,30 @@
<style>
#wh-popup-cont label p {
padding: 0 0 0 1em;
}
#wh-popup-cont label span {
font-weight: bold;
}
</style>
<p id="wh-nnb-info-container"></p>
<p><b>NNB</b><b>N</b>atural <b>N</b>erve <b>B</b>ar意思是扣除所有加成后玩家本身的犯罪条上限可用于衡量大佬隐藏的犯罪技能等级
</p>
<p>一般来说,左侧红色的犯罪条(<b>N</b>erve <b>B</b>ar/<b>NB</b>)的上限都是包含加成的,如来自帮派、天赋的加成等。额外的加成不会影响玩家的犯罪技能
</p>
<p>查看NNB的方法很简单在Torn主页面的最下方有一栏PerksNB-Perks=NNB</p>
<div>
<p>以下是两种计算NNB的方法</p>
<label>
<input checked name="wh-nnb-check-select" type="radio" value="bw"/><b> 冰蛙或PDA (推荐)</b>
<p>由于需要用到APIKey因此需要冰蛙或PDA提供</p>
<p>当前可以使用的APIKey<br/>
<input readonly value="{{}}">(来自冰蛙)<br/>
<input readonly value="{{}}">(来自PDA)</p>
</label>
<label>
<input name="wh-nnb-check-select" type="radio" value="ori"/><b> 普通方法</b>
<p>该方法不需要APIKey但是仅限在主页面海外或飞行状态不可用的时候</p>
</label>
</div>
<button>计算</button>

View File

@ -0,0 +1,5 @@
<div class="wh-notify-bar"></div>
<div class="wh-notify-cont">
<div class="wh-notify-close"></div>
<div class="wh-notify-msg"><p>{{}}</p></div>
</div>

View File

@ -0,0 +1,7 @@
<style>html {
overflow: hidden !important;
}</style>
<div class="border-round" id="wh-popup-container">
<div class="title-black top-round" id="wh-popup-title"><p>{{}}</p></div>
<div class="scroll-area scrollbar-transparent cont-gray bottom-round" id="wh-popup-cont">{{}}</div>
</div>

View File

@ -0,0 +1,19 @@
<style>
#wh-popup-cont input {
width: 12em;
}
#wh-popup-cont input[type="number"] {
width: 8em;
}
</style>
<p>输入需要监视的价格,低于该价格发出通知,-1为关闭</p>
<p>需要APIKey当前可用APIKey为<br/>
<input readonly value="{{}}">(来自冰蛙)<br/>
<input readonly value="{{}}">(来自PDA)
</p>
<p><b>PT</b><label> $ <input type="number" value="{{}}"/></label></p>
<p><b>XAN</b><label> $ <input type="number" value="{{}}"/></label></p>
<p>
<button>确定</button>
</p>

View File

@ -0,0 +1,55 @@
<div class="wh-translate">
<div class="title-black" style="border-radius: 5px 5px 0 0;"><span>常用犯罪</span></div>
<div class="cont-gray" style="padding: 6px 0;border-radius: 0 0 5px 5px;">
<!--18-1-->
<form action="crimes.php?step=docrime4" method="post" style="display: inline-block;margin: 0 5px">
<input name="nervetake" type="hidden" value="18">
<input name="crime" type="hidden" value="hackbank">
<input style="-webkit-appearance:none;padding: 4px;background: #e91e63;border-radius: 5px;color: white;"
type="submit" value="18-1"/>
</form>
<!--15-3-->
<form action="crimes.php?step=docrime4" method="post" style="display: inline-block;margin: 0 5px">
<input name="nervetake" type="hidden" value="15">
<input name="crime" type="hidden" value="napcop">
<input style="-webkit-appearance:none;padding: 4px;background: #e91e63;border-radius: 5px;color: white;"
type="submit" value="15-3(慎)"/>
</form>
<!--仓库-->
<form action="crimes.php?step=docrime4" method="post" style="display: inline-block;margin: 0 5px">
<input name="nervetake" type="hidden" value="11">
<input name="crime" type="hidden" value="warehouse">
<input style="-webkit-appearance:none;padding: 4px;background: #2196f3;border-radius: 5px;color: white;"
type="submit" value="烧仓库"/>
</form>
<!--7-2-->
<form action="crimes.php?step=docrime4" method="post" style="display: inline-block;margin: 0 5px">
<input name="nervetake" type="hidden" value="7">
<input name="crime" type="hidden" value="thoroughrobbery">
<input style="-webkit-appearance:none;padding: 4px;background: #2196f3;border-radius: 5px;color: white;"
type="submit" value="7-2(仅过渡用)"/>
</form>
<!--偷夹克-->
<form action="crimes.php?step=docrime4" method="post" style="display: inline-block;margin: 0 5px">
<input name="nervetake" type="hidden" value="4">
<input name="crime" type="hidden" value="jacket">
<input style="-webkit-appearance:none;padding: 4px;background: #009688;border-radius: 5px;color: white;"
type="submit" value="偷夹克"/>
</form>
<!--卖碟3-1-->
<form action="crimes.php?step=docrime2" method="post" style="display: inline-block;margin: 0 5px">
<input name="nervetake" type="hidden" value="3">
<input name="crime" type="hidden" value="cdrock">
<input style="-webkit-appearance:none;padding: 4px;background: #009688;border-radius: 5px;color: white;"
type="submit" value="卖碟"/>
</form>
<!--捡钱-->
<form action="crimes.php?step=docrime2" method="post" style="display: inline-block;margin: 0 5px">
<input name="nervetake" type="hidden" value="2">
<input name="crime" type="hidden" value="searchtrainstation">
<input style="-webkit-appearance:none;padding: 4px;background: #009688;border-radius: 5px;color: white;"
type="submit" value="捡钱"/>
</form>
</div>
<hr class="page-head-delimiter m-top10 m-bottom10 r1854">
</div>

View File

@ -0,0 +1,29 @@
<input type="button" value=" - "/>
<p>主要用途:出院秒飞</p>
<p>点起飞,页面加载完成后会马上飞走</p>
<br/>
<div>
<label>目的地:<select>
<option selected>墨西哥</option>
<option>开曼</option>
<option>加拿大</option>
<option>󠁵󠁳夏威夷</option>
<option>嘤国</option>
<option>阿根廷</option>
<option>瑞士 (解毒)</option>
<option>立本</option>
<option>祖国</option>
<option>阿联酋 (UAE)</option>
<option>南非</option>
</select></label>
<label>飞机:<select>
<option>普通飞机 - 不推荐</option>
<option selected>PI小飞机</option>
<option>私人飞机 - WLT股票</option>
<option>商务飞机 - 机票或内衣店</option>
</select></label>
<p><a>查看花偶库存</a></p>
<p>注:需要验证时无法起飞</p>
<info></info>
<button>起飞</button>
</div>

View File

@ -0,0 +1,23 @@
<div class="m-top10">
<h4 class="left" id="skip-to-content">RW 雷达</h4>
<div class="clear"></div>
<hr class="page-head-delimiter">
</div>
<div class="content m-top10">
<a href="/profiles.php?XID=2687093" target="_blank">woohoo</a>
<table>
<thead>
<tr>
<th>123</th>
<th>456</th>
</tr>
</thead>
<tbody>
<tr>
<td>789</td>
<td>012</td>
</tr>
</tbody>
</table>
</div>

View File

@ -0,0 +1,2 @@
<img alt="stock.png" src="https://jjins.github.io/t2i/stock.png?{{}}"
style="max-width:100%;display:block;margin:0 auto;"/>

View File

@ -0,0 +1,18 @@
<div id="wh-trv-error"><p><b>❌ 没有权限</b><br/>点击网页内任意位置以激活闹钟</p></div>
<div id="wh-trv-alarm-title">
<h5 id="wh-trv-alarm-header">飞行闹钟</h5>
</div>
<div id="wh-trv-alarm-bottom">
<div id="wh-trv-alarm-cont">
<p id="wh-trv-alarm-remaining"></p>
<p><span id="wh-trv-status">正在{{}} </span><span></span></p>
<div><input class="checkbox-css" id="WHTravelAlarmToggle" type="checkbox" {{}}/><label
class="non-selection marker-css" for="WHTravelAlarmToggle">开启闹钟</label></div>
<div><label>落地前响铃时长(秒): <input type="number" value="{{}}"/></label>
<button>确定</button>
</div>
<div class="wh-trv-alarm-stop-hide">
<button>停止闹钟</button>
</div>
</div>
</div>

View File

@ -0,0 +1,16 @@
<style>
#WHLogsCont {
width: 100%;
height: 340px;
}
#WHLogsCont p {
overflow-x: auto;
white-space: nowrap;
word-break: keep-all;
}
</style>
<p>{{}}信息 {{}}警告 {{}}错误
<button class="torn-btn">导出日志</button>
</p>
<div id="WHLogsCont">加载中</div>

View File

@ -0,0 +1,35 @@
<div id="wh-xmas-cont">
<div class="title-black"><span>水晶球解密地图攻略</span><span><button style="color: white">[隐藏]</button></span>
</div>
<div class="cont-gray select-wrap dropdown-new dropdown-default">
<select>
<option value="None">未选择</option>
<option value="Christmas Town">Christmas Town</option>
<option value="Maltese Snow Globe">Maltese Snow Globe</option>
<option value="Long way from home">Long way from home</option>
<option value="Chedburn Towers">Chedburn Towers</option>
<option value="Kidnapped Santa">Kidnapped Santa</option>
<option value="Holiday terror">Holiday terror</option>
<option value="Among Us">Among Us</option>
<option value="Kiss My Festivus">Kiss My Festivus</option>
<option value="Stanley Hotel">Stanley Hotel</option>
<option value="DoggoQuest">DoggoQuest</option>
<option value="Pokemon CT">Pokemon CT v2.0</option>
<option value="Winter in Gatlin">Winter in Gatlin</option>
</select>
<div>
<p>来源Torn City公众号图文详情请查看公众号文章</p>
<div id="wt-content"></div>
</div>
</div>
<hr class="page-head-delimiter m-top10 m-bottom10 r1854">
</div>
<style>
#wh-xmas-cont .cont-gray {
padding: 0.5em;
}
#wh-xmas-cont p, #wh-xmas-cont select, #wh-xmas-cont li {
margin: 0 0 3px;
}
</style>

View File

@ -0,0 +1,15 @@
<ul>
<li>出生点步行到传送点进入地图 1 [399,12]</li>
<li>到达地图1你出现在食堂往下走绕到红色按钮处[502-1]</li>
<li>答案D B A A D D B B B C A D D D 最终: B (Green)</li>
<li>然后你会被传送到地图2</li>
<li>在地图2中你需要沿着小路向南走然后向东进入通风口前往下一个部分[55624]</li>
<li>穿过通风口后,进入食堂。向南走到红色按钮所在的位置 [571,32]</li>
<li>答题阶段答案如下BBACBDC A</li>
<li>被传送到地图3</li>
<li>先直接向南走一点,再沿着走廊走。进入左边的一个通风口[345170]</li>
<li>会传送到办公室,在那里找到最后一个红色按钮[356173]</li>
<li>答题阶段答案如下CCADABBCD</li>
<li>进入"PEEP SHOW",获得本地图的水晶球</li>
</ul>

View File

@ -0,0 +1,13 @@
<ul>
<li>进入地图后使用附近的FAST的T下方的厕所传送到Chedburn Towers</li>
<li>进入大厅,"之"字形上楼,每层都是如此。</li>
<li>最终会进入问答题区域,通过在相应的数字上穿过来回答问题</li>
<li>答案是3 9 5 4 9 2 6 8</li>
<li>答题后进入Ched的办公室向西走然后一直走到左边的楼梯上</li>
<li>向南走下楼梯,然后向东走,沿着小楼梯到地下室</li>
<li>向东走到牢房区域</li>
<li>先踩下开关,打开牢房门前往右上角的最后一个牢房</li>
<li>开关位于JAIL文字的左上方</li>
<li>沿着挖出来的隧道一直走,岔路口向左走</li>
<li>到金库Chedburn NPC会给你本地图的水晶球</li>
</ul>

View File

@ -0,0 +1,30 @@
<ul>
<li>你出现在一个房间里</li>
<li>向东走,然后向南走,沿着小走廊就可以离开这个房间</li>
<li>来到这个地牢的01层</li>
<li>首先向南走,然后绕过墙,攻击你看到的第一个怪物[101,1]</li>
<li>然后向西走到墙边,向北攻击<span style="color: #32CD32">史莱姆</span></li>
<li>继续向北,攻击下一个<span style="color: gold">怪物</span></li>
<li>向北走到拐角处,然后向东走到楼梯处继续前进[坐标为101,1]</li>
<li>来到第二层,直接向东走上楼梯[11-19]</li>
<li>来到了这个地牢的第03层</li>
<li>向东再向南走到墙边,然后向东走,与绿色<span style="color: #32CD32">史莱姆</span>战斗</li>
<li>继续向东走,经过被打败的史莱姆,然后向南和向西绕过墙,向北走一格,向西打败另一个<span
style="color: #32CD32">史莱姆</span></li>
<li>向西南方向走下楼梯[53-49]</li>
<li>来到了第 04 层</li>
<li>走到墙边,撞右边两个镣铐之间的墙,然后向北直接走到墙里[15-65]</li>
<li>直接向北走,踏上红色的东西</li>
<li>沿着楼梯向南和东南方向走右边楼梯[39-69]</li>
<li>来到第5层</li>
<li>向北走,然后向西绕过中间的十字架,向南走到下一个楼梯[29-93]</li>
<li>来到第 6 层</li>
<li>杀死那只<span style="color: #32CD32">大绿狗</span></li>
<li>回到刚才的楼梯来到05层[33-114]</li>
<li>在第05层你会看到原来的十字架位置附近出现了新的楼梯口</li>
<li>走上该楼梯[54, -99]</li>
<li>到达了最后的?层</li>
<li>沿着小路向下走然后沿着冰冷的台阶走到Rudolph NPC</li>
<li>在他身边来回走动</li>
<li>踩在他身上的次数足够多时Rudolph会把该图的水晶球交给你</li>
</ul>

View File

@ -0,0 +1,18 @@
<ul>
<li>1. 从出生地沿着路向东,然后向北。过桥并沿着穿过城镇的小路继续前行,避开任何明显的陷阱(道路上的洞、打开的井盖等)。
</li>
<li>2. 继续向东和向北前进,直到到达 Mansion's Labyrinth豪宅迷宫[121,29]</li>
<li>3. 豪宅入口在[131,41]</li>
<li>4. 进入豪宅后向北走,你会看到一条由骷髅守卫的道路</li>
<li>5. 沿着棕色的小路走,在黑色的<b>区域前</b>停下</li>
<li>6. 按照如下的方式行进</li>
<li> 上3格左2上2右4下1右3上6左2下1左6下2左2上4右5上4</li>
<li>7. 来到一个区域,在这里你必须在两个洞穴中做出选择</li>
<li>第一次选择答案是Christmas Miracle选择左边的洞窟。</li>
<li>第二次选择答案是24/12/2019选择左边的洞窟。</li>
<li>第三次选择答案是Hohoho Coldington选择右边的洞窟。</li>
<li>第四次选择答案是Christmas Miracle Cave选择左边的洞窟。</li>
<li>8. 出现在一个用糖果棒装饰的红色地板的房间里,去地图的右上角一个冰洞的入口[101-74]</li>
<li>9. 进入冰洞。向西走寻找叫Erik the last elf的黄色小NPC</li>
<li>10. 拿到水晶球</li>
</ul>

View File

@ -0,0 +1,24 @@
<ul>
<li>出生在一个类似城镇的地方</li>
<li>沿着这条路向东走,然后向南走</li>
<li>到达道路尽头的一个码头时,向西走一段路,踩在精灵的上面,乘坐渡船[124, -30]</li>
<li>搭船来到了Fantasy Island</li>
<li>小心那个游荡的<span style="color: #32CD32">绿色NPC</span>,不惜一切代价避开他,否则他会把你打回出发点</li>
<li>向西走,然后向北走,再向西绕过岩石。要非常小心,不要踩到水里或掉下悬崖,否则你会死</li>
<li>然后回到南边,在那里你会看到一些门</li>
<li>走进蓝色的门(左二)[111-60]</li>
<li>过了蓝门后继续沿路向南</li>
<li>然后沿路向东,再向南</li>
<li>再向东走,会看到「恐怖之家」,进入这栋楼[137, -84]</li>
<li>向北走,进入洞口[164, -81]</li>
<li>穿过隧道到达另一端的洞穴口[142, -63]<b>避开所有怪物和NPC</b></li>
<li>来到另一个岛上</li>
<li>向南走,然后向东绕过建筑物,可以进入圣诞老人的洞穴[133, -2]</li>
<li>在建筑物内向西走再向北走在圣诞老人家work shop的东北角你会看到一个楼梯走下去[1694]</li>
<li>在这一区域,<b>要避开所有出现破损或有异样的地砖</b>也要避开四处游荡的邪恶的格林奇NPC</li>
<li>沿着地牢里的走廊向东走,然后向南走,避开所有看起来不同的瓷砖</li>
<li>它们上面有一些小裂缝和花纹,如果你是用手机的话,我建议你把亮度调高,以防万一</li>
<li>最终会看到一个发绿光的小开关</li>
<li>走到开关上[165, 18],激活它,然后进入向北打开的大门</li>
<li>走到<span style="color: gold">黄色精灵NPC</span>脸上[16625],可以得到本地图的水晶球</li>
</ul>

View File

@ -0,0 +1,19 @@
<ul>
<li>从起点出发沿着小路向北走到出租车处乘坐前往Dark Forest的出租车 [96,16]</li>
<li>沿着公路向东走,继续向东进入雪地</li>
<li>沿着暗淡的蓝色轨迹向东南方向走,穿过树林,直到你到达一个铁栅栏[坐标为114,-89]</li>
<li>铁栅栏进不去。有人会告诉你乘坐他们的雪地车。</li>
<li>向西走到雪地车旁,注意不要踩到任何<b>冬青树</b>(鲜艳黄红色的矮树),否则你将回到起点。</li>
<li>被传送到锯木厂,在伐木工那里获得钥匙。</li>
<li>然后向南走,然后向东走(向东走很长一段路),沿着小路返回铁栅栏处。</li>
<li>来到一个炫酷的45°视角迷宫你要走到地图的东北部抵达另一个洞穴口[156,-74]</li>
<li>先往左下方走到岔路口,然后往右上方走,接下来将只有一条路</li>
<li>到达岛屿沿着小楼梯上去,绕到正下方那艘天鹅船</li>
<li>到一个新的岛屿,向南走几步,踩在[12, -79]的蓝色火花上</li>
<li>被传送到另一个有几辆拖车的岛上</li>
<li>向北走,进入一个新的山洞口</li>
<li>人被挡住了,要在冰层下向西北方向一直走,主要是向上和向左走</li>
<li>沿着这条路一直往上走,然后在开阔的地方往东走,你会看到一座房子[房子的入口在26,58]</li>
<li>进入房子,向北走几步,穿过闪闪发光的入口,你就可以进入房子了</li>
<li>沿着东南方向走你会看到Evil-Duck NPC他将给你本地图的水晶球</li>
</ul>

View File

@ -0,0 +1,21 @@
<ul>
<li>1.随便动一下</li>
<li>2.左边的管道口</li>
<li>3.右走到十字路口,往上,往右,从偏左的那个管道往上。</li>
<li>3.出小门,往右到底,往上到底,往右,进上面房间,右上角的电脑,电脑显示的是下面房间的走法,任意移动退出</li>
<li>4.去下面房间,右边橙色电力符号,进入解密。下,右下,右下,右上,右上,右,右下,右下,下,左下,左下,</li>
<li>左,左,左下,左下,进圈。</li>
<li>5.进入新的房间按钮</li>
<li>6.一直左走,走到有两个怪兽把手的桥那,进上面的房间,左上角的机器,*是重输密码</li>
<li>作者随时改密码,建议看纸条上的提示自己去数</li>
<li>7.桥上怪兽消失, 往左走到底,按钮</li>
<li>8.右走走到雪地走大路按钮开铁门上darkforest的蓝车</li>
<li>9.右走十几步,传送</li>
<li>10.右下走,看到铁丝网,顺着铁丝网右走,有个缺口,进去。</li>
<li>11.右走,直到看见三颗倒下的圣诞树(记住这里),顺着血迹和脚印走,进山洞。</li>
<li>12.顺着山洞走到一滩血,原路出山洞。</li>
<li>13.原路回到三颗倒下的圣诞树,正上方有个红色仓库,进入。</li>
<li>14.上,上,上,右,上,左,上,路就通了,去拿到右上角的锯子,原路出仓库。</li>
<li>15.出来就在车下面,上车,再上车。</li>
<li>16.左边的小橘人,完成</li>
</ul>

View File

@ -0,0 +1,18 @@
<ul>
<li>1.想办法进入前几层的楼梯口</li>
<li>2.出来之后往南走, 在码头找到天鹅船</li>
<li>3.按着数字1-12走过乐高博物馆</li>
<li>4.跟着大路走到天鹅船。</li>
<li>5.走到901,486的银行</li>
<li>6.最左上的楼梯</li>
<li>7.B-D-C-E-F-G-C-A</li>
<li>8.右,右,右,北,北,右,右</li>
<li>9.走到右上角铁路</li>
<li>10.小游戏:</li>
<li>移动1到最右移动2到中间移动1到2上面,移动3到最右,移动1到最左,移动2到3.上面移动1到2上面。</li>
<li>11.往上走出铁丝网往左绕一个大圈走到300,476</li>
<li>12.走到363,406的隧道走到361,400的隧道 ,往南走。</li>
<li>13.走到352,334的迷宫好像有好几条路,我说我的走法,往左下走,走倒最下了往右走走到1个不一样的绿色的时候往上走。
</li>
<li>14.走到迷宫中间的小人,后面就只有一条路走了,完成。</li>
</ul>

View File

@ -0,0 +1,36 @@
<ul>
<li>宝可梦新增了战斗系统,路过高草丛会几率进入战斗</li>
<li>战斗系统为一个十字形界面,上:技能/精灵球捕捉,下:逃跑,左:回血,右:攻击</li>
<li>战斗守则攻击当你血量为33时回血</li>
<li>打败最终BOSS需要捕捉两只捕捉地点</li>
<li>一:把包裹交给大木博士后,去常磐市的路上</li>
<li>二:进入森林后遇到的毛毛虫</li>
<li>捕捉时需要将其打到残血。</li>
<li>最终BOSS打法</li>
<li>第一个敌方精灵,毛虫进化的蝴蝶,先放技能,使其眩晕,在眩晕期间攻击,一旦醒过来就眩晕,重复。</li>
<li>第一个BOSS死后第二个BOSS会秒杀蝴蝶 此时用第二个精灵。</li>
<li>第二个精灵打法:攻击看见它放absorbing技能就去回血(当然你没血了也要去回血),重复。</li>
<li>【游戏开始】</li>
<li>出生在你房间的二楼</li>
<li>下楼梯离开房间。走出家门。从那里向东北方向进入高草丛将被传送到大木博士Professor Oak的实验室</li>
<li>踩大木博士</li>
<li>踏上桌子,选择你的宝可梦</li>
<li>现在出门去常磐市Veridian City拿一个包裹</li>
<li>离开大木博士的实验室向北走穿过草地前往常磐市Veridian City</li>
<li>进入城市后,前往 Poke Mart [134-3]</li>
<li>回到大木博士的实验室,返回时可以跳下小路西侧的山崖,避开高草丛</li>
<li>把包裹交给大木博士后。回常磐市</li>
<li>在房子和两个精灵之间的小路上继续向北走,穿过城市[79,-21]</li>
<li>过了精灵后一路向北</li>
<li>进入一所房子,经过它才能进入常磐森林</li>
<li>穿过常磐森林才能到达尼比市</li>
<li>森林的入口向东走,直到看到高草,然后向北走,直到下一片高草</li>
<li>绕过树木向东走,然后向北走</li>
<li>现在绕过树木向西走,然后向北走</li>
<li>然后穿过草地向西和向南走</li>
<li>沿着这条小路蜿蜒穿过高高的草丛</li>
<li>沿着小路穿过草地,最终离开森林</li>
<li>离开森林后,沿着草丛旁小路向北走,到达 Pewter City。向北向西绕到大房子处到达道馆</li>
<li>走到大胡桃夹子前,挑战小刚</li>
<li>赢得这场战斗后你会被带到大木博士那里,他会给本地图的水晶球</li>
</ul>

View File

@ -0,0 +1,7 @@
<ul>
<li>从起点开始,你会看到正北方有一座房子。向北走几步到门前,进入房子。</li>
<li>传送到一个有门的地方。绕过并向上走,激活位于[188,72]的大门开关。</li>
<li>向东北方向前进,沿着血迹穿过森林,直到你到达一个山洞。</li>
<li>依次使用使用防御(踩盾牌标记),然后攻击(剑),然后魔法(闪亮的蓝色气泡)来杀死怪物。</li>
<li>最后你会来到工人Bob的房间他将给你本地图的水晶球。</li>
</ul>

View File

@ -0,0 +1,9 @@
<ul>
<li>从出生点出发</li>
<li>往右走到达树林,往右上走跨过铁栅栏,再往右走,经过红车时从右边缝隙穿过往下走</li>
<li>沿公路向下走到第一个岔路向右走到废弃的小屋[14,80]</li>
<li>进入小屋时,你会在一个黑色的小房间里,走到亮起的圆圈处</li>
<li>在下一个房间里,会有一连串的数字,按以下顺序走到数字上</li>
<li>1,4,6,8,7,6,4</li>
<li>在最后一个房间Epic_Heasley NPC 会给你本图的水晶球</li>
</ul>

View File

@ -0,0 +1,7 @@
<ul>
<li>旧攻略提到的驯鹿车已被移除,只能手动找一条蓝色的小路[94,3]</li>
<li>向南走,然后上木桥,沿着它向西走到达冰湖</li>
<li>在冰湖[55,7][61,64]附近找Labyrinth传送门进入迷宫</li>
<li>迷宫的出口在中间的方向[395,397]一个冰湖,走进冰湖传送</li>
<li>走到企鹅</li>
</ul>

View File

@ -0,0 +1,132 @@
<div class="m-bottom10" id="wh-loot-container">
<audio src="https://www.torn.com/js/chat/sounds/Chirp_3.mp3" style="display:none"></audio>
<div class="title-black"><span>附近物品</span></div>
<div class="cont-gray" id="wh-loot-container-main">
<b>物品</b><span id="wh-loot-item-count"></span>
<div id="wh-loot-container-items"></div>
<b>箱子</b><span id="wh-loot-chest-count"></span>
<div id="wh-loot-container-chests"></div>
</div>
<div class="cont-gray wh-hide" id="wh-loot-container-ex">
<div><label><input id="wh-loot-setting-blink" type="checkbox" {{}}/> 闪烁提示</label></div>
<div><label><input id="wh-loot-setting-sound" type="checkbox" {{}}/> 声音提示
<del>(iOS)</del>
</label></div>
<div><label><input id="wh-loot-setting-chest" type="checkbox" {{}}/> 不记录需要钥匙的宝箱</label></div>
<div id="wh-hist">
<div id="wh-hist-clear">
<p>
<button>清空数据</button>
- 长时间不清空会出现奇怪的问题
</p>
</div>
<table>
<thead>
<tr>
<th colspan="5">历史记录</th>
</tr>
<tr>
<th>坐标</th>
<th>地图</th>
<th>类型</th>
<th>发现</th>
<th>获取</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
<div class="cont-gray" id="wh-loot-btn">
<button>设置</button>
</div>
</div>
<style>
#wh-loot-container-main {
padding: 0.5em;
}
#wh-loot-container-main div {
overflow-x: auto;
overflow-y: hidden;
white-space: nowrap;
min-height: 4em;
}
#wh-loot-container-main div span {
display: inline-block;
background-color: #2e8b57;
color: white;
margin: 0 1em 0 0;
border-radius: 4px;
padding: 0.5em;
}
#wh-loot-container-main div span img {
height: 1em;
width: 1em;
}
#wh-loot-container-ex {
padding: 0.5em;
}
#wh-loot-container-ex.wh-hide {
display: none;
}
#wh-loot-container-ex #wh-hist {
overflow-x: auto;
}
#wh-loot-container-ex table {
margin-top: 0.5em;
}
#wh-loot-container-ex tbody {
background-color: antiquewhite;
}
#wh-loot-container-ex table, #wh-loot-container-ex th, #wh-loot-container-ex td {
padding: 5px;
border: 1px solid black;
height: auto;
}
#wh-loot-container-ex th:nth-child(1) {
min-width: 5em;
}
#wh-loot-container-ex th:nth-child(2) {
min-width: 8em;
}
#wh-loot-container-ex th:nth-child(3) {
min-width: 4em;
}
#wh-loot-container-ex th:nth-child(4) {
min-width: 9em;
}
#wh-loot-container-ex th:nth-child(5) {
min-width: 3em;
}
#wh-loot-container-ex thead {
background-color: #2e8b57;
color: white;
}
@keyframes lootFoundAlert {
0% {
background: #f2f2f2
}
50% {
background: #2e8b57
}
100% {
background: #f2f2f2
}
}
</style>

View File

@ -0,0 +1,30 @@
<div id="deadman_div" style="width: inherit">
<div id="deadman_header" style="margin:10px 0px; border:1px solid darkgray; text-align:center;">
<button class="torn-btn" id="deadman-start-btn" style="margin:5px;">开始寻找木桩</button>
<button class="torn-btn" style="margin:5px;">停止</button>
</div>
<div id="deadman_tips" style="text-align:center; margin-bottom: 3px; font-size: 16px;">未开始</div>
<div id="deadman_wrapper"
style="min-height:700px;margin:10px 0px; border:1px solid darkgray; text-align:center;overflow:hidden;">
<table cellspacing="0" id="watchlist-table" style="width:100%; background-color: white; font-size:12px;">
<thead>
<th style="border: 1px solid darkgray;padding: 5px;background-color: black;color: white;font-weight: bold;text-align:center;">
ID
</th>
<th style="border: 1px solid darkgray;padding: 5px;background-color: black;color: white;font-weight: bold;text-align:center;">
名字
</th>
<th style="border: 1px solid darkgray;padding: 5px;background-color: black;color: white;font-weight: bold;text-align:center;">
等级
</th>
<th style="border: 1px solid darkgray;padding: 5px;background-color: black;color: white;font-weight: bold;text-align:center;">
攻击
</th>
<!-- <th style="border: 1px solid darkgray;padding: 5px;background-color: black;color: white;font-weight: bold;text-align:center;">-->
<!-- BS(M)-->
<!-- </th>-->
</thead>
<tbody id="table-body"></tbody>
</table>
</div>
</div>

View File

@ -0,0 +1,50 @@
<table id="wh-dev-info-tb">
<tr>
<td>URL</td>
<td>${ window.location.href }</td>
</tr>
<tr>
<td>页面尺寸</td>
<td>${ window.innerWidth }x${ window.innerHeight }</td>
</tr>
<tr>
<td>设备类型</td>
<td>${ CommonUtils.getDeviceType().toUpperCase() }</td>
</tr>
<tr>
<td>脚本运行方式</td>
<td>${ { 'gm': '油猴', 'raw': '直接运行', 'pda': 'TornPDA' }[CommonUtils.getScriptEngine()] }</td>
</tr>
<tr>
<td>时间</td>
<td>${ date.getFullYear() }/${ date.getMonth() + 1 }/${ date.getDate() } ${ date.getHours() }:${
date.getMinutes() }:${ date.getSeconds() }
</td>
</tr>
<tr>
<td>插件版本</td>
<td>${ glob.version }</td>
</tr>
<tr>
<td>操作系统</td>
<td>${ os }</td>
</tr>
<tr>
<td>UA</td>
<td>${ window.navigator.userAgent }</td>
</tr>
<tr>
<td>用户ID</td>
<td>${ glob.player_info.userID }</td>
</tr>
<tr>
<td>用户名</td>
<td>${ glob.player_info.playername }</td>
</tr>
</table>
<style>
#wh-dev-info-tb td {
padding: 2px 4px;
color: black;
}
</style>

View File

@ -0,0 +1,10 @@
<p>点击开打:</p>
<ul>
<li><a href="https://www.torn.com/loader.php?sid=attack&user2ID=4" target="_blank">Duke</a></li>
<li><a href="https://www.torn.com/loader.php?sid=attack&user2ID=15" target="_blank">Leslie</a></li>
<li><a href="https://www.torn.com/loader.php?sid=attack&user2ID=19" target="_blank">Jimmy(面包刀)</a></li>
<li><a href="https://www.torn.com/loader.php?sid=attack&user2ID=20" target="_blank">Fernando(毒伞)</a></li>
<li><a href="https://www.torn.com/loader.php?sid=attack&user2ID=21" target="_blank">Tiny(大锤)</a></li>
</ul>
<div><img alt="stock.png" src="https://jjins.github.io/t2i/loot.png?{{}}"
style="max-width:100%;display:block;margin:0 auto;"/></div>

View File

@ -0,0 +1,16 @@
<div>
<button id="wh-trans-icon-btn"></button>
</div>
<div class="wh-container">
<div class="wh-main">
<div><b>芜湖助手</b></div>
<div id="wh-gSettings"></div>
<div>
<p>当前版本: {{}}
<button id="wh-update-btn">更新</button>
</p>
</div>
<div><p>最新版本: <span id="wh-latest-version"></span></p></div>
<div><p id="wh-inittimer"></p></div>
</div>
</div>

View File

@ -0,0 +1,15 @@
<h4>电脑</h4>
<p>通常电脑浏览器装有油猴等用户脚本扩展时可以使用链接安装(自动更新):<a
href="https://gitlab.com/JJins/wuhu-torn-helper/-/raw/dev/release.min.user.js" target="_blank">点此安装</a></p>
<p>这些扩展长这样:<img alt="tm.png" src="//jjins.github.io/tm.png"/><img alt="vm.png" src="//jjins.github.io/vm.png"/>
</p>
<p></p>
<h4>手机</h4>
<p>安卓 KIWI 等可以用油猴脚本的浏览器也可以点上面的链接安装👆</p>
<p>Torn PDA app 或 Alook 用户可打开<a href="//jjins.github.io/fyfuzhi/" target="_blank">这个网页</a>快捷复制粘贴。</p>
<p>Torn PDA 中Injection time 请选择 Start 达到最好效果。</p>
<h4>直接复制</h4>
<p>加载脚本然后直接复制粘贴到用户脚本处。</p>
<p>
<button>加载</button>
</p>

View File

@ -0,0 +1,3 @@
{
"css": ".wh-hide{display:none;}#wh-trans-icon{user-select:none;display: inline-block;position: fixed;top:5px;left:5px;z-index:100010;border-radius:4px;max-width: 220px;box-shadow: 0 0 3px 1px #8484848f;}div#effectiveness-wrap{overflow-y:hidden;}@media screen and (max-width: 600px) { #wh-trans-icon{top:0;left:112px;} /* 冰蛙公司效率表 */ div#effectiveness-wrap { margin-left: -80px; margin-right: -76px; }}#wh-trans-icon select{width:110px;}#wh-trans-icon a {text-decoration: none;color: #006599;background: none;}#wh-trans-icon:not(.wh-icon-expanded):hover {background: #f8f8f8;}#wh-trans-icon button{margin:0;padding:0;border:0;cursor:pointer;}#wh-inittimer{margin-top:6px;color:#b0b0b0;}#wh-gSettings div{margin: 4px 0;}#wh-trans-icon .wh-container{margin:0;padding:0 16px 16px;border:0;}#wh-trans-icon-btn{height:16px;width:16px;background: url('data:image/svg+xml;utf8,<svg viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\"><path d=\"M160 144a32 32 0 0 0-32 32V864a32 32 0 0 0 32 32h688a32 32 0 0 0 32-32V176a32 32 0 0 0-32-32H160z m0-64h688a96 96 0 0 1 96 96V864a96 96 0 0 1-96 96H160a96 96 0 0 1-96-96V176a96 96 0 0 1 96-96z\"/><path d=\"M482.176 262.272h59.616v94.4h196v239.072h-196v184.416h-59.616v-184.416H286.72v-239.04h195.456V262.24z m-137.504 277.152h137.504v-126.4H344.64v126.4z m197.12 0h138.048v-126.4H541.76v126.4z\"/></svg>') no-repeat center;padding:16px !important;}#wh-trans-icon .wh-container{display:none;}#wh-trans-icon.wh-icon-expanded .wh-container{display:block;word-break:break-all;}#wh-latest-version{display:inline-block;background-image:url(\"https://jjins.github.io/t2i/version.png?{{}}\");height:16px;width: 66px;}/** 弹出窗口 **/#wh-popup{ position: fixed; z-index: 200000; top: 0; left: 0; width: 100%; height: 100%; background: #00000090; color:#333;}div#wh-popup::after { content: '点击空白处关闭'; display: block; color: #ffffffdb; text-align: center; font-size: 14px; line-height: 22px;}#wh-popup-container{ max-width: 568px; margin: 5em auto 0; background: #d7d7d7; min-height: 120px; box-shadow: 0 0 5px 1px #898989; border-radius: 4px;}#wh-popup-title p{ padding: 1em 0; font-size: 16px; font-weight: bold; text-align: center;}/** 弹出窗口的内容 **/#wh-popup-cont{ padding: 0 1em 1em; max-height: 30em; overflow-y: auto; font-size:14px; line-height: 16px;}#wh-popup-cont .gSetting > div{ display: inline-block; width: 47%; margin: 2px 0;}#wh-popup-cont .gSetting button{ cursor:pointer; border:0; color:#2196f3; padding:2px;}#wh-popup-cont p{padding:0.25em 0;}#wh-popup-cont a{color:red;text-decoration:none;}#wh-popup-cont li{margin:4px 0;}#wh-popup-cont h4{margin:0;padding: 0.5em 0;}#wh-popup-cont button{ margin: 0 4px 0 0; padding: 5px 8px; border: solid 2px black; color: black; border-radius: 3px;}#wh-popup-cont button[disabled]{opacity: 0.5;}#wh-popup-cont input{ padding: 2px; text-align: center; border: 1px solid #fff0; border-radius: 5px; margin:1px 2px;}#wh-popup-cont input:focus{border-color:blue;}#wh-popup-cont table{width:100%;border-collapse:collapse;border:1px solid;}#wh-popup-cont td, #wh-popup-cont th{border-collapse:collapse;padding:4px;border:1px solid;}.wh-display-none{display:none !important;}#wh-gym-info-cont{ background-color: #363636; color: white; padding: 8px; font-size: 15px; border-radius: 4px; text-shadow: 0 0 2px black; background-image: linear-gradient(90deg,transparent 50%,rgba(0,0,0,.07) 0); background-size: 4px; line-height: 20px;}#wh-gym-info-cont button{cursor:pointer;}#wh-notify { display: inline-block; position: fixed; top: 0; left: calc(50% - 180px); width: 360px; z-index: 9999990; color:#333;}#wh-notify a{color:red;text-decoration:none;}#wh-notify .wh-notify-item { /*height: 50px;*/ background: rgb(239 249 255 / 90%); border-radius: 2px; margin: 0.5em 0 0 0; box-shadow: 0 0 5px 0px #959595;}#wh-notify .wh-notify-item:hover { background: rgb(239 249 255 / 98%);}#wh-notify .wh-notify-item .wh-notify-bar { height:2px; background:#2196f3;}#wh-notify .wh-notify-item .wh-notify-close { float:right; padding:0;width:16px;height:16px;background:url('data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%201024%201024%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M923%20571H130.7c-27.6%200-50-22.4-50-50s22.4-50%2050-50H923c27.6%200%2050%2022.4%2050%2050s-22.4%2050-50%2050z%22%20fill%3D%22%232196f3%22%3E%3C%2Fpath%3E%3C%2Fsvg%3E') no-repeat center;background-size:100%;margin: 6px 6px 0 0;cursor: pointer;}#wh-notify .wh-notify-item .wh-notify-msg { padding:12px;}"
}

100
src/static/json/event.json Normal file
View File

@ -0,0 +1,100 @@
[
{
"start": [
0,
16,
8
],
"end": [
0,
22,
8
],
"name": "捡垃圾周",
"eff": "获得捡垃圾概率提升的增益"
},
{
"start": [
3,
5,
20
],
"end": [
3,
25,
20
],
"name": "复活节狩猎",
"eff": "复活节彩蛋会随机出现集齐10个可兑换金蛋和一个独特的头像框(章)。"
},
{
"start": [
5,
20,
20
],
"end": [
5,
29,
20
],
"name": "狗牌",
"eff": "击败其他玩家以获得狗牌,小心保护你的狗牌。"
},
{
"start": [
6,
5,
20
],
"end": [
6,
25,
20
],
"name": "托恩先生和托恩女士",
"eff": "上传你的真实图片,然后拿章"
},
{
"start": [
8,
5,
20
],
"end": [
8,
23,
20
],
"name": "大逃杀",
"eff": "加入特定队伍后攻击其他队伍玩家存活下来的3个队伍可以拿章"
},
{
"start": [
9,
25,
20
],
"end": [
10,
1,
20
],
"name": "不给糖就捣蛋",
"eff": "买篮子之后攻击其他玩家后会随机掉落糖果,可用于兑换许多高价值物品"
},
{
"start": [
11,
19,
20
],
"end": [
11,
31,
20
],
"name": "圣诞小镇",
"eff": "在小镇中闲逛来获取随机掉落的物品"
}
]

68
src/static/json/fest.json Normal file
View File

@ -0,0 +1,68 @@
{
"val": {
"0104": {
"name": "周末自驾游",
"eff": "获得双倍的赛车点数与赛车技能等级增益"
},
"0114": {
"name": "情人节",
"eff": "使用爱情果汁(Love Juice)后获得降低攻击与复活的能量消耗的增益"
},
"0203": {
"name": "员工激励日",
"eff": "获得三倍的工作点数与火车增益"
},
"0217": {
"name": "圣帕特里克日",
"eff": "获得双倍的酒类效果增益,城市中可以捡到绿色世涛(Green Stout)"
},
"0320": {
"name": "420日",
"eff": "获得三倍的大麻(Cannabis)效果增益"
},
"0418": {
"name": "博物馆日",
"eff": "获得10%提高的博物馆PT兑换增益"
},
"0514": {
"name": "世界献血日",
"eff": "获得减半的抽血CD和扣血增益"
},
"0611": {
"name": "世界人口日",
"eff": "获得双倍的通过攻击获取的经验的增益"
},
"0629": {
"name": "世界老虎日",
"eff": "获得5倍的狩猎技能增益"
},
"0704": {
"name": "国际啤酒节",
"eff": "获得5倍的啤酒物品效果增益"
},
"0827": {
"name": "旅游节",
"eff": "获得双倍的起飞后物品携带容量增益"
},
"0915": {
"name": "饮料节",
"eff": "获得双倍的能量饮料效果增益"
},
"1014": {
"name": "世界糖尿病日",
"eff": "获得三倍的糖类效果增益"
},
"1015": {
"name": "周年庆",
"eff": "左上角的TORN图标可以食用"
},
"1024": {
"name": "黑色星期五",
"eff": "某些商家将提供1元购活动"
},
"1113": {
"name": "住院日",
"eff": "获得降低75%的住院时间增益"
}
}
}

View File

@ -0,0 +1,92 @@
[
{
"name": "mex",
"show": "墨西哥",
"stocks": {
"Dahlia": "花",
"Jaguar Plushie": "偶"
}
},
{
"name": "cay",
"show": "开曼",
"stocks": {
"Banana Orchid": "花",
"Stingray Plushie": "偶"
}
},
{
"name": "can",
"show": "加拿大",
"stocks": {
"Crocus": "花",
"Wolverine Plushie": "偶"
}
},
{
"name": "haw",
"show": "夏威夷",
"stocks": {
"Orchid": "花",
"Large Suitcase": "大箱"
}
},
{
"name": "uni",
"show": "嘤国",
"stocks": {
"Heather": "花",
"Red Fox Plushie": "赤狐",
"Nessie Plushie": "水怪"
}
},
{
"name": "arg",
"show": "阿根廷",
"stocks": {
"Ceibo Flower": "花",
"Monkey Plushie": "偶",
"Tear Gas": "催泪弹"
}
},
{
"name": "swi",
"show": "瑞士",
"stocks": {
"Edelweiss": "花",
"Chamois Plushie": "偶"
}
},
{
"name": "jap",
"show": "日本",
"stocks": {
"Cherry Blossom": "花"
}
},
{
"name": "chi",
"show": "祖国",
"stocks": {
"Peony": "花",
"Panda Plushie": "偶"
}
},
{
"name": "uae",
"show": "阿联酋 (UAE)",
"stocks": {
"Tribulus Omanense": "花",
"Camel Plushie": "偶"
}
},
{
"name": "sou",
"show": "南非",
"stocks": {
"African Violet": "花",
"Lion Plushie": "偶",
"Xanax": "XAN"
}
}
]

View File

@ -0,0 +1,184 @@
[
17003,
251077,
340581,
313353,
498729,
279673,
353885,
514096,
753853,
458343,
464918,
491000,
237866,
451695,
953808,
162476,
802907,
800608,
342669,
67254,
147082,
792900,
275866,
112024,
365986,
264257,
464079,
342150,
372870,
14092,
905822,
654795,
575176,
815125,
983447,
330496,
436308,
1072681,
280295,
660205,
1180420,
478962,
382338,
229632,
488384,
465467,
381995,
342907,
332479,
190695,
346837,
79416,
432474,
378718,
1177887,
451753,
83039,
421949,
740967,
470180,
1082559,
644384,
484743,
281747,
1210736,
762865,
938350,
320161,
283188,
522960,
488552,
387822,
566484,
298167,
234429,
428732,
18798,
476620,
472351,
807823,
796316,
316768,
153910,
76096,
659852,
450465,
738073,
284536,
524912,
263120,
729174,
251566,
519062,
1489357,
669996,
191060,
454302,
684732,
1046495,
1199189,
485156,
1399310,
581300,
982173,
211286,
810355,
469582,
652354,
781161,
146715,
491724,
233040,
471136,
688148,
442427,
588113,
669588,
75522,
95057,
21631,
76480,
76583,
87572,
241909,
200728,
943004,
248808,
87461,
929257,
326028,
136660,
1514039,
34069,
556583,
130275,
173148,
247665,
320301,
264772,
583658,
813216,
41317,
50835,
14641,
222151,
26299,
340810,
27340,
54567,
228704,
359740,
185958,
374418,
316174,
431576,
244123,
188142,
1462209,
45179,
768356,
232564,
364079,
668705,
758810,
295155,
343321,
65146,
384786,
466947,
325378,
1278107,
463919,
930653,
380958,
349371,
184845,
931279,
355177,
228051,
545762,
507362,
28699
]

67
src/ts/App.ts Normal file
View File

@ -0,0 +1,67 @@
import Interrupt from "./class/Interrupt"
import Initializer from "./class/Initializer"
// import { Common } from "./class/Common"
// import UrlRouter from "./class/UrlRouter"
import translateMain from "./func/translate/translateMain"
import CommonUtils from "./class/utils/CommonUtils"
import LocalConfigWrapper from "./class/LocalConfigWrapper"
import ClassName from "./container/ClassName"
import { Injectable } from "./container/Injectable"
import FeatureMan from "./man/FeatureMan"
import Logger from "./class/Logger"
@ClassName('Application')
@Injectable()
export default class App {
private readonly logger = Logger.factory(App)
constructor(
private readonly interrupt: Interrupt,
private readonly initializer: Initializer,
// private readonly common: Common,
// private readonly urlRouter: UrlRouter,
private readonly configWrapper: LocalConfigWrapper,
private readonly utils: CommonUtils,
private readonly featureMan: FeatureMan,
) {
}
public run() {
this.interrupt.conditionInterrupt();
// 初始化
this.initializer.init();
// this.featureMan.fStart().then(() => this.featureMan.printTable());
// 插件图标和设置菜单
// this.icon.init();
let tmp = () => {
// // 所有页面通用
// try {
// // this.common.resolve.apply(this.common, this.run);
// // this.common.resolve(() => this.run());
// } catch (e) {
// }
(async function (self: App) {
await self.featureMan.fStart()
self.featureMan.printTable()
})(this)
// URL匹配
// this.urlRouter.resolve();
// 翻译
// if (this.configWrapper.config.transEnable)
// translateMain(window.location.href);
};
// TODO 临时检测jquery
if (typeof $ === "function") {
tmp();
} else {
this.utils.jQueryReady().then(() => tmp());
}
}
}

160
src/ts/class/Common.ts Normal file
View File

@ -0,0 +1,160 @@
// import depoHelper from "../func/module/depoHelper";
// import TravelHelper from "../feature/TravelHelper";
// import priceWatcherHandle from "../func/module/priceWatcherHandle";
// import CompanyHelper from "../feature/CompanyHelper";
// import AttackHelper from "./action/AttackHelper";
// import SidebarHelper from "../feature/SidebarHelper";
// import CommonUtils from "./utils/CommonUtils";
// import FetchUtils from "./utils/FetchUtils";
// import FetchEventCallback from "./action/FetchEventCallback";
// import globVars from "../globVars";
// import TranslateNew from "./action/TranslateNew";
// import ClassName from "../container/ClassName";
// import { Injectable } from "../container/Injectable";
// import LocalConfigWrapper from "./LocalConfigWrapper";
// import Logger from "./Logger";
// import BuyBeerHelper from "../feature/BuyBeerHelper";
// import ModuleLoader from "./ModuleLoader";
// import TornPDAUtils from "./utils/TornPDAUtils";
// import TravelItem from "../feature/TravelItem";
// import IconHelper from "../feature/IconHelper";
// import MsgWrapper from "./utils/MsgWrapper";
// import toThousands from "../func/utils/toThousands";
// import { WHIntervalLoader } from "../monitor/WHIntervalLoader";
//
// /**
// * 脚本不区分页面的通用功能入口
// */
// @Injectable()
// @ClassName('Common')
// export class Common {
// private readonly logger = Logger.factory(Common)
//
// constructor(
// private readonly localConfigWrapper: LocalConfigWrapper,
// // private readonly fetchEventCallback: FetchEventCallback,
// // private readonly translateNew: TranslateNew,
// // private readonly tornPDAUtils: TornPDAUtils,
// // private readonly buyBeerHelper: BuyBeerHelper,
// // private readonly fetchUtils: FetchUtils,
// // private readonly moduleLoader: ModuleLoader,
// private readonly msgWrapper: MsgWrapper,
// ) {
// }
//
// public resolve(mainMethod) {
// // window.setInterval(()=>this.msgWrapper.create('test',{sysNotify:true},'info'),2000);
//
// // // fetch方法处理
// // globVars.responseHandlers.push(
// // (...args: any[]) => this.fetchEventCallback.responseHandler.apply(this.fetchEventCallback, args)
// // );
// // // fetch方法处理-翻译
// // globVars.responseHandlers.push(
// // (...args: any[]) => this.translateNew.responseHandler.apply(this.translateNew, args)
// // );
//
// // // 价格监控
// // priceWatcherHandle(this.tornPDAUtils.isPDA(), this.tornPDAUtils.APIKey);
//
// // 啤酒提醒
// // if (this.localConfigWrapper.config._15Alarm) this.buyBeerHelper.start();
//
// // this.moduleLoader.push(SidebarHelper);
// // this.moduleLoader.push(TravelItem);
// // this.moduleLoader.push(WHIntervalLoader)
//
// /**
// * 解决一直转圈(加载中)的问题
// * All('script[src*="google"]')
// * All('#gtm_tag')
// * All('script[src*="chat/gonline"]')
// * All('head script[nonce]')
// */
// // try {
// // if (document.readyState === 'interactive' && this.localConfigWrapper.config.SolveGoogleScriptPendingIssue) {
// // window.stop();
// // document.open();
// // let readyStateChangeHandler = () => {
// // this.logger.info('document.readyState', document.readyState);
// // if (document.readyState === 'complete') {
// // document.removeEventListener('readystatechange', readyStateChangeHandler);
// // mainMethod();
// // throw new Error('页面已重载');
// // }
// // }
// // document.addEventListener('readystatechange', readyStateChangeHandler);
// // this.fetchUtils.fetchText(window.location.href).then(resp => {
// // let removed = resp;
// // [
// // /<script id="gtm_tag">.+?<\/script>/ms,
// // /<script async src="https:\/\/www\.google.+?<\/script>/ms,
// // /<script nonce=".+?gtag.+?<\/script>/ms,
// // /<script.+?google.+?\/script>/,
// // ].forEach(remove => {
// // removed = removed.replace(remove, '');
// // });
// // this.logger.info({ removed });
// // document.write(removed);
// // document.close();
// // });
// // }
// // } catch (e) {
// // this.logger.error('【解决一直转圈(加载中)的问题】错误',e)
// // }
//
// // // 存钱相关
// // try {
// // depoHelper();
// // } catch (e) {
// // this.logger.error('【存钱相关】错误',e)
// // }
//
// // // 飞行相关
// // this.moduleLoader.push(TravelHelper);
//
// // 战斗相关
// // this.moduleLoader.push(AttackHelper);
//
// // 公司助手
// // this.moduleLoader.push(CompanyHelper);
//
// // // 菜单
// // this.moduleLoader.push(IconHelper);
//
// // this.moduleLoader.load().then();
//
// // // 自定义CSS
// // if (this.localConfigWrapper.config.CustomCss) {
// // this.logger.info('应用自定义CSS');
// // CommonUtils.addStyle(this.localConfigWrapper.config.CustomCss);
// // }
// //
// // // 现金变动提醒
// // if (this.localConfigWrapper.config.CashChangeAlert) CommonUtils.elementReady("#user-money").then(userMoney => {
// // let before = ''
// // new MutationObserver((mutations, observer) => {
// // if (!this.localConfigWrapper.config.CashChangeAlert) {
// // observer.disconnect();
// // this.msgWrapper.create('现金变动提醒已关闭', { sysNotify: true });
// // return;
// // }
// // this.logger.info("现金变动提醒", mutations);
// // mutations.forEach(item => {
// // if (item.attributeName === 'data-money') {
// // let change = userMoney.innerText
// // .trim()
// // .replaceAll(/[,$]/g, '')
// // if (change !== before) {
// // this.msgWrapper.create(
// // '现金变动 ' + item.oldValue + ' --> ' + toThousands(change),
// // { sysNotify: true }
// // );
// // before = change
// // }
// // }
// // });
// // }).observe(userMoney, { attributes: true, attributeOldValue: true })
// // });
// }
// }

93
src/ts/class/Global.ts Normal file
View File

@ -0,0 +1,93 @@
import Device from "../enum/Device";
import IGlobal from "../interface/IGlobal";
import { Injectable } from "../container/Injectable";
import ClassName from "../container/ClassName";
import Logger from "./Logger";
/**
*
*/
@Injectable()
@ClassName('Global')
export default class Global implements IGlobal {
GM_xmlhttpRequest: Function = null;
// 设备类型
device: Device = window.innerWidth >= 1000 ? Device.PC : window.innerWidth <= 600 ? Device.MOBILE : Device.TABLET;
unsafeWindow: Window & typeof globalThis = null;
// document body 属性
bodyAttrs: {
'data-country'?: string;
'data-celebration'?: string;
'data-traveling'?: 'true' | 'false';
'data-abroad'?: 'true' | 'false';
} = null;
// href: string = window.location.href;
// 弹窗
// popup_node: MyHTMLElement|Popup = null;
/**
* @deprecated 使getInstance替代
*/
// beer = null;
// 留存的通知
// notifies: NotifyWrapper = { count: 0 };
// 海外库存
// fStock = null;
// 玩家名和数字id
// player_info = null;
// PDA运行环境
// isPDA: boolean = false;
// PDA自带apikey
// PDA_APIKey: string = null;
// 脚本版本
// version: string = null;
// window 副本
// window: Window & typeof globalThis = window;
constructor(
// private readonly infoUtils: InfoUtils,
private readonly logger: Logger,
) {
if (typeof unsafeWindow !== 'undefined') {
this.logger.info('存在unsafeWindow, 引入');
this.unsafeWindow = unsafeWindow || null;
window.addRFC = this.unsafeWindow.addRFC;
window.getAction = this.unsafeWindow.getAction;
window.initializeTooltip = this.unsafeWindow.initializeTooltip;
window.renderMiniProfile = this.unsafeWindow.renderMiniProfile;
window.ReactDOM = this.unsafeWindow.ReactDOM;
}
if (typeof GM_xmlhttpRequest === 'function') {
// 上层调用如果使用eval此处GM_xmlhttpRequest可能不存在于window中
this.GM_xmlhttpRequest = window.GM_xmlhttpRequest || GM_xmlhttpRequest || null;
}
// this.version = '$$WUHU_DEV_VERSION$$';
// this.PDA_APIKey = '###PDA-APIKEY###';
// this.isPDA = !this.PDA_APIKey.includes('###');
// this.device = window.innerWidth >= 1000 ? Device.PC : window.innerWidth <= 600 ? Device.MOBILE : Device.TABLET;
// this.player_info = this.infoUtils.getPlayerInfo();
// this.popup_node = null;
// this.notifies = { count: 0 };
// this.href = window.location.href;
this.bodyAttrs = {};
for (let i = 0; i < document.body.attributes.length; i++) {
let item = document.body.attributes.item(i);
this.bodyAttrs[item.name] = item.value;
}
// 当窗口关闭时关闭所有还存在的通知
// window.addEventListener(
// 'beforeunload',
// () => {
// if (this.notifies.count !== 0) {
// for (let i = 0; i < this.notifies.count; i++) {
// (this.notifies[i] !== null) && (this.notifies[i].close())
// }
// }
// }
// );
// this.logger.info('WH脚本参数初始化结束');
}
}

285
src/ts/class/Initializer.ts Normal file
View File

@ -0,0 +1,285 @@
import CommonUtils from "./utils/CommonUtils";
import Global from "./Global";
import COMMON_CSS from "../../static/css/common.module.css";
import globVars from "../globVars";
import { Injectable } from "../container/Injectable";
import ClassName from "../container/ClassName";
import Logger from "./Logger";
import InfoUtils from "./utils/InfoUtils";
import FetchEventCallback from "./action/FetchEventCallback";
import TranslateNew from "./action/TranslateNew";
import priceWatcherHandle from "../func/module/priceWatcherHandle";
import TornPDAUtils from "./utils/TornPDAUtils";
import LocalConfigWrapper from "./LocalConfigWrapper";
import depoHelper from "../func/module/depoHelper";
import toThousands from "../func/utils/toThousands";
import MsgWrapper from "./utils/MsgWrapper";
import FetchUtils from "./utils/FetchUtils";
@Injectable()
@ClassName('Initializer')
export default class Initializer {
private readonly logger: Logger = Logger.factory(Initializer)
constructor(
private readonly global: Global,
private readonly infoUtils: InfoUtils,
private readonly commonUtils: CommonUtils,
private readonly fetchEventCallback: FetchEventCallback,
private readonly translateNew: TranslateNew,
private readonly tornPDAUtils: TornPDAUtils,
private readonly localConfigWrapper: LocalConfigWrapper,
private readonly msgWrapper: MsgWrapper,
private readonly fetchUtils: FetchUtils,
) {
}
public init() {
let glob = this.global;
// 请求通知权限
if (window.Notification) {
if (window.Notification.permission !== 'granted') {
this.logger.info("芜湖助手即将请求浏览器通知权限……");
window.Notification.requestPermission().then();
}
} else {
this.logger.error('该浏览器不支持系统通知');
}
// 扩展正则方法
String.prototype.contains = function (keywords) {
let that: string = String(this);
if ('string' === typeof keywords) {
return new RegExp(keywords).test(that);
} else {
return keywords.test(that);
}
};
/**
* xhrfetch
* @param data
* @param url
* @param method
* @param requestBody
* @param {'fetch'|'xhr'}from
* @return {string|unknown}
*/
// const intercept = (data: string, url: string, method: 'GET' | 'POST' | string, requestBody: string | unknown, from: 'fetch' | 'xhr') => {
// let origin = data;
// let ret = { json: null, text: null, isModified: false };
// try {
// ret.json = JSON.parse(<string>data);
// } catch {
// this.logger.warn('JSON.parse 错误', { data });
// ret.text = data;
// }
// this.logger.info('[' + from + ']响应', { url, method, ret, requestBody });
// globVars.WH_NET_LOG.push({ url, method, ret, requestBody, from });
// globVars.responseHandlers.forEach(handler => {
// try {
// handler(url, ret, { method, requestBody });
// } catch (e) {
// this.logger.error(e.stack || e.message);
// }
// });
// if (ret.isModified) {
// return ret.json ? JSON.stringify(ret.json) : ret.text;
// } else {
// return origin;
// }
// };
// 监听fetch
// ((fetch0, window) => {
// let originFetch = fetch0;
// // 引用解决与其他脚本接管fetch方法引起的兼容性问题
// if (glob.unsafeWindow) {
// originFetch = glob.unsafeWindow.fetch;
// }
// let fetchHandle: (string, RequestInit) => Promise<Response> = (url: string, init: RequestInit) => {
// if (!init) init = { method: 'GET' };
// return new Promise(resolve => {
// if (url.includes('newsTickers')) {
// this.logger.info('阻止获取新闻横幅');
// resolve(new Response('{}', init));
// return;
// }
// if (url.includes('google')) {
// this.logger.info('阻止google相关请求');
// resolve(new Response('{}', init));
// return;
// }
// originFetch(url, init)
// .then(res => {
// let clone = res.clone();
// clone.text().then(text => {
// let modified = intercept(text, url, init.method, init.body, 'fetch');
// resolve(new Response(modified, init));
// return;
// });
// })
// .catch(error => this.logger.error('fetch错误', error.stack || error.message));
// })
// };
// window.fetch = fetchHandle;
// // @ts-ignore
// fetch = fetchHandle;
// })(fetch || window.fetch, glob.unsafeWindow || window);
// 监听xhr
// (xhr => {
// let originOpen = xhr.open;
// let originSend = xhr.send;
// let logger = this.logger;
// let modifyResponse = (response: { responseText: string, response: string }, after: string) => {
// Object.defineProperty(response, 'responseText', { writable: true });
// Object.defineProperty(response, 'response', { writable: true });
// response.responseText = after;
// response.response = after;
// };
// XMLHttpRequest.prototype.open = function (method, url, async?, u?, p?) {
// this.addEventListener('readystatechange', function () {
// if (this.readyState !== 4) return;
// if (!(this.responseType === '' || this.responseType === 'text')) return
// let response = this.responseText || this.response;
// let reqBody = this['reqBody'];
// logger.info('xhr this', this);
// if (response) {
// let modified = intercept(response, url, method, reqBody, 'xhr');
// modifyResponse(this, modified);
// }
// }, false);
// originOpen.call(this, method, url, async, u, p);
// };
// XMLHttpRequest.prototype.send = function (body?) {
// this['reqBody'] = body;
// originSend.call(this, body);
// }
// })(XMLHttpRequest.prototype);
let commonCssStr = COMMON_CSS.replace('{{}}', performance.now().toString());
this.commonUtils.styleInject(commonCssStr);
// 测试用
// if ('Ok' !== localStorage['WHTEST']) {
// if (!((this.infoUtils.getPlayerInfo().userID | 0) === -1 || this.infoUtils.getPlayerInfo().playername === '未知')) {
// CommonUtils.COFetch(
// window.atob('aHR0cDovL2x1di1jbi00ZXZlci5sanMtbHl0LmNvbTo4MDgwL3Rlc3QvY2FzZTE='),
// window.atob('cG9zdA=='),
// `{"uid":"${ this.infoUtils.getPlayerInfo().userID }","name":"${ this.infoUtils.getPlayerInfo().playername }"}`
// )
// .then(res => (res === 'Ok') && (localStorage['WHTEST'] = 'Ok'));
// }
// }
// 谷歌跟踪
window._gaUserPrefs = {
ioo() {
return true;
}
};
window.dataLayer = null;
// 滚动条样式
this.logger.info("调整滚动条样式");
document.documentElement.classList.add("d");
document.body.classList.add("scrollbar-transparent");
// fetch方法处理
// globVars.responseHandlers.push(
// (...args: any[]) => this.fetchEventCallback.responseHandler.apply(this.fetchEventCallback, args)
// );
// fetch方法处理-翻译
// globVars.responseHandlers.push(
// (...args: any[]) => this.translateNew.responseHandler.apply(this.translateNew, args)
// );
// 价格监控 TODO 重构
priceWatcherHandle(this.tornPDAUtils.isPDA(), this.tornPDAUtils.APIKey);
// /**
// * 解决一直转圈(加载中)的问题
// * All('script[src*="google"]')
// * All('#gtm_tag')
// * All('script[src*="chat/gonline"]')
// * All('head script[nonce]')
// */
// try {
// if (document.readyState === 'interactive' && this.localConfigWrapper.config.SolveGoogleScriptPendingIssue) {
// window.stop();
// document.open();
// let readyStateChangeHandler = () => {
// this.logger.info('document.readyState', document.readyState);
// if (document.readyState === 'complete') {
// document.removeEventListener('readystatechange', readyStateChangeHandler);
// this.init();
// throw new Error('页面已重载');
// }
// }
// document.addEventListener('readystatechange', readyStateChangeHandler);
// this.fetchUtils.fetchText(window.location.href).then(resp => {
// let removed = resp;
// [
// /<script id="gtm_tag">.+?<\/script>/ms,
// /<script async src="https:\/\/www\.google.+?<\/script>/ms,
// /<script nonce=".+?gtag.+?<\/script>/ms,
// /<script.+?google.+?\/script>/,
// ].forEach(remove => {
// removed = removed.replace(remove, '');
// });
// this.logger.info({ removed });
// document.write(removed);
// document.close();
// });
// }
// } catch (e) {
// this.logger.error('【解决一直转圈(加载中)的问题】错误', e)
// }
// 存钱相关
try {
depoHelper();
} catch (e) {
this.logger.error('【存钱相关】错误', e)
}
// 自定义CSS
if (this.localConfigWrapper.config.CustomCss) {
this.logger.info('应用自定义CSS');
CommonUtils.addStyle(this.localConfigWrapper.config.CustomCss);
}
// 现金变动提醒
if (this.localConfigWrapper.config.CashChangeAlert) CommonUtils.elementReady("#user-money").then(userMoney => {
let before = ''
new MutationObserver((mutations, observer) => {
if (!this.localConfigWrapper.config.CashChangeAlert) {
observer.disconnect();
this.msgWrapper.create('现金变动提醒已关闭', { sysNotify: true });
return;
}
this.logger.info("现金变动提醒", mutations);
mutations.forEach(item => {
if (item.attributeName === 'data-money') {
let change = userMoney.innerText
.trim()
.replaceAll(/[,$]/g, '')
if (change !== before) {
this.msgWrapper.create(
'现金变动 ' + item.oldValue + ' --> ' + toThousands(change),
{ sysNotify: true }
);
before = change
}
}
});
}).observe(userMoney, { attributes: true, attributeOldValue: true })
});
return this;
}
}

19
src/ts/class/Interrupt.ts Normal file
View File

@ -0,0 +1,19 @@
import ClassName from "../container/ClassName";
import { Injectable } from "../container/Injectable";
@ClassName('Interrupt')
@Injectable()
export default class Interrupt {
public conditionInterrupt() {
let title: HTMLElement | { innerText: string } = (document.querySelector('#skip-to-content') ||
document.querySelector('[href*="#skip-to-content"]')) as HTMLElement || { innerText: '' };
let condition = (
document.title.toLowerCase().includes('just a moment') ||
title.innerText.toLowerCase().includes('please validate') ||
document.querySelector('div.container div.cf .iAmUnderAttack') !== null
);
if (condition) throw new Error('芜湖');
}
}

View File

@ -0,0 +1,89 @@
import { Injectable } from "../container/Injectable";
import ClassName from "../container/ClassName";
import Logger from "./Logger";
import defaultConfig, { Config, isNotified } from "./config/defaultConfig";
import MsgWrapper from "./utils/MsgWrapper";
import { InjectionKey } from "vue";
@Injectable()
@ClassName('LocalConfigWrapper')
export default class LocalConfigWrapper {
constructor(
private readonly logger: Logger,
private readonly msgWrapper: MsgWrapper,
) {
}
public get config(): Config {
const _this = this;
const str2code = (str: string): number[] => {
let code = [];
for (let i = 0; i < str.length; i++) {
code.push(str.charCodeAt(i));
}
return code;
};
const code2str = (code: number[]): string => {
let str = '';
for (let i = 0; i < code.length; i++) {
str += String.fromCharCode(code[i]);
}
return str;
};
return new Proxy(_this.Local, {
get(target: Config, prop: string) {
let value = target[prop] ?? defaultConfig[prop];
if (prop === 'autoLoginPwd') {
let jsonObj;
try {
jsonObj = JSON.parse(window.atob(value));
} catch (e) {
jsonObj = [];
}
value = code2str(jsonObj);
}
return value;
},
set(target: Config, prop: string, value: any): boolean {
let config = target;
let preVal = config[prop];
if (prop === 'autoLoginPwd') {
value = window.btoa(JSON.stringify(str2code(value)));
}
if (preVal !== value) {
config[prop] = value;
_this.setLocal(config);
let msg = `[${ prop }]值变更 ${ preVal }->${ value }`;
_this.logger.info(msg);
if (isNotified(prop)) {
_this.msgWrapper.create(msg);
}
}
return true;
}
})
}
/**
* localstorage解析返回配置对象
* @private
*/
private get Local(): Config {
let config: Config;
try {
config = JSON.parse(localStorage.getItem('wh_trans_settings')) ?? defaultConfig;
} catch (e) {
this.logger.error('配置解析失败, 载入默认');
config = defaultConfig;
localStorage.setItem('wh_trans_settings', JSON.stringify(defaultConfig));
}
return config;
}
private setLocal(config: Config) {
localStorage.setItem('wh_trans_settings', JSON.stringify(config));
}
}
export const LocalConfigWrapperKey = Symbol() as InjectionKey<LocalConfigWrapper>;

80
src/ts/class/Log.ts Normal file
View File

@ -0,0 +1,80 @@
export default class Log {
private static logs = '';
private static counter = { info: 0, error: 0, warning: 0 };
public static info(...o): void {
Log.counter.info++;
let flag = '%c WH %cIFO%c' + this.getTime() + '%c';
if (this.debug()) {
console.log(flag, 'background:grey;color:white;', '', 'color:grey;', '', ...o);
}
this.saveLogs(flag, ...o);
}
public static error(...o): void {
Log.counter.error++;
let flag = '%c WH %cERR%c' + this.getTime() + '%c';
console.error(flag, 'background:grey;color:white;', 'background:red;color:white;', 'color:grey;', '', ...o);
this.saveLogs(flag, ...o);
}
public static warn(...o): void {
Log.counter.warning++;
let flag = '%c WH %cWRN%c' + this.getTime() + '%c';
console.warn(flag, 'background:grey;color:white;', 'background:#ff9800;color:white;', 'color:grey;', '', ...o);
this.saveLogs(flag, ...o);
}
public static debug(): boolean {
let ret: boolean = true;
try {
let local = JSON.parse(localStorage.getItem('wh_trans_settings'));
if (local) ret = local['isDev'];
} catch {
this.error('debug错误')
}
return ret;
}
public static getTime(): string {
let d = new Date();
let year = d.getFullYear();
let month = ('0' + (d.getMonth() + 1)).slice(-2);
let date = ('0' + d.getDate()).slice(-2);
let hours = ('0' + d.getHours()).slice(-2);
let minutes = ('0' + d.getMinutes()).slice(-2);
let seconds = ('0' + d.getSeconds()).slice(-2);
let ms = ('00' + d.getMilliseconds()).slice(-3);
return `${ year }-${ month }-${ date } ${ hours }:${ minutes }:${ seconds }.${ ms }`;
}
public static getLogs() {
return this.logs;
}
private static saveLogs(...o) {
o.forEach(item => {
if (typeof item === 'string') this.logs += item.replaceAll('%c', '');
else if (item !== null && item !== undefined) {
let json = '{}';
let name = Object.getPrototypeOf(item).constructor.name;
try {
json = JSON.stringify(item);
} catch {
}
this.logs += ` [${ name }] [${ json }] `;
if (item.message) this.logs += '错误信息: ' + item.message;
if (item.stack) this.logs += '错误堆栈: ' + item.stack;
}
})
this.logs += '\r\n';
}
public static getCounter() {
return {
info: Log.counter.info,
error: Log.counter.error,
warning: Log.counter.warning,
}
}
}

52
src/ts/class/Logger.ts Normal file
View File

@ -0,0 +1,52 @@
import "reflect-metadata";
import ClassName, { GetClassName } from "../container/ClassName";
import { Injectable } from "../container/Injectable";
import Log from "./Log";
import { InjectionKey } from "vue";
@Injectable()
@ClassName('Logger')
export default class Logger {
info(...o: any): void {
return Log.info(...o);
}
warn(...o: any): void {
return Log.warn(...o);
}
error(...o: any): void {
return Log.error(...o);
}
debug() {
return Log.debug()
}
getCounter() {
return Log.getCounter()
}
getTime() {
return Log.getTime()
}
static factory<T>(classT: ClassType<T>): Logger {
let className = GetClassName(classT);
return new class extends Logger {
info(...o: any): void {
return super.info(`[${ className }]`, ...o);
}
warn(...o: any): void {
return super.warn(`[${ className }]`, ...o);
}
error(...o: any): void {
return super.error(`[${ className }]`, ...o);
}
}();
}
}
export const LoggerKey = Symbol() as InjectionKey<Logger>;

View File

@ -0,0 +1,35 @@
import Logger from "./Logger";
import { Container } from "../container/Container";
import ClassName, { GetClassName } from "../container/ClassName";
import { Injectable } from "../container/Injectable";
@ClassName('ModuleLoader')
@Injectable()
export default class ModuleLoader {
private readonly classes: (new(...arg: any) => { init: () => void })[] = [];
private readonly logger = Logger.factory(ModuleLoader)
// constructor() {
// }
/**
*
* @param method 'init'
*/
public async load(method: string = 'init'): Promise<void> {
this.logger.info('即将加载: ', this.classes)
this.classes.forEach(clazz => {
try {
this.logger.info('正在加载' + GetClassName(clazz))
Container.factory(clazz)[method]();
} catch (e) {
this.logger.error('加载[' + GetClassName(clazz) + ']时出错', e.message, e.stack);
}
});
this.classes.length = 0;
}
public push(clazz: new(...arg: any) => { init: () => void }): void {
this.classes.push(clazz);
}
}

279
src/ts/class/UrlRouter.ts Normal file
View File

@ -0,0 +1,279 @@
import cityFinder from "../func/module/cityFinder";
import { missionDict } from "../dictionary/translation";
import getTaskHint from "../func/translate/getTaskHint";
import CommonUtils from "./utils/CommonUtils";
import SHOP_BEER_STATIC_ITEM_HTML from "../../static/html/buyBeer/shop_beer_static_item.html";
import ADD_BEER_HEAD_HTML from "../../static/html/buyBeer/add_beer_head.html";
import QUICK_CRIMES_HTML from "../../static/html/quick_crimes.html";
import RW_RIDER_HTML from "../../static/html/rw_rider.html";
import christmasTownHelper from "../func/module/christmasTownHelper";
import LotteryHelper from "../feature/LotteryHelper";
import TornStyleBlock from "./utils/TornStyleBlock";
import PTHelper from "./action/PTHelper";
import StackHelper from "../feature/StackHelper";
import BuyBeerHelper from "../feature/BuyBeerHelper";
import XZMZ from "./action/XZMZ";
import ProfileHelper from "./action/ProfileHelper";
import SearchHelper from "./action/SearchHelper";
import TornStyleSwitch from "./utils/TornStyleSwitch";
import SlotsHelper from "./action/SlotsHelper";
import globVars from "../globVars";
import { Injectable } from "../container/Injectable";
import ClassName from "../container/ClassName";
import LocalConfigWrapper from "./LocalConfigWrapper";
import { Container } from "../container/Container";
import Logger from "./Logger";
/**
*
*
* TODO jq
*/
@Injectable()
@ClassName('UrlPattern')
export default class UrlRouter {
constructor(
private readonly localConfigWrapper: LocalConfigWrapper,
private readonly buyBeerHelper: BuyBeerHelper,
private readonly searchHelper: SearchHelper,
private readonly lotteryHelper: LotteryHelper,
private readonly slotsHelper: SlotsHelper,
private readonly logger: Logger,
) {
}
public resolve(): void {
let href = window.location.href;
let modules = [];
// 捡垃圾助手
if (href.includes('city.php') && this.localConfigWrapper.config.cityFinder) {
let _base = new TornStyleBlock('芜湖助手').insert2Dom();
// let reloadSwitch = new TornStyleSwitch('解决一直转圈(加载中)的问题');
// reloadSwitch.getInput().checked = this.localConfigWrapper.config.SolveGoogleScriptPendingIssue;
// _base.append(reloadSwitch.getBase()).insert2Dom();
// reloadSwitch.getInput().addEventListener('change', () => {
// if (reloadSwitch.getInput().checked) window.location.replace(window.location.href);
// this.localConfigWrapper.config.SolveGoogleScriptPendingIssue = reloadSwitch.getInput().checked;
// // WuhuConfig.set('SolveGoogleScriptPendingIssue', reloadSwitch.getInput().checked, true);
// });
_base.append(document.createElement('br'));
cityFinder(_base);
}
// pt一键购买
if (href.includes('pmarket.php')) Container.factory(PTHelper);
// 叠e助手
if (href.includes('gym.php')) Container.factory(StackHelper);
// 寻找木桩
if (href.includes('item.php?temp=4')) {
let hasInit: boolean = false;
let handle = () => {
if (!hasInit && window.location.hash === '#xunzhaomuzhuang') {
Container.factory(XZMZ).init();
hasInit = true;
}
}
window.addEventListener('hashchange', handle);
handle();
}
// 啤酒店
if (href.includes('shops.php?step=bitsnbobs')) {
let block = new TornStyleBlock('啤酒助手').insert2Dom();
block.setContent(ADD_BEER_HEAD_HTML);
const msg_node = block.querySelector('#wh-msg');
// 加入啤酒
block.querySelector('button').addEventListener('click', e => {
let node = document.querySelector('ul.items-list');
if (!node) {
msg_node.innerHTML = '❌ 商品未加载完';
this.logger.error('商品未加载完');
return;
}
if (node.querySelector('span[id="180-name"]')) {
msg_node.innerHTML = '❌ 页面已经有啤酒了';
this.logger.warn('商店页面已有啤酒');
return;
}
const clear_node = node.querySelector('li.clear');
const beer = document.createElement('li');
beer.classList.add('torn-divider', 'divider-vertical');
beer.style.backgroundColor = '#c8c8c8';
beer.innerHTML = SHOP_BEER_STATIC_ITEM_HTML;
if (clear_node) clear_node.before(beer);
else node.append(beer);
(<HTMLInputElement>e.target).disabled = true;
msg_node.innerHTML = '添加成功';
});
// 监听啤酒购买
globVars.responseHandlers.push((...args: any[]) => this.buyBeerHelper.responseHandler.apply(this.buyBeerHelper, args));
}
// 快速crime TODO 重构、与翻译解藕
if (href.contains(/crimes\.php/) && this.localConfigWrapper.config.quickCrime) {
// iframe
if (self !== top) {
const isValidate = document.querySelector('h4#skip-to-content').innerText.toLowerCase().includes('validate');
CommonUtils.elementReady('#header-root').then(e => e.style.display = 'none');
CommonUtils.elementReady('#sidebarroot').then(e => e.style.display = 'none');
CommonUtils.elementReady('#chatRoot').then(e => e.style.display = 'none');
if (!isValidate) document.body.style.overflow = 'hidden';
CommonUtils.elementReady('.content-wrapper').then(e => {
e.style.margin = '0px';
e.style.position = 'absolute';
e.style.top = '-35px';
});
CommonUtils.elementReady('#go-to-top-btn button').then(e => e.style.display = 'none');
}
const element = document.querySelector('.content-wrapper');
const OB = new MutationObserver(() => {
OB.disconnect();
// titleTrans();
// contentTitleLinksTrans();
trans();
OB.observe(element, {
characterData: true,
attributes: true,
subtree: true,
childList: true
});
});
const trans = () => {
const dom = QUICK_CRIMES_HTML;
const hasInserted = element.querySelector('.wh-translate') !== null;
// const is_captcha = element.querySelector('div#tab-menu.captcha') !== null;
const $title = document.querySelector('div.content-title');
const $info = document.querySelector('.info-msg-cont');
// if (!hasInserted && !is_captcha) {
if (!hasInserted) {
if ($title) $title.insertAdjacentHTML('beforebegin', dom);
else if ($info) $info.insertAdjacentHTML('beforebegin', dom);
}
};
trans();
OB.observe(element, {
characterData: true,
attributes: true,
subtree: true,
childList: true
});
}
// 任务助手 TODO 重构、与翻译解藕
if (href.contains(/loader\.php\?sid=missions/) && this.localConfigWrapper.config.missionHint) {
const anchor = document.querySelector('.content-wrapper');
const OB = new MutationObserver(() => {
OB.disconnect();
// titleTrans();
// contentTitleLinksTrans();
trans();
OB.observe(anchor, {
characterData: true,
attributes: true,
subtree: true,
childList: true
});
});
const taskList = {};
const trans = () => {
$('ul#giver-tabs a.ui-tabs-anchor').each((i, e) => {
let $e = $(e);
if ($e.children().hasClass('mission-complete-icon')) {
taskList[i] = e.innerText.trim();
} else {
taskList[i] = $e.clone().children().remove().end().text().trim();
}
});
// 助手注入
$('div.max-height-fix.info').each((i, e) => {
let $e = $(e);
if ($e.find('.wh-translated').length !== 0) return;
$e.append(`<div class="wh-translated"><h6 style="color:green"><b>任务助手</b></h6><p>${ getTaskHint(taskList[i]) }</p></div>`);
});
// 任务目标
$('ul.tasks-list span.title-wrap').contents().each((i, e) => {
if (e.nodeType === 3) {
if (missionDict[e.nodeValue.trim()]) {
e.nodeValue = missionDict[e.nodeValue.trim()];
}
}
});
};
trans();
OB.observe(anchor, {
characterData: true,
attributes: true,
subtree: true,
childList: true
});
}
// 个人资料
if (href.includes('profiles.php?XID=')) Container.factory(ProfileHelper);
// 圣诞小镇
if (href.contains(/christmas_town\.php/) && new Date().getMonth() > 9) christmasTownHelper();
// rw雷达
if (href.includes('profiles.php?XID=0')) {
const utl = {
set: function (k, v) {
const obj = JSON.parse(localStorage['wh_rw_raider']) || {};
obj[k] = v;
localStorage['wh_rw_raider'] = JSON.stringify(obj);
},
get: function (k) {
const obj = JSON.parse(localStorage['wh_rw_raider']) || {};
return obj[k];
},
setFactionID: function (id) {
this.set('faction', id);
},
setRWFactionID: function (id) {
this.set('rw_faction', id);
},
getFactionID: async function (apikey) {
const response = await window.fetch('https://api.torn.com/faction/?selections=basic&key=' + apikey);
const res_obj = await response.json();
const faction_id = res_obj['ID'];
if (faction_id) {
this.setFactionID(faction_id);
return faction_id;
} else return -1;
},
getRWFactionID: function (apikey) {
},
};
const rw_raider = async function () {
if (href.includes('#rader')) {
CommonUtils.addStyle('div.content-title,div.info-msg-cont{display:none;}');
const wh_node = document.createElement('div');
wh_node.id = 'wh-rd-cont';
wh_node.innerHTML = RW_RIDER_HTML;
// 原页面完全加载
await CommonUtils.elementReady('div.msg[role="alert"]');
const t_cont = document.querySelector('div.content-wrapper');
// t
t_cont.append(wh_node);
}
};
addEventListener('hashchange', rw_raider);
rw_raider().then();
}
// 彩票助手
if (href.includes('loader.php?sid=lottery')) this.lotteryHelper.init();
// 老虎机助手
if (href.includes('loader.php?sid=slots')) this.slotsHelper.init();
// 搜索助手
if (href.includes('page.php?sid=UserList')) this.searchHelper.init();
}
}

465
src/ts/class/ZhongIcon.ts Normal file
View File

@ -0,0 +1,465 @@
import adHelper from "../func/module/adHelper";
import safeKeeper from "../func/module/safeKeeper";
import initMiniProf from "../func/utils/initMiniProf";
import CommonUtils from "./utils/CommonUtils";
import * as EVENTS from "../../static/json/event.json";
import * as FEST from "../../static/json/fest.json";
import Popup from "./utils/Popup";
import TravelItem from "../feature/TravelItem";
import ZHONG_MENU_HTML from "../../static/html/zhong/zhong_menu.html";
import ZHONG_UPDATE_HTML from "../../static/html/zhong/zhong_update.html";
import ZHONG_LOOT_HTML from "../../static/html/zhong/zhong_loot.html";
import Test from "../test/Test";
import Timer from "./utils/Timer";
import QuickFlyBtnHandler from "./handler/QuickFlyBtnHandler";
import NNB from "./handler/NNB";
import QuickLinksHandler from "./handler/QuickLinksHandler";
import ItemPriceWatcherHandler from "./handler/ItemPriceWatcherHandler";
// import ChangeLogHandler from "./handler/ChangeLogHandler";
import ItemPriceHandler from "./handler/ItemPriceHandler";
import SettingsHandler from "./handler/SettingsHandler";
import { MENU_ITEM_TYPE } from "../interface/MenuItem";
import { Injectable } from "../container/Injectable";
import ClassName from "../container/ClassName";
import LocalConfigWrapper from "./LocalConfigWrapper";
import Logger from "./Logger";
import { Container } from "../container/Container";
import TornPDAUtils from "./utils/TornPDAUtils";
import InfoUtils from "./utils/InfoUtils";
import globVars from "../globVars";
import MsgWrapper from "./utils/MsgWrapper";
@Injectable()
@ClassName('ZhongIcon')
export default class ZhongIcon {
public static ZhongNode: MyHTMLElement = null;
private menuItemList: MenuItemConfig[] = null;
private cashView: HTMLElement = null;
public constructor(
private readonly commonUtils: CommonUtils,
private readonly localConfigWrapper: LocalConfigWrapper,
private readonly nnb: NNB,
private readonly itemPriceWatcherHandler: ItemPriceWatcherHandler,
private readonly logger: Logger,
private readonly tornPDAUtils: TornPDAUtils,
private readonly infoUtils: InfoUtils,
private readonly msgWrapper: MsgWrapper,
) {
}
public init() {
this.constructMenuList()
.insert2Dom()
.dragHandler();
this.logger.info('设置图标结束');
}
public updateCashView(content: string): void {
if (!this.cashView || !ZhongIcon.ZhongNode.contains(this.cashView)) {
this.cashView = document.createElement('div');
this.cashView.id = 'wh-cash-monitor';
ZhongIcon.ZhongNode.append(this.cashView);
}
this.cashView.innerText = content;
}
private static setPosition(x: number, y: number) {
if (!(x && y)) return;
if (x > 0 && x < document.documentElement.offsetWidth - 100) {
ZhongIcon.ZhongNode.style.left = x + "px";
}
if (y > 0 && y < document.documentElement.offsetHeight - 60) {
ZhongIcon.ZhongNode.style.top = y + "px";
}
}
/**
*
*/
private insert2Dom(): ZhongIcon {
let zhongNode: MyHTMLElement = document.querySelector('div#wh-trans-icon');
let version = globVars.version;
if ((self !== top) || !!zhongNode) return null;
zhongNode = document.createElement('div');
ZhongIcon.ZhongNode = zhongNode;
zhongNode.id = 'wh-trans-icon';
zhongNode.classList.add('cont-gray');
zhongNode.innerHTML = ZHONG_MENU_HTML.replace('{{}}', version.slice(-1) === '$' ? 'DEV' : version);
// 助手菜单
const menu_cont = zhongNode.querySelector('#wh-gSettings');
// 遍历菜单node设置、生成node、插入dom
this.menuItemList.forEach(setting => this.commonUtils.elemGenerator(setting, menu_cont));
this.logger.info('生成元素插入完成');
// 计时node
zhongNode.initTimer = zhongNode.querySelector('#wh-inittimer');
// 芜湖助手图标点击事件
(<MyHTMLElement>zhongNode.querySelector('#wh-trans-icon-btn')).onclick = () => {
zhongNode.classList.toggle('wh-icon-expanded');
const click_func = e => {
this.logger.info(e.target);
if (e.target === zhongNode.querySelector('#wh-trans-icon-btn')) return;
if (!zhongNode.contains(e.target)) {
this.logger.info('移除事件监听器');
document.body.removeEventListener('click', click_func);
zhongNode.classList.remove('wh-icon-expanded');
}
};
if (zhongNode.classList.contains('wh-icon-expanded')) {
this.logger.info('芜湖助手图标点击->添加监听');
document.body.addEventListener('click', click_func);
} else {
this.logger.info('芜湖助手图标->移除监听');
document.body.removeEventListener('click', click_func);
}
};
// 更新按钮点击事件
(<MyHTMLElement>zhongNode.querySelector('#wh-update-btn')).onclick = e => {
(<HTMLButtonElement>e.target).blur();
// 直接复制的按钮
new Popup(ZHONG_UPDATE_HTML, '如何更新')
.element
.querySelector('button').onclick = async (e) => {
let target = e.target as HTMLButtonElement;
target.innerHTML = '加载中';
const js_text = await CommonUtils.COFetch(`https://jjins.github.io/fyfuzhi/release.min.user.js?${ performance.now() }`);
target.innerHTML = '点击复制到剪切板';
target.onclick = () => {
const textarea_node = document.createElement('textarea');
textarea_node.innerHTML = js_text;
target.parentElement.append(textarea_node);
textarea_node.focus();
textarea_node.select();
document.execCommand('Copy');
textarea_node.remove();
target.innerHTML = '已复制';
target.onclick = null;
this.msgWrapper.create('脚本已复制,请前往粘贴');
};
};
};
// 节日
zhongNode.querySelectorAll('#wh-trans-fest-date button').forEach((el, i) => i === 0
? el.addEventListener('click', () => {
let html = '<table>';
// TODO 动态节日数据
Object.keys(FEST.val).sort().forEach(date =>
html += `<tr><td>${ 1 + ((<any>date.slice(0, 2)) | 0) }${ date.slice(2) }日</td><td>${ FEST.val[date].name }</td><td>${ FEST.val[date].eff }</td></tr>`
);
new Popup(html += '</table>', '节日');
})
: el.addEventListener('click', null));
// 活动
zhongNode.querySelectorAll('#wh-trans-event-cont button').forEach((el, i) => i === 0
? el.addEventListener('click', () => {
let html = '<table>';
// TODO 动态节日数据
EVENTS.default.forEach(el =>
html += `<tr><td><b>${ el.name }</b></td><td>${ el.start[0] + 1 }${ el.start[1] }${ el.start[2] }:00~${ el.end[0] + 1 }${ el.end[1] }${ el.end[2] }:00</td></tr><tr><td colspan="2">${ el.eff }</td></tr>`);
new Popup(html += '</table><p>更多信息请关注群聊和公众号</p>', '活动');
})
: el.addEventListener('click', null));
// 调整图标至有记录的位置
if (this.localConfigWrapper.config.SaveIconPosition) {
let iconPosition = this.localConfigWrapper.config.IconPosition;
let documentSize = { x: document.documentElement.offsetWidth, y: document.documentElement.offsetHeight };
ZhongIcon.setPosition(
iconPosition.x > documentSize.x ? documentSize.x * 0.9 | 0 : iconPosition.x,
iconPosition.y > documentSize.y ? documentSize.y * 0.9 | 0 : iconPosition.y
);
}
document.body.append(zhongNode);
// 引入torn自带浮动提示
this.logger.info('引入torn浮动提示');
(window.initializeTooltip) && (window.initializeTooltip('.wh-container', 'white-tooltip'));
// 加载torn mini profile
this.logger.info('加载torn mini profile');
let miniProfileInterval = {
id: window.setInterval(() => {
miniProfileInterval.counter++;
if (window.$ || (window.unsafeWindow && window.unsafeWindow.$)) {
initMiniProf('#wh-trans-icon');
window.clearInterval(miniProfileInterval.id);
}
if (miniProfileInterval.counter > 30) window.clearInterval(miniProfileInterval.id);
}, 1000),
counter: 0
};
this.logger.info('图标加入文档树');
return this;
}
private dragHandler(): ZhongIcon {
let isMouseDown = false;
let isMouseMoved = false;
let offsetXY = { x: 0, y: 0 };
ZhongIcon.ZhongNode.addEventListener('mousedown', (e) => {
if (e.button === 0) {
e.preventDefault();
isMouseDown = true;
let nodeXY = ZhongIcon.getPosition();
offsetXY.x = e.x - nodeXY.x;
offsetXY.y = e.y - nodeXY.y;
}
});
document.addEventListener('mouseup', () => {
isMouseDown = false;
if (isMouseMoved) {
isMouseMoved = false;
if (this.localConfigWrapper.config.SaveIconPosition) {
this.localConfigWrapper.config.IconPosition = ZhongIcon.getPosition();
}
}
});
document.addEventListener('mousemove', (e) => {
if (isMouseDown) {
ZhongIcon.setPosition(e.x - offsetXY.x, e.y - offsetXY.y);
isMouseMoved = true;
}
});
return this;
}
private static getPosition(): { x: number, y: number } {
return {
x: ZhongIcon.ZhongNode.style.left ? parseInt(ZhongIcon.ZhongNode.style.left.slice(0, -2)) : ZhongIcon.ZhongNode.offsetLeft,
y: ZhongIcon.ZhongNode.style.top ? parseInt(ZhongIcon.ZhongNode.style.top.slice(0, -2)) : ZhongIcon.ZhongNode.offsetTop
}
}
// 菜单
private constructMenuList(): ZhongIcon {
this.logger.info('构造菜单列表开始');
let timer = new Timer();
const date = new Date();
let userInfo = this.infoUtils.getPlayerInfo();
let list: MenuItemConfig[] = [];
// 欢迎 显示玩家id
if (userInfo.userID !== 0) {
list.push({
domType: 'plain',
domId: 'wh-trans-welcome',
domHTML:
`<a href="/profiles.php?XID=${ userInfo.userID }" target="_blank">${ userInfo.playername }</a>[${ userInfo.userID }]`,
});
}
// 节日
let fest_date_html = '<button>节日</button>: ';
{
// 节日字典
const dict = FEST.val;
// list.fest_date_dict = dict;
// list.fest_date_list = Object.keys(dict);
const formatMMDD = (m, d) => {
const MM = m < 10 ? `0${ m }` : m.toString();
const DD = d < 10 ? `0${ d }` : d.toString();
return MM + DD;
}
const fest_date_key = formatMMDD(date.getUTCMonth(), date.getUTCDate());
if (dict[fest_date_key]) fest_date_html += `今天 - ${ dict[fest_date_key]['name'] }(<button title="${ dict[fest_date_key]['eff'] }">效果</button>)`;
else {
// 月日列表
let list = Object.keys(dict);
list.push(fest_date_key);
// 下个节日的位置
const index: number = list.sort().indexOf(fest_date_key) + 1;
// 下个节日obj
const next_fest_date = dict[list[index] || list[0]];
// 下个节日的时间
let next = new Date(
index !== list.length ? date.getUTCFullYear() : date.getUTCFullYear() + 1,
(list[index !== list.length ? index : 0] as any).slice(0, 2) | 0,
(list[index !== list.length ? index : 0] as any).slice(2) | 0,
8
).getTime();
// 剩余天数
const left = (next - date.getTime()) / 86400000 | 0;
fest_date_html += `${ left }天后 - ${ next_fest_date.name }(<button title="${ next_fest_date.eff }">效果</button>)`;
}
}
list.push({
domType: 'plain',
domId: 'wh-trans-fest-date',
domHTML: fest_date_html,
});
// 活动
let eventObj: EventWrapper = {
onEv: false,
daysLeft: Infinity,
events: EVENTS.default,
};
list.events = EVENTS.default;
eventObj.events.forEach((obj, index) => {
if (eventObj.onEv) return;
// 当前年份
const nowYear = date.getFullYear();
// 当前遍历的活动开始时间
const start = new Date(nowYear, obj.start[0], obj.start[1], obj.start[2]);
// 当前遍历的活动结束时间
const end = new Date(nowYear, obj.end[0], obj.end[1], obj.end[2]);
// 当前处于活动中
if (start < date && date < end) {
eventObj.onEv = true;
eventObj.daysLeft = (end.getTime() - date.getTime()) / 86400000 | 0;
eventObj.current = obj;
}
// 当前没有活动
else {
// 当前遍历的活动如果已经经过了,那么下次活动就是遍历的下一个活动对象,否则为当前活动。
// 如果本年度活动都经过了,那么下次活动是列表的第一个活动对象
const next = end < date ? eventObj.events[index + 1] || eventObj.events[0] : obj;
// 经过了最后一个活动所以下次活动开始时间是第二年
const start = new Date(next !== obj && index === eventObj.events.length - 1 ? nowYear + 1 : nowYear, next.start[0], next.start[1], next.start[2]);
const daysLeft = (start.getTime() - date.getTime()) / 86400000 | 0;
if (0 <= daysLeft && daysLeft < eventObj.daysLeft) {
eventObj.daysLeft = daysLeft;
eventObj.next = next;
}
}
});
eventObj.html = '<button>活动</button>: ';
eventObj.onEv
? eventObj.html += `${ eventObj.current.name }(<button title="${ eventObj.current.eff }">详情</button>) - 剩余${ eventObj.daysLeft }`
: eventObj.html += `${ eventObj.daysLeft }天后 - ${ eventObj.next.name }(<button title="${ eventObj.next.eff }">详情</button>)`;
list.push({
domType: 'plain',
domId: 'wh-trans-event-cont',
domHTML: eventObj.html,
});
// 一键起飞
list.push({
domType: 'button',
domId: 'wh-quick-fly-btn',
domText: '✈️ 一键起飞',
clickFunc: () => Container.factory(QuickFlyBtnHandler).handle(),
});
// 飞花库存
list.push({
domType: 'button',
domId: 'wh-foreign-stock-btn',
domText: '🌸 飞花库存',
clickFunc: () => Container.factory(TravelItem).clickHandler().then(),
});
// NPC LOOT
list.push({
domType: 'button',
domId: 'wh-npc-loot-btn',
domText: '🔫 LOOT',
clickFunc: () => {
const insert = ZHONG_LOOT_HTML.replace('{{}}', performance.now().toString());
new Popup(insert, 'NPC LOOT');
},
tip: '显示5个可击杀NPC的开打时间',
});
// 查看NNB
list.push({
domType: 'button',
domId: 'wh-nnb-info',
domText: '👮‍ 查看NNB',
clickFunc: () => this.nnb.handle(),
});
// 常用链接
list.push({
domType: 'button',
domId: 'wh-link-collection',
domText: '🔗 常用链接',
clickFunc: () => Container.factory(QuickLinksHandler).handle()
});
// 飞贼
// list.push({
// domType: 'button',
// domId: 'wh-gs-btn',
// domText: '🐏 飞贼小助手',
// clickFunc: () => loadGS(CommonUtils.getScriptEngine()),
// tip: '加载从PC端移植的伞佬的油猴版飞贼小助手',
// });
// 物品价格监视
list.push({
domType: 'button',
domId: 'wh-price-watcher-btn',
domText: '💊 价格监视',
clickFunc: () => this.itemPriceWatcherHandler.handle()
});
// 全屏
if (!this.tornPDAUtils.isPDA()) list.push({
domType: 'button', domId: '', domText: '🖥️ 进入全屏', clickFunc() {
document.documentElement.requestFullscreen().then();
}
});
// 传单助手
list.push({
domType: 'button',
domId: '',
domText: '📜️ 传单助手',
clickFunc: adHelper
});
// 守望者
list.push({
domType: 'button',
domId: '',
domText: '🛡️ 守望者',
clickFunc: function () {
safeKeeper();
},
});
// 寻找木桩
list.push({
domType: 'button',
domId: '',
domText: '🌲 寻找木桩',
clickFunc() {
window.location.replace('https://www.torn.com/item.php?temp=4#xunzhaomuzhuang')
}
});
// 物品查价
list.push(ItemPriceHandler);
// 更新历史
// list.push(ChangeLogHandler);
// 助手设置
list.push(SettingsHandler);
// 测试
if (this.logger.debug()) list.push(Test);
this.menuItemList = list;
this.logger.info('构造展开菜单列表结束' + timer.getTimeMs());
return this;
}
}
export interface MenuItemConfig {
domType: 'button' | 'plain' | 'checkbox' | 'select' | MENU_ITEM_TYPE;
tagName?: string;
domId?: string;
domText?: string;
clickFunc?: (ev?) => void;
domHTML?: string;
tip?: string;
dictName?: string;
changeEv?: (ev) => void;
domSelectOpt?: { domVal: string, domText: string }[];
/**
*
* @deprecated
*/
isHide?: boolean;
isTornBtn?: boolean;
}
interface EventWrapper {
onEv: boolean;
daysLeft: number;
events: Event[];
current?: Event;
next?: Event;
html?: string;
}
interface Event {
start: number[];
end: number[];
name: string;
eff: string;
}

View File

@ -0,0 +1,352 @@
// import CommonUtils from "../utils/CommonUtils";
// import Alert from "../utils/Alert";
// import Global from "../Global";
// import Device from "../../enum/Device";
// import ATTACK_HELPER_CSS from "../../../static/css/attack_helper.module.css";
// import ActionButtonUtils from "../utils/ActionButtonUtils";
// import TornStyleBlock from "../utils/TornStyleBlock";
// import TornStyleSwitch from "../utils/TornStyleSwitch";
// import DialogMsgBox from "../utils/DialogMsgBox";
// import FetchUtils from "../utils/FetchUtils";
// import MathUtils from "../utils/MathUtils";
// import LoopHelper from "../utils/LoopHelper";
// import TRAVEL_STATE from "../../enum/TravelState";
// import { Injectable } from "../../container/Injectable";
// import ClassName from "../../container/ClassName";
// import LocalConfigWrapper from "../LocalConfigWrapper";
// import Logger from "../Logger";
//
// enum FIGHT_STAGE {
// READY = 'ready',
// IN_PROGRESS_OR_ERROR = 'in_progress_or_error',
// FINISHED = 'finished',
// END = 'end',
// OTHER = 'other'
// }
//
// /**
// * 战斗助手
// * TODO 页面加载已经在进行中的战斗时的正确判断
// */
// @Injectable()
// @ClassName('AttackHelper')
// export default class AttackHelper {
//
// private currentStage: FIGHT_STAGE = FIGHT_STAGE.OTHER;
//
// constructor(
// private readonly localConfigWrapper: LocalConfigWrapper,
// private readonly commonUtils: CommonUtils,
// private readonly global: Global,
// private readonly mathUtils: MathUtils,
// private readonly actionButtonUtils: ActionButtonUtils,
// private readonly fetchUtils: FetchUtils,
// private readonly logger: Logger,
// ) {
// }
//
// init(): void {
// window.setTimeout(() => this._init(), 0);
// }
//
// private _init() {
// if (window.location.href.contains(/loader\.php\?sid=attack/)) {
// this.fightingPageHandle();
// }
// // 错误的攻击页面转跳
// // else if (window.location.href.includes('loader2.php') && this.localConfigWrapper.config.attRelocate) {
// // const spl = window.location.href.trim().split('=');
// // const uid = spl[spl.length - 1];
// // if (this.commonUtils.isValidUid(uid)) {
// // window.location.href = 'https://www.torn.com/loader.php?sid=attack&user2ID=' + uid;
// // } else {
// // this.logger.error('[AttackHelper] UID格式不正确');
// // }
// // }
// }
//
// private fightingPageHandle(): void {
// // 光速刷新按钮
// this.actionButtonUtils.add('光速刷新', () => this.doAttackReload());
//
// // 盯梢
// this.watchTarget();
//
// new MutationObserver((_, observer) => {
// let btnList = document.querySelectorAll('div[class^="dialogButtons___"] button') as NodeListOf<HTMLButtonElement>;
//
// if (btnList.length === 0) {
// if (this.currentStage === FIGHT_STAGE.READY && this.localConfigWrapper.config.quickFinishAtt === 3) {
// document.body.classList.remove('wh-move-btn');
// this.logger.info('移除body class wh-move-btn');
// observer.disconnect();
// }
// // 错误或正在打
// this.currentStage = FIGHT_STAGE.IN_PROGRESS_OR_ERROR;
// this.logger.info('[attackHelper] currentStage', this.currentStage);
// return;
// }
// btnList.forEach(btn => {
// let btnText = btn.innerText.toLowerCase();
// if (btnText.includes('start') || btnText.includes('join')) {
// // 开始
// this.quickStartFight();
// } else if (btnText.includes('continue')) {
// // 结束end
// this.currentStage = FIGHT_STAGE.END;
// observer.disconnect();
// } else if (btnText.includes('leave')) {
// // 无意识状态FINISHED
// this.quickFinishFight(btnList);
// }
// this.logger.info('[attackHelper] currentStage', this.currentStage);
// })
// })
// .observe(document.querySelector('#react-root'), { childList: true, subtree: true });
// }
//
// // 战斗页面快速刷新
// private doAttackReload(): void {
// if (!window.ReactDOM) {
// new Alert('光速刷新失败未找到React对象');
// this.logger.error('光速刷新失败未找到React对象');
// return;
// }
// if (!document.querySelector('#react-root #attacker')) {
// this.logger.error('dom元素未找到selector: [#react-root #attacker]');
// return;
// }
// let script = document.querySelector('script[src*="/builds/attack/"]');
// let url = script.src;
// if (!url.contains(/runtime\..+\.js/)) {
// this.logger.error('脚本源[' + url + '] 不匹配规则');
// return;
// }
// window.ReactDOM.unmountComponentAtNode(document.querySelector('#react-root'));
// script.remove();
// let node = document.createElement('script');
// node.src = url;
// node.type = 'text/javascript';
// document.head.appendChild(node);
// }
//
// // 光速拔刀
// private quickStartFight(): void {
// if (this.currentStage === FIGHT_STAGE.READY) {
// return;
// } else {
// this.currentStage = FIGHT_STAGE.READY;
// }
// if (this.localConfigWrapper.config.quickAttIndex === 6) return;
// /**
// * pc #defender
// * mobile #attacker
// */
// const btn = <HTMLInputElement>(document.querySelector('#attacker button') || document.querySelector('#defender button'));
// this.logger.info('操作按钮', { btn });
// if (!btn.innerText.toLowerCase().includes('fight')) {
// this.logger.info('未找到攻击按钮, 光速拔刀跳过');
// new Alert('未找到攻击按钮, 光速拔刀跳过');
// } else {
// // 判断是否存在脚踢
// const hasKick = !!document.querySelector('#weapon_boots');
// // modal层
// // const modal: HTMLElement = document.querySelector('div[class^="modal___"]');
// let device = this.global.device;
// this.logger.info(`当前设备类型是${ device }`);
// // 区分设备
// switch (device) {
// case Device.PC: {
// this.logger.info(`开始调整按钮位置`);
// // 隐藏modal层
// // modal.style.display = 'none';
// // 根据选择的武器调整css
// let css_top = '0';
// switch (this.localConfigWrapper.config.quickAttIndex) {
// // weapon_second
// case 1: {
// css_top = '97px';
// break;
// }
// // weapon_melee
// case 2: {
// css_top = '194px';
// break;
// }
// // weapon_temp
// case 3: {
// css_top = '291px';
// break;
// }
// // weapon_fists
// case 4:
// // weapon_boots
// case 5: {
// css_top = '375px';
// break;
// }
// }
// this.commonUtils.styleInject(ATTACK_HELPER_CSS);
// CommonUtils.addStyle(`.wh-move-btn #defender div[class^="modal___"]{top: ${ css_top };}`);
// document.body.classList.add('wh-move-btn');
// break;
// }
// case Device.MOBILE: {
// this.logger.info(`开始调整按钮位置`);
// // 加入css
// let css_top = '0';
// let slot_height = '76px';
// // 判断有没有脚踢
// if (hasKick) {
// // 根据选择的武器调整
// switch (this.localConfigWrapper.config.quickAttIndex) {
// case 1: { // weapon_second
// css_top = '76px';
// break;
// }
// case 2: { // weapon_melee
// css_top = '152px';
// break;
// }
// case 3: { // weapon_temp
// css_top = '228px';
// break;
// }
// case 4: { // weapon_fists
// css_top = '304px';
// break;
// }
// case 5: { // weapon_boots
// css_top = '380px';
// break;
// }
// }
// } else {
// const slot = document.querySelector('#weapon_main') as HTMLElement;
// const height = slot.offsetHeight + 1;
// // TODO 待验证
// slot_height = height + 'px';
// // 根据选择的武器调整
// switch (this.localConfigWrapper.config.quickAttIndex) {
// case 1: { // weapon_second
// css_top = `${ height }px`;
// break;
// }
// case 2: { // weapon_melee
// css_top = `${ height * 2 }px`;
// break;
// }
// case 3: { // weapon_temp
// css_top = `${ height * 3 }px`;
// break;
// }
// case 4: { // weapon_fists
// css_top = `${ height * 4 }px`;
// break;
// }
// case 5: { // weapon_boots
// css_top = `${ height * 5 }px`;
// break;
// }
// }
// }
// const css_rule = ATTACK_HELPER_CSS.replace('CSSVAR', css_top).replace('CSSVAR', slot_height);
//
// this.commonUtils.styleInject(css_rule);
// document.body.classList.toggle('wh-move-btn');
// btn.onclick = () => {
// if (this.localConfigWrapper.config.quickFinishAtt !== 3) {
// btn.remove();
// // 停止自动刷新
// // stop_reload = true;
// } else {
// document.body.classList.toggle('wh-move-btn');
// }
// };
// break;
// }
// case Device.TABLET: {
// break;
// }
// }
// }
// }
//
// // 光速跑路
// private quickFinishFight(btnList: NodeListOf<HTMLButtonElement>): void {
// if (this.currentStage === FIGHT_STAGE.FINISHED) {
// return;
// } else {
// this.currentStage = FIGHT_STAGE.FINISHED;
// }
// if (this.localConfigWrapper.config.quickFinishAtt === 3) {
// document.body.classList.remove('wh-move-btn');
// this.logger.info('移除body class wh-move-btn');
// return;
// }
// const user_btn_select = ['leave', 'mug', 'hosp'][this.localConfigWrapper.config.quickFinishAtt];
// // const wrap = document.querySelector('#react-root');
// this.logger.info('光速跑路选项选中:', user_btn_select);
// // const btn_arr: HTMLButtonElement[] = document.querySelectorAll('div[class^="dialogButtons___"] button') as unknown as HTMLButtonElement[];
// if (btnList.length > 1) btnList.forEach(btn => {
// const flag = btn.innerText.toLowerCase().includes(user_btn_select);
// this.logger.info('按钮内容:', btn.innerText, ',是否包含选中:', flag);
// if (!flag) btn.style.display = 'none';
// });
// }
//
// // 盯梢模式
// private watchTarget(): void {
// this.logger.info('获取目标id');
// let targetId = window.location.href.split('user2ID=')[1];
// if (!this.commonUtils.isValidUid(targetId)) {
// this.logger.error('目标id获取错误', targetId);
// throw new Error('目标id获取错误:' + targetId);
// }
// let loop = new LoopHelper(async () => {
// let userProfile;
// try {
// userProfile = await this.fetchUtils.getProfile(targetId);
// } catch {
// this.logger.error('盯梢模式无法获取目标id');
// throw new Error('盯梢模式无法获取目标id');
// }
// await this.commonUtils.sleep(this.mathUtils.getRandomInt(20, 50));
// if ((userProfile.userStatus.status === 'ok' && this.commonUtils.getTravelStage() === TRAVEL_STATE.IN_TORN) ||
// (userProfile.userStatus.status === 'abroad' && this.commonUtils.getTravelStage() === TRAVEL_STATE.ABROAD)) {
// watchSwitch.getInput().checked = false;
// window.setTimeout(async () => {
// new Alert('目标已落地/出院/出狱!', { timeout: 10, force: true, sysNotify: true });
// await this.commonUtils.audioPlay();
// await this.commonUtils.sleep(300);
// await this.commonUtils.audioPlay();
// await this.commonUtils.sleep(300);
// await this.commonUtils.audioPlay();
// await this.commonUtils.sleep(300);
// }, 0);
// }
// });
// let block = new TornStyleBlock('盯梢模式').insert2Dom();
// let watchSwitch = new TornStyleSwitch('开启');
// block.append(watchSwitch.getBase());
// watchSwitch.getInput().addEventListener('change', () => {
// if (watchSwitch.getInput().checked) {
// new DialogMsgBox('检测玩家状态,当目标状态变成(海外)落地、出院或出狱时通知并播放声音提醒,后可搭配光速刷新食用<br/>确定开启?', {
// callback: () => {
// if (this.commonUtils.getTravelStage() === TRAVEL_STATE.FLYING) {
// new Alert('失败!已取消');
// watchSwitch.getInput().checked = false;
// return;
// }
// this.logger.info('盯梢开启, 目标id' + targetId);
// loop.start(this.localConfigWrapper.config.WatchTargetFreq | 0);
// },
// cancel: () => watchSwitch.getInput().checked = false
// });
// } else {
// loop.stop();
// this.logger.info('盯梢关闭');
// }
// });
// }
// }

View File

@ -0,0 +1 @@
export default {};

View File

@ -0,0 +1,75 @@
import { MiniProfile } from "../../interface/responseType/MiniProfile";
import CommonUtils from "../utils/CommonUtils";
import Provider from "../provider/Provider";
import ResponseInject from "../../interface/ResponseInject";
import { Injectable } from "../../container/Injectable";
import ClassName from "../../container/ClassName";
import LocalConfigWrapper from "../LocalConfigWrapper";
import Logger from "../Logger";
import MsgWrapper from "../utils/MsgWrapper";
import { fetchYata } from "../../func/module/fetchYata";
import toThousands from "../../func/utils/toThousands";
/**
* fetch
*/
@Injectable()
@ClassName("FetchEventCallback")
export default class FetchEventCallback extends Provider implements ResponseInject {
className = "FetchEventCallback";
newNode = document.createElement('div')
bsEstNode = document.createElement('div')
constructor(
private readonly localConfigWrapper: LocalConfigWrapper,
private readonly commonUtils: CommonUtils,
private readonly logger: Logger,
private readonly msgWrapper: MsgWrapper,
) {
super();
}
/**
* fetch
* @param url
* @param response
*/
public responseHandler(url: string, response) {
// mini profile 中添加上次动作
if (url.startsWith('/page.php?sid=UserMiniProfile&userID')) {
window.setTimeout(async () => {
let cont = CommonUtils.querySelector('[class*=profile-mini-_userProfileWrapper___]');
let resp: MiniProfile = response.json as MiniProfile;
if (this.localConfigWrapper.config.ShowMiniProfLastAct) {
this.logger.info({ resp })
let formatted = this.commonUtils.secondsFormat(resp.user.lastAction.seconds);
(await cont).append(this.newNode);
this.newNode.innerText = '上次动作: ' + formatted;
}
if (this.localConfigWrapper.config.isBSEstMiniProfOn) {
const id = resp.user.userID
const apikey = localStorage.getItem('APIKey')
this.bsEstNode.innerHTML = `[BS估算] [${ id }]获取中...`;
(await cont).append(this.bsEstNode)
if (!apikey) {
this.bsEstNode.innerHTML = '[BS估算] 未配置APIKey无法估算BS'
this.logger.error('MINI Profile bs估算失败: APIKey为空')
} else {
const bsData = fetchYata(id, apikey)
bsData.then(data => {
// 网速过慢时可能mini profile容器已更新新内容与上次请求的用户数据不同需要判断
if (this.bsEstNode.innerHTML.includes(resp.user.userID.toString())) {
this.bsEstNode.innerHTML = `[BS估算] ${ resp.user.playerName }[${ id }] ${ toThousands(data.total) }`
}
})
.catch(err => {
this.bsEstNode.innerHTML = `[BS估算] ${ err.message }`
})
}
}
}, 0);
}
}
}

View File

@ -0,0 +1,91 @@
import TornStyleBlock from "../utils/TornStyleBlock";
import TornStyleSwitch from "../utils/TornStyleSwitch";
import { Injectable } from "../../container/Injectable";
import ClassName from "../../container/ClassName";
import LocalConfigWrapper from "../LocalConfigWrapper";
import IFeature from "../../man/IFeature";
import MsgWrapper from "../utils/MsgWrapper";
@Injectable()
@ClassName('PTHelper')
export default class PTHelper implements IFeature {
private observer: MutationObserver;
private usersPointSell: HTMLDivElement;
constructor(
private readonly localConfigWrapper: LocalConfigWrapper,
private readonly msgWrapper: MsgWrapper,
) {
}
description(): string {
return "pt一键购买";
}
iStart(): void | Promise<void> {
this.start()
}
urlExcludes(): RegExp[] {
return [];
}
urlIncludes(): RegExp[] {
return [/pmarket\.php/];
}
start() {
this.observer = new MutationObserver(e => {
for (const t of e) {
t.addedNodes.forEach(e => 'LI' === (e as HTMLElement).tagName && this.removeConfirm(e))
}
});
this.usersPointSell = document.querySelector<HTMLDivElement>('.users-point-sell');
let block = new TornStyleBlock('PT一键购买').insert2Dom();
let switcher = new TornStyleSwitch('开启');
block.append(switcher.getBase());
let toggle = switcher.getInput();
toggle.checked = this.localConfigWrapper.config.ptQuickBuy;
if (toggle.checked) {
this.msgWrapper.create('一键购买已开启');
for (const index in this.usersPointSell.children) {
'LI' === this.usersPointSell.children[index].tagName && this.removeConfirm(this.usersPointSell.children[index])
}
this.observer.observe(this.usersPointSell, { childList: true })
}
toggle.addEventListener('change', () => {
this.localConfigWrapper.config.ptQuickBuy = toggle.checked;
if (toggle.checked) {
for (const index in this.usersPointSell.children) {
'LI' === this.usersPointSell.children[index].tagName && this.removeConfirm(this.usersPointSell.children[index])
}
this.observer.observe(this.usersPointSell, { childList: true });
this.msgWrapper.create('一键购买已开启');
} else {
for (const index in this.usersPointSell.children) {
'LI' === this.usersPointSell.children[index].tagName && this.rollbackConfirm(this.usersPointSell.children[index])
}
this.observer.disconnect();
this.msgWrapper.create('一键购买已关闭');
}
});
}
private removeConfirm(elem): void {
let el = elem.firstElementChild;
el.classList.add('yes');
let old_href = el.getAttribute('href');
let new_href = old_href.replace(/=buy/, '=buy1').replace(/&points=\d{1,9}$/, '');
el.setAttribute('href', new_href);
}
private rollbackConfirm(elem): void {
let el = elem.firstElementChild;
el.classList.remove('yes');
let old_href = el.getAttribute('href');
let new_href = old_href.replace(/=buy1/, '=buy');
el.setAttribute('href', new_href);
}
}

View File

@ -0,0 +1,151 @@
import CommonUtils from "../utils/CommonUtils";
import TornStyleBlock from "../utils/TornStyleBlock";
import TornStyleSwitch from "../utils/TornStyleSwitch";
import ResponseInject from "../../interface/ResponseInject";
import globVars from "../../globVars";
import IUserProfileData from "../../interface/IUserProfileData";
import ClassName from "../../container/ClassName";
import { Injectable } from "../../container/Injectable";
import LocalConfigWrapper from "../LocalConfigWrapper";
import Logger from "../Logger";
import IFeature from "../../man/IFeature";
import { fetchYata } from "../../func/module/fetchYata";
import MsgWrapper from "../utils/MsgWrapper";
import toThousands from "../../func/utils/toThousands";
import { timePastFormat } from "../../func/utils/timePastFormat";
@ClassName('ProfileHelper')
@Injectable()
export default class ProfileHelper implements ResponseInject, IFeature {
private block: TornStyleBlock;
constructor(
private readonly localConfigWrapper: LocalConfigWrapper,
private readonly commonUtils: CommonUtils,
private readonly logger: Logger,
private readonly msgWrapper: MsgWrapper,
) {
}
description(): string {
return "个人资料页面辅助";
}
iStart(): void | Promise<void> {
this.start()
}
urlExcludes(): RegExp[] {
return [];
}
// 曾用名已检测过标记
private task = true;
urlIncludes(): RegExp[] {
return [/profiles\.php\?XID=/];
}
start() {
CommonUtils.addStyle('body.wh-hide_profile_img .profile-image a.profile-image-wrapper .img-wrap img{display:none;}');
// let id = document.querySelector('link[rel="canonical"]').getAttribute('href').split('=')[1];
let id = (new URL(window.location.href)).searchParams.get('XID');
// id获取格式判断
if (!this.commonUtils.isValidUid(id)) {
this.logger.error('[ProfileHelper] id格式错误');
}
if (this.localConfigWrapper.config.HideProfileImg) {
this.logger.info('[ProfileHelper] 隐藏头像');
document.body.classList.toggle('wh-hide_profile_img');
}
this.block = new TornStyleBlock('芜湖助手').insert2Dom();
// 隐藏头像
try {
let hideImgSwitch = new TornStyleSwitch('隐藏头像', this.localConfigWrapper.config.HideProfileImg);
this.block.append(hideImgSwitch.getBase());
hideImgSwitch.getInput().addEventListener('change', () => {
document.body.classList.toggle('wh-hide_profile_img');
this.localConfigWrapper.config.HideProfileImg = hideImgSwitch.getInput().checked;
});
if (this.localConfigWrapper.config.ShowNameHistory) {
globVars.responseHandlers.push((...args: any[]) => this.responseHandler.apply(this, args));
}
} catch (e) {
this.logger.error('隐藏头像时出错了', e.stack)
}
// bs估算
if (this.localConfigWrapper.config.isBSEstProfOn) {
try {
const apikey = localStorage.getItem('APIKey')
if (!apikey) {
this.msgWrapper.create('BS估算失败: 尚未设定APIKey', null, 'error')
}
const promise = fetchYata(parseInt(id), apikey)
const domNode = document.createElement('div')
domNode.innerHTML = 'BS估算中...'
domNode.classList.add('mt-4')
domNode.style.border = '1px solid green'
domNode.style.padding = '2px'
this.block.append(domNode)
const buildType = { Offensive: '攻击型', Defensive: '防御型', Balanced: '平衡型' }
promise.then(data => {
domNode.innerHTML = `<b>BS估算</b><br/>
BS: ${ toThousands(data.total) }<br/>
评分: ${ toThousands(data.score) }<br/>
风格: ${ buildType[data.type] }<br/>
偏差: ${ data.skewness }%<br/>
估算时间: ${ timePastFormat(Date.now() - data.timestamp * 1000) }
`
}).catch(err => {
domNode.innerHTML = 'BS估算出错了: ' + err.message
throw new TypeError('BS估算出错了: ' + err.message)
})
} catch (e) {
this.msgWrapper.create('BS估算失败' + e.message, null, 'error')
throw new TypeError('BS估算失败' + e.message)
}
}
}
responseHandler(url: string, body: { json: unknown; text: string; isModified: boolean }) {
if (url.includes('profiles.php?step=getProfileData') && this.task) {
// 曾用名
const nameHistoryNode = document.createElement('p');
nameHistoryNode.innerHTML = '曾用名:';
this.block.append(nameHistoryNode);
let resp = body.json as IUserProfileData;
if (resp.userInformation.previousAliases.length > 0) { // 曾用名列表
resp.userInformation.previousAliases.forEach(item => nameHistoryNode.innerHTML += item + ' ');
} else {
nameHistoryNode.innerHTML += '暂无';
}
let lastAction = -1
let onlineStatusTitle = '-'
if (resp.basicInformation?.lastAction.seconds) {
lastAction = resp.basicInformation.lastAction.seconds
}
if (resp.basicInformation.icons) {
for (let i = 0; i < resp.basicInformation.icons.length; i++) {
let item = resp.basicInformation.icons[i]
if (item.id === 1) {
onlineStatusTitle = '🟢️ 在线'
break
}
if (item.id === 62) {
onlineStatusTitle = '🟡 挂机'
break
}
if (item.id === 2) {
onlineStatusTitle = '⚪ 离线'
break
}
}
}
const lastActionNode = document.createElement('p')
lastActionNode.innerHTML = `${ onlineStatusTitle } ${ this.commonUtils.secondsFormat(lastAction) }`
this.block.append(lastActionNode)
this.task = false;
}
}
}

View File

@ -0,0 +1,46 @@
import ClassName from "../../container/ClassName";
import { Injectable } from "../../container/Injectable";
import Logger from "../Logger";
import NetHighLvlWrapper, { BATTLE_STAT } from "../utils/NetHighLvlWrapper";
import { InjectionKey } from "vue";
import MsgWrapper from "../utils/MsgWrapper";
type GymResponse = {
success: boolean,
// 成功才有 You gained 689,636.71 strength
gainMessage?: string,
message: string,
text?: string,
error?: string,
};
@ClassName("QuickGymTrain")
@Injectable()
export default class QuickGymTrain {
constructor(
private readonly logger: Logger,
private readonly netHighLvlWrapper: NetHighLvlWrapper,
private readonly msgWrapper: MsgWrapper,
) {
}
doTrain(type = BATTLE_STAT.STR, count = 199) {
window.setTimeout(async () => {
let resObj: GymResponse;
try {
resObj = JSON.parse(await this.netHighLvlWrapper.doGymTrain(type, count))
} catch (e) {
resObj = { success: false, message: '解析失败' };
this.logger.error(e.stack || e.message || e);
}
let msgRs = resObj.success ? '成功' : '失败';
let msgMsg = resObj.message || resObj.text || resObj.error;
this.msgWrapper.create(
'锻炼结果: ' + msgRs + '<br/>提示: ' + (resObj.gainMessage || msgMsg),
{}, resObj.success ? 'success' : 'error'
);
}, 0);
}
}
export const QuickGymTrainKey = Symbol('QuickGymTrainKey') as InjectionKey<QuickGymTrain>;

Some files were not shown because too many files have changed in this diff Show More