Compare commits

...

740 Commits

Author SHA1 Message Date
Nut.andor
b13a8179d9 next_release content 2023-12-31 19:59:17 +01:00
Nut.andor
63f1d27ae8 authors 2023-12-31 19:43:28 +01:00
Nut.andor
185b94732f fix % in translations 2023-12-31 19:35:50 +01:00
Nut.andor
5264c23dc5 Merge remote-tracking branch 'hosted.weblate/master' into v0.8.9 2023-12-31 19:24:33 +01:00
CloneWith
216ae613c6 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (16839 of 16839 strings)
2023-12-30 19:08:28 +01:00
CloneWith
e129245866 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (16839 of 16839 strings)
2023-12-30 16:08:55 +01:00
Nut Andor
bdc9d41b90 Translated using Weblate (German)
Currently translated at 86.8% (14631 of 16839 strings)
2023-12-30 16:08:53 +01:00
ilya
dc80a3bbe9 Translated using Weblate (Russian)
Currently translated at 97.5% (16428 of 16839 strings)
2023-12-27 15:14:06 +01:00
Ilian Iliev
54170d7dd4 Translated using Weblate (Bulgarian)
Currently translated at 38.5% (236 of 612 strings)
2023-12-26 15:09:19 +01:00
Daniel Stasiak
3b3629c1bb Translated using Weblate (Polish)
Currently translated at 84.5% (14245 of 16839 strings)
2023-12-26 15:09:18 +01:00
Ilian Iliev
8c7ab49812 Translated using Weblate (Bulgarian)
Currently translated at 35.7% (219 of 612 strings)
2023-12-24 19:17:33 +01:00
aircqsj
8c3c069f17 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (16839 of 16839 strings)
2023-12-20 13:15:23 +01:00
aircqsj
d491a2db89 Translated using Weblate (Chinese (Simplified))
Currently translated at 97.4% (16410 of 16839 strings)
2023-12-18 05:21:32 +01:00
ilya
fcad74852a Translated using Weblate (Russian)
Currently translated at 96.9% (16330 of 16839 strings)
2023-12-18 05:21:30 +01:00
Nut.andor
04db185d75 next version 2023-12-17 22:21:02 +01:00
aircqsj
6678fc1c72 Translated using Weblate (Chinese (Simplified))
Currently translated at 97.2% (16384 of 16839 strings)
2023-12-14 16:03:24 +01:00
ilya
e7d8a37291 Translated using Weblate (Russian)
Currently translated at 96.7% (16285 of 16839 strings)
2023-12-14 16:03:22 +01:00
Nut.andor
591d368667 next version 2023-12-11 14:39:51 +01:00
Nut.andor
38e136d6f3 fix 2023-12-11 13:15:12 +01:00
Rey Evan
afe7766cad Translated using Weblate (Filipino)
Currently translated at 44.7% (274 of 612 strings)
2023-12-11 13:04:37 +01:00
aircqsj
6a1d927190 Translated using Weblate (Chinese (Simplified))
Currently translated at 96.8% (16301 of 16839 strings)
2023-12-11 13:04:37 +01:00
Nut.andor
063ce332a8 Whatsnew + Foruum Announcement 2023-12-11 12:30:14 +01:00
Nut.andor
239f03c5ec translation status
whatsNew
2023-12-10 23:13:46 +01:00
Nut.andor
add01e2508 release notes 2023-12-10 01:42:41 +01:00
Nut.andor
a2fb8bb2b9 Merge branch 'V0.8.8' 2023-12-10 00:48:39 +01:00
Nut.andor
56c57e7dba mo 2023-12-10 00:25:31 +01:00
Nut.andor
c34c5ecd5e potc 2023-12-10 00:20:33 +01:00
Nut.andor
14b9d00796 content exported from ATCS 2023-12-09 22:18:49 +01:00
Nut.andor
457c98cc0d version 2023-12-09 22:09:31 +01:00
Nut.andor
bb614278bb Merge branch 'master' into V0.8.8 2023-12-09 22:03:23 +01:00
Nut.andor
655d464677 content format reference 2023-12-09 21:54:08 +01:00
Nut.andor
1f63ae060f Merge remote-tracking branch 'hosted.weblate/master' 2023-12-09 21:51:14 +01:00
Nut.andor
b7cc23cb32 opt vegetable 2023-12-07 23:30:55 +01:00
g1zza
53b75f1c80 Added translation using Weblate (Albanian) 2023-12-06 16:21:35 +01:00
Daniel Stasiak
429bb7d61d Translated using Weblate (Polish)
Currently translated at 85.6% (13934 of 16269 strings)
2023-12-05 14:05:56 +01:00
Daniel Stasiak
8070329915 Translated using Weblate (Polish)
Currently translated at 85.6% (13934 of 16269 strings)
2023-12-02 18:06:07 +00:00
Daniel Stasiak
e9138d9cbf Translated using Weblate (Polish)
Currently translated at 85.6% (13934 of 16269 strings)
2023-11-28 15:05:44 +00:00
Raphi
209cf28224 Translated using Weblate (German)
Currently translated at 89.9% (14632 of 16269 strings)
2023-11-28 15:05:41 +00:00
Daniel Stasiak
5363d60ece Translated using Weblate (Polish)
Currently translated at 85.6% (13934 of 16269 strings)
2023-11-26 19:53:11 +01:00
Mateusz Mendel
5d273f7308 Translated using Weblate (Polish)
Currently translated at 85.6% (13934 of 16269 strings)
2023-11-26 19:53:11 +01:00
Mateusz Mendel
000c3e71e2 Translated using Weblate (Polish)
Currently translated at 85.6% (13933 of 16269 strings)
2023-11-26 19:47:51 +01:00
Daniel Stasiak
093c75da95 Translated using Weblate (Polish)
Currently translated at 85.6% (13933 of 16269 strings)
2023-11-26 19:47:50 +01:00
Nut.andor
979d3c81db duplicated dialogue IDs
Removal of xxx_next_release.json
2023-11-26 02:38:58 +01:00
Nut.andor
16c9378da4 content reference fixes 2023-11-26 01:57:54 +01:00
Nut.andor
bf62a3502f APK rename 2023-11-26 01:00:41 +01:00
Darren Crowlen
06d71caa1e Translated using Weblate (Indonesian)
Currently translated at 100.0% (612 of 612 strings)
2023-11-25 19:08:10 +01:00
Daniel Stasiak
aab900dc58 Translated using Weblate (Polish)
Currently translated at 85.6% (13932 of 16269 strings)
2023-11-25 19:08:08 +01:00
Mateusz Mendel
cdb02a8a7b Translated using Weblate (Polish)
Currently translated at 85.6% (13928 of 16269 strings)
2023-11-24 20:38:54 +01:00
Daniel Stasiak
01affa64b3 Translated using Weblate (Polish)
Currently translated at 85.6% (13928 of 16269 strings)
2023-11-24 20:38:53 +01:00
gallegonovato
cc34decd0f Translated using Weblate (Spanish)
Currently translated at 82.9% (13498 of 16269 strings)
2023-11-24 20:38:52 +01:00
Ranforingus
d971825cbd Translated using Weblate (Dutch)
Currently translated at 96.8% (593 of 612 strings)
2023-11-23 09:54:34 +01:00
Ilian Iliev
cbc4992f10 Translated using Weblate (Bulgarian)
Currently translated at 35.7% (219 of 612 strings)
2023-11-23 09:54:34 +01:00
Daniel Stasiak
89bac044f1 Translated using Weblate (Polish)
Currently translated at 85.5% (13924 of 16269 strings)
2023-11-23 09:54:34 +01:00
Ranforingus
dc933ba225 Translated using Weblate (Dutch)
Currently translated at 6.6% (1082 of 16269 strings)
2023-11-23 09:54:32 +01:00
Kevin Rojas Costa Rica
a7ac2ed657 Translated using Weblate (Spanish)
Currently translated at 82.9% (13497 of 16269 strings)
2023-11-23 09:54:31 +01:00
Ilian Iliev
8453f0e5f5 Translated using Weblate (Bulgarian)
Currently translated at 28.5% (175 of 612 strings)
2023-11-21 21:56:00 +01:00
Ilian Iliev
17f3c75fdf Translated using Weblate (Bulgarian)
Currently translated at 1.2% (199 of 16269 strings)
2023-11-21 21:56:00 +01:00
Daniel Stasiak
4f5952f24c Translated using Weblate (Polish)
Currently translated at 85.5% (13924 of 16269 strings)
2023-11-21 21:55:59 +01:00
Daniel Stasiak
2bf6e4c3b7 Translated using Weblate (Polish)
Currently translated at 85.5% (13924 of 16269 strings)
2023-11-20 08:51:36 +01:00
Ilian Iliev
90cb403196 Translated using Weblate (Bulgarian)
Currently translated at 25.1% (154 of 612 strings)
2023-11-19 21:33:35 +01:00
Ilian Iliev
d59b686d10 Translated using Weblate (Bulgarian)
Currently translated at 1.1% (180 of 16269 strings)
2023-11-19 21:33:34 +01:00
Daniel Stasiak
346187a80f Translated using Weblate (Polish)
Currently translated at 85.5% (13924 of 16269 strings)
2023-11-18 19:07:26 +01:00
Daniel Stasiak
f8b38d88aa Translated using Weblate (Polish)
Currently translated at 85.5% (13924 of 16269 strings)
2023-11-17 04:52:48 +01:00
Nut.andor
ad4432a2df Announcement 2023-11-16 22:49:16 +01:00
Mateusz Mendel
bf20d0dc6e Translated using Weblate (Polish)
Currently translated at 85.5% (13921 of 16269 strings)
2023-11-16 04:10:47 +01:00
Daniel Stasiak
d940229581 Translated using Weblate (Polish)
Currently translated at 85.5% (13921 of 16269 strings)
2023-11-16 04:10:47 +01:00
Daniel Stasiak
044c6fa4b1 Translated using Weblate (Polish)
Currently translated at 85.5% (13920 of 16269 strings)
2023-11-14 23:54:40 +01:00
Daniel Stasiak
d2b1e67bac Translated using Weblate (Polish)
Currently translated at 85.5% (13920 of 16269 strings)
2023-11-13 22:59:42 +01:00
Daniel Stasiak
7bb42e98b6 Translated using Weblate (Polish)
Currently translated at 85.5% (13920 of 16269 strings)
2023-11-13 12:56:11 +01:00
Daniel Stasiak
ea80cd11fe Translated using Weblate (Polish)
Currently translated at 85.5% (13920 of 16269 strings)
2023-11-12 17:13:48 +01:00
Jacque Fresco
1f00f4a86c Translated using Weblate (Malay)
Currently translated at 3.5% (579 of 16269 strings)
2023-11-12 17:13:45 +01:00
Nut.andor
12350f3fdb whatsNew 2023-11-12 01:10:43 +01:00
Nut.andor
c650e4aa75 whatsNew 2023-11-12 01:10:43 +01:00
Nut.andor
94f81db7ba Forum Announcement (actual version) 2023-11-12 01:10:43 +01:00
Mohamed Amaadour
8c80615659 Translated using Weblate (Arabic)
Currently translated at 11.4% (1864 of 16268 strings)
2023-11-10 10:10:40 +01:00
Mohamed Amaadour
bc5e956cb3 Translated using Weblate (Arabic)
Currently translated at 11.4% (1864 of 16268 strings)
2023-11-09 22:51:23 +01:00
Daniel Stasiak
fab9bdc298 Translated using Weblate (Polish)
Currently translated at 85.5% (13920 of 16269 strings)
2023-11-09 22:51:21 +01:00
Mateusz Mendel
1d90db1c1e Translated using Weblate (Polish)
Currently translated at 85.5% (13919 of 16269 strings)
2023-11-09 15:08:12 +01:00
Daniel Stasiak
9c3dd2e671 Translated using Weblate (Polish)
Currently translated at 85.5% (13919 of 16269 strings)
2023-11-09 15:08:12 +01:00
Daniel Stasiak
711285aab2 Translated using Weblate (Polish)
Currently translated at 85.5% (13918 of 16269 strings)
2023-11-09 15:07:43 +01:00
Mateusz Mendel
3d20a43a24 Translated using Weblate (Polish)
Currently translated at 85.5% (13918 of 16269 strings)
2023-11-09 15:07:43 +01:00
Mateusz Mendel
c3c491f72c Translated using Weblate (Polish)
Currently translated at 85.5% (13915 of 16269 strings)
2023-11-09 14:58:25 +01:00
Daniel Stasiak
489dfd55fb Translated using Weblate (Polish)
Currently translated at 85.5% (13915 of 16269 strings)
2023-11-09 14:58:25 +01:00
Daniel Stasiak
b84ffde283 Translated using Weblate (Polish)
Currently translated at 85.5% (13914 of 16269 strings)
2023-11-09 14:51:42 +01:00
Mateusz Mendel
5256868327 Translated using Weblate (Polish)
Currently translated at 85.5% (13914 of 16269 strings)
2023-11-09 14:51:41 +01:00
Mateusz Mendel
606e90e9bd Translated using Weblate (Polish)
Currently translated at 85.5% (13913 of 16269 strings)
2023-11-09 14:50:19 +01:00
Daniel Stasiak
c5b426af13 Translated using Weblate (Polish)
Currently translated at 85.5% (13913 of 16269 strings)
2023-11-09 14:50:18 +01:00
Daniel Stasiak
8ee1bf782c Translated using Weblate (Polish)
Currently translated at 85.5% (13912 of 16269 strings)
2023-11-09 14:37:13 +01:00
Mateusz Mendel
f4651a9bed Translated using Weblate (Polish)
Currently translated at 85.5% (13912 of 16269 strings)
2023-11-09 14:37:13 +01:00
Mateusz Mendel
c7a77f9c99 Translated using Weblate (Polish)
Currently translated at 85.5% (13911 of 16269 strings)
2023-11-09 14:36:13 +01:00
Daniel Stasiak
e42d2fcec8 Translated using Weblate (Polish)
Currently translated at 85.5% (13911 of 16269 strings)
2023-11-09 14:36:13 +01:00
Mateusz Mendel
2173fda575 Translated using Weblate (Polish)
Currently translated at 85.5% (13910 of 16269 strings)
2023-11-09 14:34:32 +01:00
Daniel Stasiak
dccb078060 Translated using Weblate (Polish)
Currently translated at 85.5% (13910 of 16269 strings)
2023-11-09 14:34:32 +01:00
Daniel Stasiak
9bc007349f Translated using Weblate (Polish)
Currently translated at 85.4% (13909 of 16269 strings)
2023-11-09 14:31:02 +01:00
Mateusz Mendel
435865f250 Translated using Weblate (Polish)
Currently translated at 85.4% (13909 of 16269 strings)
2023-11-09 14:31:02 +01:00
Mateusz Mendel
f7e64c5ab9 Translated using Weblate (Polish)
Currently translated at 85.4% (13908 of 16269 strings)
2023-11-09 14:29:53 +01:00
Daniel Stasiak
271a28887f Translated using Weblate (Polish)
Currently translated at 85.4% (13908 of 16269 strings)
2023-11-09 14:29:53 +01:00
Daniel Stasiak
e3955dac3a Translated using Weblate (Polish)
Currently translated at 85.4% (13907 of 16269 strings)
2023-11-09 14:26:46 +01:00
Mateusz Mendel
8971d671fe Translated using Weblate (Polish)
Currently translated at 85.4% (13907 of 16269 strings)
2023-11-09 14:26:46 +01:00
Mateusz Mendel
e03bc105b0 Translated using Weblate (Polish)
Currently translated at 85.4% (13906 of 16269 strings)
2023-11-09 14:26:25 +01:00
Daniel Stasiak
b5381d5d68 Translated using Weblate (Polish)
Currently translated at 85.4% (13906 of 16269 strings)
2023-11-09 14:26:24 +01:00
Mohamed Amaadour
40eb5ca761 Translated using Weblate (Arabic)
Currently translated at 11.4% (1863 of 16268 strings)
2023-11-09 14:25:03 +01:00
Mateusz Mendel
44298bf59d Translated using Weblate (Polish)
Currently translated at 85.4% (13905 of 16269 strings)
2023-11-09 14:25:02 +01:00
Daniel Stasiak
aab4771fcc Translated using Weblate (Polish)
Currently translated at 85.4% (13905 of 16269 strings)
2023-11-09 14:25:02 +01:00
Mateusz Mendel
b6dfb2eb7d Translated using Weblate (Polish)
Currently translated at 85.4% (13902 of 16269 strings)
2023-11-08 20:56:30 +01:00
Daniel Stasiak
1182bd84cd Translated using Weblate (Polish)
Currently translated at 85.4% (13902 of 16269 strings)
2023-11-08 20:56:30 +01:00
Mateusz Mendel
664f285e9a Translated using Weblate (Polish)
Currently translated at 85.4% (13896 of 16269 strings)
2023-11-08 18:41:42 +01:00
Daniel Stasiak
33717be65d Translated using Weblate (Polish)
Currently translated at 85.4% (13896 of 16269 strings)
2023-11-08 18:41:41 +01:00
Daniel Stasiak
eac69a5e67 Translated using Weblate (Polish)
Currently translated at 85.4% (13894 of 16269 strings)
2023-11-08 18:36:24 +01:00
Mateusz Mendel
9597363785 Translated using Weblate (Polish)
Currently translated at 85.4% (13894 of 16269 strings)
2023-11-08 18:36:24 +01:00
Mateusz Mendel
b7a06e04cb Translated using Weblate (Polish)
Currently translated at 85.3% (13890 of 16269 strings)
2023-11-08 13:16:26 +01:00
Lacrom
8984f35240 Translated using Weblate (French)
Currently translated at 95.9% (15603 of 16269 strings)
2023-11-06 10:36:23 +01:00
Nut.andor
4a8f784fd5 generate current translations 2023-11-05 12:09:01 +01:00
Nut.andor
7877fbdca7 Merge branch 'master' into V0.8.8 2023-11-05 11:59:39 +01:00
Nut.andor
2c67adcda2 Merge remote-tracking branch 'hosted.weblate/master' 2023-11-05 11:53:00 +01:00
Palkia
1ff1835feb Translated using Weblate (Spanish)
Currently translated at 82.9% (13495 of 16269 strings)
2023-11-05 08:46:04 +01:00
Nut.andor
6b24efc014 Release Notes 2023-11-05 02:26:37 +01:00
Nut.andor
894bf9ea8d date/time 2023-11-02 20:59:40 +01:00
Nut
dcbb525fb6 show zero ac
show zero ac
2023-11-02 20:59:37 +01:00
Mohamed Amaadour
689f7820eb Translated using Weblate (Arabic)
Currently translated at 11.2% (1830 of 16268 strings)
2023-10-31 16:30:32 +01:00
Mohamed Amaadour
d47f26d038 Translated using Weblate (Arabic)
Currently translated at 11.0% (1793 of 16268 strings)
2023-10-30 20:04:10 +01:00
Hakunek
3c5645156f Translated using Weblate (Polish)
Currently translated at 85.3% (13889 of 16269 strings)
2023-10-30 20:04:08 +01:00
Nut.andor
edd79b4e4e new sprite of Omicron 2023-10-30 01:23:30 +01:00
Mohamed Amaadour
8a95194465 Translated using Weblate (Arabic)
Currently translated at 10.9% (1788 of 16268 strings)
2023-10-29 22:10:42 +01:00
Nut.andor
80b55c1717 date/time addition 2023-10-29 15:29:39 +01:00
Mohamed Amaadour
faca85e283 Translated using Weblate (Arabic)
Currently translated at 10.8% (1758 of 16268 strings)
2023-10-29 05:19:19 +00:00
OMGeeky
40d84d8c78 add documentation to attack hit chance method 2023-10-28 14:10:06 +02:00
OMGeeky
f0988afaa5 Show a zero for AC 2023-10-28 14:09:34 +02:00
Mohamed
03b0ec16de Translated using Weblate (Arabic)
Currently translated at 10.7% (1742 of 16268 strings)
2023-10-28 03:32:33 +02:00
Mohamed
3a31b3d00c Translated using Weblate (Arabic)
Currently translated at 100.0% (612 of 612 strings)
2023-10-28 02:20:34 +02:00
Mohamed
50a697c85a Translated using Weblate (Arabic)
Currently translated at 10.6% (1737 of 16268 strings)
2023-10-28 02:20:34 +02:00
عادل نصري
af77d8e497 Translated using Weblate (Arabic)
Currently translated at 10.6% (1737 of 16268 strings)
2023-10-28 02:20:34 +02:00
Nut.andor
c6b80f1ff1 more teleport buttons 2023-10-27 00:40:29 +02:00
Sven Knoblach
edbccb62e5 Translated using Weblate (German)
Currently translated at 89.6% (14589 of 16269 strings)
2023-10-26 22:50:07 +02:00
Nut.andor
24a7578c67 vegetable added 2023-10-23 23:39:38 +02:00
Nut.andor
200e44ad15 debug certificate for easier debugging 2023-10-21 19:06:55 +02:00
Nut.andor
ac669f4aaa some debug messages 2023-10-21 18:56:31 +02:00
Nut.andor
f73d993934 Merge branch 'pulls/1829009049/62' into V0.8.8 2023-10-19 22:10:30 +02:00
Nut.andor
15657d08da Rats are too pink. 2023-10-19 22:08:54 +02:00
Raphi
b0829d7195 Translated using Weblate (German)
Currently translated at 89.6% (14589 of 16269 strings)
2023-10-17 04:18:20 +00:00
Nut.andor
e31cee7fef Pull Request #62: Rats are too pink. 2023-10-17 00:55:58 +02:00
Omicronrg9
ec2f4d74b2 • Tweaked some sprites (rats). 2023-10-17 00:53:19 +02:00
Reinhard Lackner
773a9dbbe3 Translated using Weblate (German)
Currently translated at 88.8% (14455 of 16269 strings)
2023-10-15 23:10:16 +02:00
Raphi
0de31eefd2 Translated using Weblate (German)
Currently translated at 88.8% (14455 of 16269 strings)
2023-10-15 23:10:16 +02:00
Nut.andor
cd764d4c10 cats 2023-10-14 01:10:56 +02:00
Nut.andor
283418d43a Pull Request #61: Cats 2023-10-14 01:03:36 +02:00
Daniel–Ømicrón Rodríguez García
e99da003d1 Merge branch 'AndorsTrailRelease:V0.8.8' into V0.8.8 2023-10-12 15:20:56 +02:00
Nut.andor
fc29346dee debugmessage 2023-10-11 22:19:10 +02:00
Daniel–Ømicrón Rodríguez García
6ee86d8c56 Merge branch 'AndorsTrailRelease:V0.8.8' into V0.8.8 2023-10-10 13:00:24 +02:00
Nut.andor
5f91d084ed debugmessage 2023-10-10 01:07:20 +02:00
Nut.andor
7989c84723 formatting 2023-10-08 13:36:02 +02:00
Nut.andor
e280ad1423 new engine enhancements 2023-10-08 13:15:42 +02:00
Nut.andor
35b762e891 bold and italic
bold
unordered lists
ode
img
headers
2023-10-08 13:01:27 +02:00
Omicronrg9
b40eb7dc66 Ignored tmx bak files. 2023-10-08 02:33:51 +02:00
Omicronrg9
a3b74eb08a Merge remote-tracking branch 'origin/V0.8.8' into V0.8.8 2023-10-08 02:29:38 +02:00
Mateusz Mendel
6b724c5e8d Translated using Weblate (Polish)
Currently translated at 85.3% (13889 of 16269 strings)
2023-10-07 20:21:47 +02:00
Nut.andor
a407260c33 Enhance log for better bug finding
sprite definitions again
2023-10-07 18:35:45 +02:00
Nut.andor
e0dc8e24b6 Revert "Auxiliary commit to revert individual files from c54ade42d967b775992c05117933cf7bead7b8c8"
This reverts commit 16f38a2e0dea0b8d1e887f5f0d06aefa2ebe7ef9.
2023-10-07 17:50:46 +02:00
Nut.andor
fcb21a1218 sprite definitions 2023-10-07 14:57:36 +02:00
Nut.andor
c54ade42d9 sprites for Erumentemple 2023-10-07 13:41:26 +02:00
Nut.andor
5460d52baf Merge branch 'pulls/1829009049/60' into V0.8.8 2023-10-07 13:30:11 +02:00
Nut.andor
84c5242195 • map_transition_6 completed (just 1 tile) 2023-10-07 13:27:43 +02:00
Mateusz Mendel
278e61cf7e Translated using Weblate (Polish)
Currently translated at 85.3% (13889 of 16269 strings)
2023-10-05 15:20:39 +02:00
Palkia
7537309cd3 Translated using Weblate (Spanish)
Currently translated at 82.9% (13489 of 16269 strings)
2023-10-05 15:20:38 +02:00
Kevin Rojas Costa Rica
7dc2bcaa59 Translated using Weblate (Spanish)
Currently translated at 82.9% (13489 of 16269 strings)
2023-10-05 15:20:37 +02:00
Raphi
1e99c026cb Translated using Weblate (German)
Currently translated at 88.8% (14449 of 16269 strings)
2023-10-05 15:20:36 +02:00
Nut.andor
ae23d99c7f Pull Request #60: • map_transition_6 completed (just 1 tile) 2023-10-04 10:04:50 +02:00
Omicronrg9
a97f3cee64 • map_transition_6 completed (just 1 tile more) 2023-10-04 10:03:32 +02:00
Nut.andor
c0e5f77d53 requirements date/time implementation 2023-10-03 20:41:33 +02:00
Nut.andor
7c8e269b09 Merge branch 'pulls/1829009049/59' into V0.8.8 2023-10-03 18:07:35 +02:00
Nut.andor
87bdd6036a 5 additions to blank tiles in existing spritesheets. 2023-10-03 17:55:30 +02:00
Nut.andor
4d222f7b06 Pull Request #59: 5 additions to blank tiles in existing spritesheets. 2023-10-03 05:16:43 +02:00
Omicronrg9
9b8d0665a1 • 3 variants of Newb's trees. 2023-10-03 05:16:39 +02:00
Erdem Kocamış
498600c6bd Translated using Weblate (Turkish)
Currently translated at 33.8% (5501 of 16269 strings)
2023-10-03 02:34:26 +02:00
Mateusz Mendel
b2031e0f50 Translated using Weblate (Polish)
Currently translated at 85.3% (13889 of 16269 strings)
2023-10-03 02:34:25 +02:00
Kevin Rojas Costa Rica
7536d14a34 Translated using Weblate (Spanish)
Currently translated at 82.3% (13391 of 16269 strings)
2023-10-03 02:34:23 +02:00
Nut.andor
10772abcb4 new requirements: date, dateEquals, time, timeEquals
new rewards: mapchange
2023-10-03 01:26:03 +02:00
Omicronrg9
b5996767c1 • NewbNewb's items added to the spritesheets. 2023-10-03 00:37:40 +02:00
Omicronrg9
1f7adadf78 • Vertical bridge (North-South) in map_bridge_2
• Pickaxe & shovel rusted variants in map_indoor_1
• Cacti high variants in map_plant_1
• Black salt rocks/crystals/remains in map_rock_1
• More shadows in map_trail_1
2023-10-02 01:42:06 +02:00
Erdem Kocamış
810bcff78c Translated using Weblate (Turkish)
Currently translated at 99.6% (610 of 612 strings)
2023-10-01 23:11:37 +02:00
Erdem Kocamış
e953d34d17 Translated using Weblate (Turkish)
Currently translated at 33.8% (5501 of 16269 strings)
2023-10-01 23:11:36 +02:00
Raphi
3b5fe2e622 Translated using Weblate (German)
Currently translated at 88.5% (14404 of 16269 strings)
2023-09-29 15:09:05 +02:00
Nut Andor
9f46492f86 Translated using Weblate (German)
Currently translated at 100.0% (612 of 612 strings)
2023-09-29 15:09:03 +02:00
Eduardo
f1e69677be Translated using Weblate (Portuguese (Brazil))
Currently translated at 90.5% (14733 of 16269 strings)
2023-09-27 08:13:59 +02:00
Mateusz Mendel
17e573a7a9 Translated using Weblate (Polish)
Currently translated at 85.3% (13889 of 16269 strings)
2023-09-24 21:03:15 +00:00
Raphi
4cb6c26363 Translated using Weblate (German)
Currently translated at 87.9% (14311 of 16269 strings)
2023-09-23 11:02:53 +02:00
Raphi
09974c67e4 Translated using Weblate (German)
Currently translated at 87.9% (14301 of 16269 strings)
2023-09-19 20:26:59 +02:00
Palkia
51b0554668 Translated using Weblate (Spanish)
Currently translated at 80.6% (13116 of 16269 strings)
2023-09-19 05:01:52 +00:00
Mateusz Mendel
3c3610d63c Translated using Weblate (Polish)
Currently translated at 85.3% (13889 of 16269 strings)
2023-09-16 21:53:29 +02:00
Eduardo
468ec1ee83 Translated using Weblate (Portuguese (Brazil))
Currently translated at 90.0% (14658 of 16269 strings)
2023-09-13 17:00:30 +02:00
Raphi
dcb6fcb3a6 Translated using Weblate (German)
Currently translated at 87.7% (14275 of 16269 strings)
2023-09-13 17:00:26 +02:00
Nut.andor
9c080c4334 broken bridge 2023-09-12 01:09:28 +02:00
Nut Andor
7b7fefb954 Translated using Weblate (Spanish)
Currently translated at 80.5% (13107 of 16269 strings)
2023-09-10 23:08:29 +02:00
Daniel-Ømicrón Rodríguez Garcí
616e43ce8f Translated using Weblate (Spanish)
Currently translated at 100.0% (612 of 612 strings)
2023-09-10 10:07:42 +02:00
Raphi
318d070e05 Translated using Weblate (German)
Currently translated at 87.6% (14263 of 16269 strings)
2023-09-09 09:29:45 +02:00
Raphi
4a7739a1bf Translated using Weblate (German)
Currently translated at 87.6% (14262 of 16269 strings)
2023-09-08 23:58:59 +02:00
Darren Crowlen
e12250509e Translated using Weblate (Indonesian)
Currently translated at 100.0% (16269 of 16269 strings)
2023-09-07 05:10:44 +02:00
Daniel Stasiak
afb025fd91 Translated using Weblate (Polish)
Currently translated at 85.3% (13886 of 16269 strings)
2023-09-06 15:58:55 +02:00
Daniel Stasiak
8899cb5ea4 Translated using Weblate (Polish)
Currently translated at 85.3% (13886 of 16269 strings)
2023-09-05 19:04:10 +02:00
Darren Crowlen
c6a7bc8c14 Translated using Weblate (Indonesian)
Currently translated at 100.0% (16269 of 16269 strings)
2023-09-05 19:04:07 +02:00
Daniel Stasiak
f2bb6d547b Translated using Weblate (Polish)
Currently translated at 85.3% (13886 of 16269 strings)
2023-09-05 10:42:48 +02:00
Darren Crowlen
1fdcb23d04 Translated using Weblate (Indonesian)
Currently translated at 100.0% (16269 of 16269 strings)
2023-09-05 10:42:45 +02:00
Raphi
131088ad22 Translated using Weblate (German)
Currently translated at 87.6% (14252 of 16269 strings)
2023-09-05 06:25:21 +02:00
Nut.andor
5d3a51e8f2 next version number 2023-09-04 20:42:57 +02:00
Nut.andor
d1cd8a8cef Merge branch 'v0.8.7(new)' 2023-09-04 20:39:10 +02:00
Daniel Stasiak
c2757dcbce Translated using Weblate (Polish)
Currently translated at 85.3% (13886 of 16269 strings)
2023-09-04 11:21:23 +02:00
Darren Crowlen
274ef6a44f Translated using Weblate (Indonesian)
Currently translated at 100.0% (16269 of 16269 strings)
2023-09-03 23:30:14 +02:00
Eduardo
efff180339 Translated using Weblate (Portuguese (Brazil))
Currently translated at 89.8% (14618 of 16269 strings)
2023-09-03 13:48:33 +02:00
Eduardo
8fb51c0647 Translated using Weblate (Portuguese)
Currently translated at 94.4% (578 of 612 strings)
2023-09-03 13:48:30 +02:00
Darren Crowlen
7db9cf50ca Translated using Weblate (Indonesian)
Currently translated at 100.0% (16269 of 16269 strings)
2023-09-03 06:31:19 +02:00
Nut.andor
8128707aa4 release version 2023-09-02 20:23:01 +02:00
Nut.andor
de7740ab14 Merge branch 'master' into v0.8.7(new) 2023-09-02 18:26:32 +02:00
Nut.andor
31633be812 etc 2023-09-02 18:23:59 +02:00
عادل نصري
bcb5d36999 Translated using Weblate (Arabic)
Currently translated at 10.3% (1680 of 16268 strings)
2023-09-02 17:06:23 +02:00
Raphi
7d847dfde5 Translated using Weblate (German)
Currently translated at 87.4% (14229 of 16269 strings)
2023-09-02 17:06:20 +02:00
Nut.andor
b703e774ae fix in/id 2023-09-02 00:55:36 +02:00
Nut.andor
f6207be9d4 translation objects 2023-09-02 00:45:28 +02:00
Nut.andor
7c87c53421 Merge remote-tracking branch 'hosted.weblate/master' 2023-09-02 00:38:28 +02:00
Hosted Weblate
a4ed3688a2 Merge branch 'origin/master' into Weblate. 2023-09-01 23:59:30 +02:00
Nut.andor
6ab8f5f836 fix Indonesian locale renaming in to id 2023-09-01 23:57:45 +02:00
عادل نصري
f9c1724228 Translated using Weblate (Arabic)
Currently translated at 9.8% (1610 of 16268 strings)
2023-09-01 19:35:12 +02:00
ilya
25c77fdf5e Translated using Weblate (Russian)
Currently translated at 100.0% (16269 of 16269 strings)
2023-09-01 19:35:08 +02:00
Eduardo
3bf9c6ae94 Translated using Weblate (Portuguese (Brazil))
Currently translated at 89.6% (14592 of 16269 strings)
2023-09-01 19:35:06 +02:00
Darren Crowlen
0e70b027f5 Translated using Weblate (Indonesian)
Currently translated at 100.0% (16269 of 16269 strings)
2023-09-01 19:35:01 +02:00
Nut.andor
17b17187ff Merge branch 'pulls/1829009049/58' into v0.8.7(new) 2023-08-31 17:51:07 +02:00
Nut.andor
dc226ebe5d rename spawnchance to respawnspeed 2023-08-31 17:35:24 +02:00
Nut.andor
55f5edbb6a Pull Request #58: rename spawnchance to respawnspeed 2023-08-31 17:13:07 +02:00
Nut.andor
29d65fbf64 Merge branch 'master' into v0.8.7(new) 2023-08-31 17:12:12 +02:00
Nut.andor
f3f35be0bf Merge remote-tracking branch 'hosted.weblate/master' 2023-08-31 01:24:10 +02:00
Nut.andor
204c8e046c id to in 2023-08-31 01:23:08 +02:00
Eduardo
1a1710a6c2 Translated using Weblate (Portuguese (Brazil))
Currently translated at 88.4% (14383 of 16269 strings)
2023-08-31 00:09:31 +02:00
Nut.andor
1a2cc00184 translation states 2023-08-30 15:15:31 +02:00
OMGeeky
b3b3f6ff98 rename spawnchance to respawnspeed
This reflects the actual effect it has better
2023-08-30 13:32:57 +02:00
Eduardo
7df8b0330c Translated using Weblate (Portuguese (Brazil))
Currently translated at 88.0% (14324 of 16269 strings)
2023-08-30 09:18:41 +02:00
Palkia
528dd2254e Translated using Weblate (Spanish)
Currently translated at 80.5% (13107 of 16269 strings)
2023-08-30 09:18:38 +02:00
Nut.andor
33fb7c83bf resource def for new png 2023-08-30 01:59:17 +02:00
Nut.andor
50ad382eed potc 2023-08-30 01:17:01 +02:00
Nut.andor
7d1c7cfd74 Merge branch 'v0.8.7(new)' 2023-08-30 00:56:24 +02:00
Nut.andor
5b637099a1 Changes from next_release 2023-08-30 00:40:14 +02:00
Nut.andor
0d6d725f87 debug off 2023-08-30 00:25:08 +02:00
Nut.andor
a98c5d5416 translations and authors 2023-08-30 00:22:59 +02:00
Nut.andor
3361973722 fix updated translations 2023-08-30 00:17:44 +02:00
Nut.andor
91bc6568ee Merge branch 'master' into v0.8.7(new) 2023-08-30 00:13:00 +02:00
Nut.andor
2e583fbfcf Merge remote-tracking branch 'hosted.weblate/master' 2023-08-30 00:08:59 +02:00
Eduardo
50eab6ff38 Translated using Weblate (Portuguese (Brazil))
Currently translated at 87.9% (14305 of 16268 strings)
2023-08-30 00:06:08 +02:00
Nut.andor
d743550cc7 enhanced and reorganized pngs 2023-08-29 23:54:34 +02:00
Eduardo
1c0efc8fa4 Translated using Weblate (Portuguese (Brazil))
Currently translated at 87.4% (14226 of 16268 strings)
2023-08-27 19:43:13 +02:00
Nut.andor
5ff38ea870 New teleport button 'gal' 2023-08-24 19:58:59 +02:00
Nut.andor
4c146f7896 new/added sprites 2023-08-19 03:18:07 +02:00
Nut
4e5aa4314e Merge pull request #57 from OMGeeky/v0.8.7(new)
AndroidX missed spot
2023-08-18 23:09:01 +02:00
OMGeeky
5223951db4 AndroidX missed spot 2023-08-18 21:34:35 +02:00
Nut.andor
ddcb355113 Versions
- next AndroidVersion 34
- 73 = 0.8.7beta
2023-08-18 20:22:29 +02:00
Nut.andor
7a80e15628 typo 2023-08-18 20:06:55 +02:00
Nut
34dc053011 Merge pull request #52 from OMGeeky/gradle-copy-v2
Improvements to the copy Gradle Tasks
2023-08-18 19:52:19 +02:00
Nut
0266449d67 Merge branch 'v0.8.7(new)' into gradle-copy-v2 2023-08-18 19:51:31 +02:00
Nut
ea3afcf99d Merge pull request #50 from OMGeeky/AndroidX-Migration
Android x migration
2023-08-18 19:45:39 +02:00
Nut
c84418186c Merge branch 'v0.8.7(new)' into AndroidX-Migration 2023-08-18 19:44:33 +02:00
Jiri Zizkin Zizka
956990dbd5 Translated using Weblate (Czech)
Currently translated at 89.6% (14583 of 16268 strings)
2023-08-16 03:59:31 +02:00
Hugo Rosa
08f6a2b289 Translated using Weblate (Portuguese (Brazil))
Currently translated at 87.2% (14192 of 16268 strings)
2023-08-11 06:51:38 +02:00
Darren Crowlen
741a4c02a0 Translated using Weblate (French)
Currently translated at 95.5% (15539 of 16268 strings)
2023-08-08 17:52:07 +02:00
Palkia
dcff4939f4 Translated using Weblate (Spanish)
Currently translated at 80.5% (13105 of 16268 strings)
2023-08-08 17:52:05 +02:00
Raphi
506ce02697 Translated using Weblate (German)
Currently translated at 87.4% (14228 of 16268 strings)
2023-08-06 18:08:28 +02:00
Raphi
95bd17b371 Translated using Weblate (German)
Currently translated at 87.4% (14228 of 16268 strings)
2023-08-06 12:10:47 +02:00
Salif Mehmed
16ef7088a6 Translated using Weblate (Bulgarian)
Currently translated at 0.5% (92 of 16268 strings)
2023-08-06 02:13:38 +02:00
Darren Crowlen
f70b0c8a41 Translated using Weblate (Indonesian)
Currently translated at 100.0% (16268 of 16268 strings)
2023-08-06 02:13:35 +02:00
Nut Andor
d68d45d7c7 Translated using Weblate (German)
Currently translated at 87.4% (14228 of 16268 strings)
2023-08-06 02:13:32 +02:00
Vanka
7af2844305 Translated using Weblate (German)
Currently translated at 87.4% (14228 of 16268 strings)
2023-08-06 02:13:31 +02:00
Raphi
fd8c5166b6 Translated using Weblate (German)
Currently translated at 87.4% (14228 of 16268 strings)
2023-08-06 02:13:31 +02:00
Andreas
2c931b6cd2 Translated using Weblate (German)
Currently translated at 100.0% (612 of 612 strings)
2023-08-06 02:13:26 +02:00
Raphi
210069f8e9 Translated using Weblate (German)
Currently translated at 100.0% (612 of 612 strings)
2023-08-06 02:13:26 +02:00
Darren Crowlen
2453897d31 Translated using Weblate (Indonesian)
Currently translated at 100.0% (16268 of 16268 strings)
2023-08-02 20:53:45 +02:00
Darren Crowlen
dc0e758f64 Translated using Weblate (Indonesian)
Currently translated at 93.5% (15224 of 16268 strings)
2023-08-02 06:52:03 +02:00
Darren Crowlen
ac3bf4a008 Translated using Weblate (Bulgarian)
Currently translated at 0.5% (92 of 16268 strings)
2023-07-31 22:51:24 +02:00
Darren Crowlen
caf16299e7 Translated using Weblate (Indonesian)
Currently translated at 73.8% (12020 of 16268 strings)
2023-07-31 22:51:21 +02:00
Darren Crowlen
cfa19ed9d9 Translated using Weblate (Belarusian)
Currently translated at 0.3% (56 of 16267 strings)
2023-07-31 17:04:04 +02:00
Darren Crowlen
6e5d82f340 Translated using Weblate (Arabic)
Currently translated at 9.6% (1567 of 16267 strings)
2023-07-31 17:04:02 +02:00
Jiri Zizkin Zizka
98456b99e8 Translated using Weblate (Czech)
Currently translated at 89.6% (14581 of 16268 strings)
2023-07-31 17:03:59 +02:00
Darren Crowlen
45c6e571cb Translated using Weblate (Indonesian)
Currently translated at 67.5% (10996 of 16268 strings)
2023-07-31 17:03:56 +02:00
Darren Crowlen
e6c5545cd3 Translated using Weblate (French)
Currently translated at 95.4% (15533 of 16268 strings)
2023-07-31 17:02:31 +02:00
LeJun
402c3ae538 Translated using Weblate (French)
Currently translated at 95.4% (15533 of 16268 strings)
2023-07-31 17:02:30 +02:00
Seven
f6018ab466 Translated using Weblate (Spanish (Argentina))
Currently translated at 0.3% (52 of 16267 strings)
2023-07-27 20:07:11 +02:00
Darren Crowlen
0ff738c85e Translated using Weblate (Indonesian)
Currently translated at 100.0% (612 of 612 strings)
2023-07-27 20:07:09 +02:00
Darren Crowlen
4876e6696d Translated using Weblate (Indonesian)
Currently translated at 21.6% (3518 of 16268 strings)
2023-07-27 20:07:09 +02:00
Palkia
167da0d70f Translated using Weblate (Spanish)
Currently translated at 80.4% (13080 of 16268 strings)
2023-07-27 20:07:00 +02:00
Seven
2748aded3f Translated using Weblate (Spanish)
Currently translated at 80.4% (13080 of 16268 strings)
2023-07-27 20:06:59 +02:00
ilya
103434baa0 Translated using Weblate (Russian)
Currently translated at 100.0% (16268 of 16268 strings)
2023-07-22 21:08:17 +02:00
Palkia
c2da7bcbe2 Translated using Weblate (Spanish)
Currently translated at 79.7% (12981 of 16268 strings)
2023-07-16 06:42:02 +02:00
عادل نصري
c64cf99d88 Translated using Weblate (Arabic)
Currently translated at 100.0% (612 of 612 strings)
2023-07-03 11:52:56 +02:00
Nut.andor
de59d8de8d Revert "worldmap bug check"
This reverts commit 718886ba3a.
2023-06-25 18:43:12 +02:00
Nut.andor
718886ba3a worldmap bug check 2023-06-25 13:27:09 +02:00
عادل نصري
3789f1fd0a Translated using Weblate (Arabic)
Currently translated at 100.0% (612 of 612 strings)
2023-06-24 08:41:19 +02:00
عادل نصري
1e6df02e45 Translated using Weblate (Arabic)
Currently translated at 9.4% (1543 of 16267 strings)
2023-06-24 08:41:18 +02:00
Jiri Zizkin Zizka
886a425aaf Translated using Weblate (Czech)
Currently translated at 89.3% (14542 of 16268 strings)
2023-06-24 08:41:14 +02:00
Jiri Zizkin Zizka
7e24d50c0c Translated using Weblate (Czech)
Currently translated at 89.3% (14535 of 16268 strings)
2023-06-13 07:14:38 +02:00
Jiri Zizkin Zizka
8f7d48c297 Translated using Weblate (Czech)
Currently translated at 89.3% (14531 of 16268 strings)
2023-06-12 12:57:53 +02:00
Jiri Zizkin Zizka
3cc81e2510 Translated using Weblate (Czech)
Currently translated at 89.3% (14528 of 16268 strings)
2023-06-11 11:53:28 +02:00
Nifou
0f0be1c18e Translated using Weblate (French)
Currently translated at 95.3% (15511 of 16268 strings)
2023-06-11 11:53:26 +02:00
A-Nicoladie[FR]
5f689e3d6c Translated using Weblate (French)
Currently translated at 95.3% (15511 of 16268 strings)
2023-06-11 11:53:25 +02:00
Jiri Zizkin Zizka
f04d3e40d4 Translated using Weblate (Czech)
Currently translated at 89.2% (14524 of 16268 strings)
2023-06-08 23:53:02 +02:00
Jiri Zizkin Zizka
68a74e07fa Translated using Weblate (Czech)
Currently translated at 89.2% (14516 of 16268 strings)
2023-06-07 09:53:06 +02:00
A-Nicoladie[FR]
199cdbb787 Translated using Weblate (French)
Currently translated at 93.6% (15227 of 16268 strings)
2023-06-07 09:53:03 +02:00
Jiri Zizkin Zizka
375fcb37a2 Translated using Weblate (Czech)
Currently translated at 89.2% (14514 of 16268 strings)
2023-06-04 01:18:50 +02:00
Rahul Shirke
bc1743dedf Translated using Weblate (Marathi)
Currently translated at 0.2% (40 of 16267 strings)
2023-06-02 15:00:22 +02:00
Rahul Shirke
f7771f79c2 Translated using Weblate (Marathi)
Currently translated at 0.2% (35 of 16267 strings)
2023-06-02 06:53:04 +02:00
gallegonovato
7ebce6b36b Translated using Weblate (Spanish)
Currently translated at 100.0% (612 of 612 strings)
2023-06-02 06:53:01 +02:00
Rahul Shirke
b4240eee3a Added translation using Weblate (Marathi) 2023-06-01 05:20:12 +02:00
Andreas
514acc2b65 Translated using Weblate (German)
Currently translated at 87.0% (14162 of 16268 strings)
2023-05-31 12:51:33 +02:00
Andreas
48bc854c8a Translated using Weblate (German)
Currently translated at 99.8% (611 of 612 strings)
2023-05-31 12:51:30 +02:00
Nut Andor
07391dc6c7 Translated using Weblate (German)
Currently translated at 99.8% (611 of 612 strings)
2023-05-31 12:51:29 +02:00
Jiri Zizkin Zizka
7e905e84b7 Translated using Weblate (Czech)
Currently translated at 89.2% (14513 of 16268 strings)
2023-05-30 00:51:29 +02:00
A-Nicoladie[FR]
200a45f0cb Translated using Weblate (French)
Currently translated at 86.5% (14075 of 16268 strings)
2023-05-30 00:51:25 +02:00
A-Nicoladie[FR]
ebff0554f7 Translated using Weblate (French)
Currently translated at 100.0% (612 of 612 strings)
2023-05-30 00:51:16 +02:00
Jiri Zizkin Zizka
e54487d0b0 Translated using Weblate (Czech)
Currently translated at 88.9% (14478 of 16268 strings)
2023-05-28 09:47:10 +02:00
A-Nicoladie[FR]
96a6e7ab20 Translated using Weblate (French)
Currently translated at 82.2% (13376 of 16268 strings)
2023-05-28 09:47:06 +02:00
A-Nicoladie[FR]
95ff8ceb7e Translated using Weblate (French)
Currently translated at 78.9% (12845 of 16268 strings)
2023-05-27 11:05:28 +02:00
Jiri Zizkin Zizka
5aa4308e27 Translated using Weblate (Czech)
Currently translated at 88.8% (14451 of 16268 strings)
2023-05-26 23:49:05 +02:00
Nico207[FR]
aa892be308 Translated using Weblate (French)
Currently translated at 78.5% (12771 of 16268 strings)
2023-05-26 23:49:02 +02:00
ilya
6971bcf9b5 Translated using Weblate (Russian)
Currently translated at 100.0% (612 of 612 strings)
2023-05-26 23:48:59 +02:00
Nico207[FR]
0581e98b55 Translated using Weblate (French)
Currently translated at 100.0% (612 of 612 strings)
2023-05-26 23:48:58 +02:00
Nico207[FR]
5c2e653cdf Translated using Weblate (French)
Currently translated at 78.3% (12750 of 16268 strings)
2023-05-25 22:04:03 +02:00
aircqsj
aa4cd722d2 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (16268 of 16268 strings)
2023-05-25 14:30:36 +02:00
Nico207[FR]
10b2f37ed8 Translated using Weblate (French)
Currently translated at 78.3% (12749 of 16268 strings)
2023-05-25 14:30:30 +02:00
Nico207[FR]
d7ae2a7082 Translated using Weblate (French)
Currently translated at 95.7% (586 of 612 strings)
2023-05-25 14:30:18 +02:00
Jiri Zizkin Zizka
c246a79726 Translated using Weblate (Czech)
Currently translated at 88.8% (14448 of 16268 strings)
2023-05-25 08:52:20 +02:00
ilya
8e4d75705e Translated using Weblate (Russian)
Currently translated at 100.0% (16268 of 16268 strings)
2023-05-25 08:52:15 +02:00
Jiri Zizkin Zizka
ffdaba2d8c Translated using Weblate (Czech)
Currently translated at 88.4% (14387 of 16268 strings)
2023-05-23 13:53:32 +02:00
aircqsj
97187071af Translated using Weblate (Chinese (Simplified))
Currently translated at 99.9% (16264 of 16268 strings)
2023-05-23 13:53:28 +02:00
ilya
dceab6b729 Translated using Weblate (Russian)
Currently translated at 96.9% (15771 of 16268 strings)
2023-05-23 13:53:24 +02:00
Mateusz Mendel
7771872947 Translated using Weblate (Polish)
Currently translated at 85.3% (13884 of 16268 strings)
2023-05-23 13:53:17 +02:00
Nut.andor
cc123f76d6 whatsnew 2023-05-21 20:12:38 +02:00
Nut.andor
a6ad03c534 next version 8.7
(the former 8.7 version was renamed to 8.6.1)
2023-05-21 19:50:13 +02:00
Nut.andor
45491871e6 version 2023-05-21 18:17:44 +02:00
Nut.andor
8988f37896 potc 2023-05-21 10:33:03 +02:00
Nut.andor
09b4324873 Merge branch 'v0.8.7' 2023-05-21 10:27:32 +02:00
Nut.andor
a5a2764cb4 whatsnew 2023-05-21 10:26:44 +02:00
Nut.andor
6de4d0c374 Merge remote-tracking branch 'hosted.weblate/master' 2023-05-21 10:05:40 +02:00
Nut.andor
48c33d766b fix quest "More rats!" 2023-05-21 10:03:23 +02:00
Nut Andor
22493ee0e9 Translated using Weblate (German)
Currently translated at 86.9% (14148 of 16267 strings)
2023-05-21 10:00:28 +02:00
Nut Andor
8afc3133c6 Translated using Weblate (German)
Currently translated at 99.8% (611 of 612 strings)
2023-05-21 10:00:24 +02:00
Jiri Zizkin Zizka
d0cfa29929 Translated using Weblate (Czech)
Currently translated at 88.2% (14358 of 16267 strings)
2023-05-19 04:13:15 +02:00
Ömer Faruk Çakmak
6a51d462d7 Translated using Weblate (Turkish)
Currently translated at 33.7% (5483 of 16267 strings)
2023-05-18 21:54:14 +02:00
Jiri Zizkin Zizka
4f7cc4942c Translated using Weblate (Czech)
Currently translated at 88.1% (14336 of 16267 strings)
2023-05-15 21:55:38 +02:00
Nut.andor
6631e01b64 next version 8.7 2023-05-14 23:14:04 +02:00
Nut.andor
133dffe330 whatsnew 2023-05-13 22:22:26 +02:00
Nut.andor
6e5d17173f potc 2023-05-13 22:13:10 +02:00
Nut.andor
7463d15159 Merge branch 'v0.8.6' 2023-05-13 22:07:16 +02:00
Nut.andor
beff0f1b71 Merge remote-tracking branch 'hosted.weblate/master' 2023-05-13 22:01:01 +02:00
Nut.andor
867ed36419 Ratdom bugfix content 2023-05-13 21:55:06 +02:00
Joan Josep
387c1e126f Translated using Weblate (Catalan)
Currently translated at 100.0% (612 of 612 strings)
2023-05-13 21:49:32 +02:00
Joan Josep
c9d7cda233 Translated using Weblate (Catalan)
Currently translated at 15.4% (2515 of 16264 strings)
2023-05-13 21:49:31 +02:00
ilya
b75521da59 Translated using Weblate (Russian)
Currently translated at 95.4% (15532 of 16264 strings)
2023-05-12 10:54:34 +02:00
aircqsj
5f9ee8a410 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (612 of 612 strings)
2023-05-11 08:51:18 +02:00
aircqsj
296c3b453c Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (16264 of 16264 strings)
2023-05-11 08:51:18 +02:00
aircqsj
6e2da63308 Translated using Weblate (Chinese (Simplified))
Currently translated at 99.9% (16262 of 16264 strings)
2023-05-09 17:53:16 +02:00
ilya
445cd9fe8e Translated using Weblate (Russian)
Currently translated at 95.2% (15496 of 16264 strings)
2023-05-09 17:52:52 +02:00
Erick Ferraz Vieira
a0cc567694 Translated using Weblate (Portuguese (Brazil))
Currently translated at 87.2% (14191 of 16264 strings)
2023-05-09 17:52:48 +02:00
Erick Ferraz Vieira
70d084fba7 Translated using Weblate (Portuguese)
Currently translated at 71.4% (11618 of 16264 strings)
2023-05-09 17:52:45 +02:00
Erick Ferraz Vieira
5236aa0bf9 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (612 of 612 strings)
2023-05-09 17:52:42 +02:00
Nut.andor
0eccb511db next version 2023-05-06 03:07:07 +02:00
Kristoffer Grundström
88c17db72b Translated using Weblate (Swedish)
Currently translated at 4.2% (690 of 16264 strings)
2023-05-03 01:48:24 +02:00
ilya
098fb95653 Translated using Weblate (Russian)
Currently translated at 93.1% (15146 of 16264 strings)
2023-05-03 01:48:21 +02:00
ilya
21d6bb7b7d Translated using Weblate (Russian)
Currently translated at 100.0% (612 of 612 strings)
2023-05-03 01:48:18 +02:00
Daniel Stasiak
ce91c5c7c8 Translated using Weblate (Polish)
Currently translated at 100.0% (612 of 612 strings)
2023-05-03 01:48:17 +02:00
Nut.andor
613ab9101e postfixes 2023-05-02 22:26:35 +02:00
Nut.andor
3fbc7cf65f authors + translation% 2023-05-01 20:57:16 +02:00
Nut.andor
dc18289d18 POTC 2023-05-01 03:03:36 +02:00
Nut.andor
6473e231e4 Mikhail basket 2023-05-01 02:56:49 +02:00
Nut.andor
33a61b7a57 Merge branch 'v0.8.5' 2023-05-01 02:09:07 +02:00
Nut.andor
c070a39f7c Ratdom content 2023-05-01 02:00:00 +02:00
Nut.andor
995ec0f697 active devs 2023-05-01 01:58:18 +02:00
Nut.andor
6cba6872c9 version name 2023-05-01 01:17:20 +02:00
Nut.andor
8812f664e7 authors 2023-05-01 01:15:09 +02:00
Nut.andor
d9113b2dab Merge branch 'master' into v0.8.5 2023-05-01 01:03:25 +02:00
Nut.andor
ad0025ba03 Merge remote-tracking branch 'hosted.weblate/master' 2023-05-01 00:56:15 +02:00
Nut.andor
984aa17cc0 Merge branch 'development' into v0.8.5 2023-05-01 00:45:33 +02:00
Seven
4cad05ce6b Translated using Weblate (Spanish (Argentina))
Currently translated at 0.3% (49 of 15108 strings)
2023-04-29 05:05:40 +02:00
Jiri Zizkin Zizka
197ab946be Translated using Weblate (Czech)
Currently translated at 94.5% (14291 of 15109 strings)
2023-04-29 05:05:37 +02:00
Daniel Stasiak
e4cdbc1840 Translated using Weblate (Polish)
Currently translated at 91.8% (13884 of 15109 strings)
2023-04-29 05:05:34 +02:00
Seven
04f00553ae Translated using Weblate (Spanish)
Currently translated at 84.4% (12763 of 15109 strings)
2023-04-29 05:05:30 +02:00
Daniel Stasiak
0c02902ceb Translated using Weblate (Polish)
Currently translated at 91.8% (13884 of 15109 strings)
2023-04-26 11:24:53 +02:00
Seven
aba93fb15b Translated using Weblate (Spanish)
Currently translated at 84.3% (12740 of 15109 strings)
2023-04-26 11:24:50 +02:00
Seven
1c8330b99a Translated using Weblate (Spanish)
Currently translated at 100.0% (610 of 610 strings)
2023-04-25 19:50:01 +02:00
Seven
a8de7c2860 Translated using Weblate (Spanish)
Currently translated at 84.2% (12727 of 15109 strings)
2023-04-25 19:50:00 +02:00
Seven
4ca8bbfc12 Translated using Weblate (Spanish)
Currently translated at 84.0% (12700 of 15109 strings)
2023-04-25 18:53:44 +02:00
Daniel Stasiak
a5c004e4d4 Translated using Weblate (Polish)
Currently translated at 91.8% (13884 of 15109 strings)
2023-04-25 18:19:25 +02:00
Seven
e957e409e0 Translated using Weblate (Spanish)
Currently translated at 83.9% (12684 of 15109 strings)
2023-04-25 18:19:21 +02:00
Jiri Zizkin Zizka
70d6340c11 Translated using Weblate (Czech)
Currently translated at 94.5% (14280 of 15109 strings)
2023-04-22 22:53:01 +02:00
Jiri Zizkin Zizka
bbbb69b175 Translated using Weblate (Czech)
Currently translated at 94.4% (14273 of 15109 strings)
2023-04-21 20:37:11 +02:00
ilya
4d5b7d8667 Translated using Weblate (Russian)
Currently translated at 100.0% (15109 of 15109 strings)
2023-04-21 20:37:08 +02:00
Daniel Stasiak
43da08f57d Translated using Weblate (Polish)
Currently translated at 91.8% (13884 of 15109 strings)
2023-04-21 20:37:04 +02:00
Jiri Zizkin Zizka
7b97367bdd Translated using Weblate (Czech)
Currently translated at 94.4% (14272 of 15109 strings)
2023-04-19 21:55:23 +02:00
Daniel Stasiak
e6fb647b99 Translated using Weblate (Polish)
Currently translated at 91.8% (13884 of 15109 strings)
2023-04-19 21:55:21 +02:00
Daniel Stasiak
5e4d7aba18 Translated using Weblate (Polish)
Currently translated at 91.8% (13884 of 15109 strings)
2023-04-18 10:35:09 +02:00
Daniel Stasiak
a96086b9af Translated using Weblate (Polish)
Currently translated at 91.8% (13884 of 15109 strings)
2023-04-17 21:14:23 +02:00
Joan Josep
0566cf899c Translated using Weblate (Catalan)
Currently translated at 100.0% (610 of 610 strings)
2023-04-17 12:49:15 +02:00
Jiri Zizkin Zizka
c8e87fb3d0 Translated using Weblate (Czech)
Currently translated at 94.4% (14265 of 15109 strings)
2023-04-17 12:49:14 +02:00
Nut.andor
0a56a0ba86 Credits for external products 2023-04-16 19:58:58 +02:00
Nut.andor
026ccde2ff Credits for external products 2023-04-16 10:33:28 +02:00
Nut.andor
7813994b81 Release Notes 2023-04-16 09:52:04 +02:00
Nut.andor
d3b070844f set high quality filters default to off 2023-04-16 09:18:45 +02:00
Emre Kaynak
7a879f99b1 Translated using Weblate (Turkish)
Currently translated at 97.5% (595 of 610 strings)
2023-04-16 06:51:16 +02:00
Jiri Zizkin Zizka
e810cdb3cb Translated using Weblate (Czech)
Currently translated at 94.3% (14257 of 15109 strings)
2023-04-16 06:51:15 +02:00
Emre Kaynak
398be07c31 Translated using Weblate (Turkish)
Currently translated at 36.1% (5455 of 15109 strings)
2023-04-16 06:51:13 +02:00
sefa mert katiç
6db4c7bb3c Translated using Weblate (Turkish)
Currently translated at 36.0% (5449 of 15109 strings)
2023-04-14 23:53:02 +02:00
Sarah Chiandotto
c402824641 Translated using Weblate (Italian)
Currently translated at 83.4% (12602 of 15109 strings)
2023-04-14 23:53:00 +02:00
Martin
abc020e8f5 Translated using Weblate (German)
Currently translated at 93.6% (14148 of 15109 strings)
2023-04-14 23:52:57 +02:00
sefa mert katiç
82caf260ce Translated using Weblate (Turkish)
Currently translated at 35.8% (5417 of 15109 strings)
2023-04-12 00:53:21 +02:00
Renald Afrenzia
cbcf5ff8ca Translated using Weblate (Indonesian)
Currently translated at 96.0% (586 of 610 strings)
2023-04-11 01:47:48 +02:00
Jiri Zizkin Zizka
39d07bf8a8 Translated using Weblate (Czech)
Currently translated at 94.2% (14245 of 15109 strings)
2023-04-11 01:47:47 +02:00
Lucas Araujo
93174f0d65 Translated using Weblate (Portuguese (Brazil))
Currently translated at 93.7% (14166 of 15109 strings)
2023-04-09 12:53:09 +02:00
Joan Josep
6afbeb9a2a Translated using Weblate (Catalan)
Currently translated at 100.0% (610 of 610 strings)
2023-04-08 11:52:57 +02:00
Lucas Araujo
a7cbd644f3 Translated using Weblate (Portuguese (Brazil))
Currently translated at 93.7% (14164 of 15109 strings)
2023-04-08 11:52:56 +02:00
Joan Josep
f674aff07c Translated using Weblate (Catalan)
Currently translated at 100.0% (610 of 610 strings)
2023-04-07 20:53:14 +02:00
Joan Josep
07b89a288c Translated using Weblate (Catalan)
Currently translated at 16.5% (2493 of 15109 strings)
2023-04-07 20:53:12 +02:00
Joan Josep
0264c418ca Translated using Weblate (Catalan)
Currently translated at 100.0% (610 of 610 strings)
2023-04-05 20:53:10 +02:00
Jiri Zizkin Zizka
494b9c47cc Translated using Weblate (Czech)
Currently translated at 94.1% (14225 of 15109 strings)
2023-04-05 20:53:09 +02:00
Pablo Jeldres
6ff6c6dd6c Translated using Weblate (Spanish)
Currently translated at 83.8% (12670 of 15109 strings)
2023-04-05 20:53:06 +02:00
Jiri Zizkin Zizka
00ab587265 Translated using Weblate (Czech)
Currently translated at 94.1% (14219 of 15109 strings)
2023-04-03 20:41:57 +02:00
Hong Quan
67fa480805 Translated using Weblate (Vietnamese)
Currently translated at 12.4% (76 of 610 strings)
2023-04-02 17:41:39 +02:00
Lucas Araujo
91db56e7a7 Translated using Weblate (Portuguese (Brazil))
Currently translated at 93.7% (14164 of 15109 strings)
2023-04-02 17:41:38 +02:00
Cicy Chen
36d52bedad Added translation using Weblate (Chinese (Literary)) 2023-03-31 06:27:20 +02:00
Hong Quan
c36b676720 Translated using Weblate (Vietnamese)
Currently translated at 1.4% (9 of 610 strings)
2023-03-29 15:40:40 +02:00
Lustheart Faezeiros
5e0a999249 Translated using Weblate (Thai)
Currently translated at 12.7% (78 of 610 strings)
2023-03-29 15:40:40 +02:00
Jiri Zizkin Zizka
8fff4aff60 Translated using Weblate (Czech)
Currently translated at 94.1% (14218 of 15109 strings)
2023-03-29 15:40:39 +02:00
Lustheart Faezeiros
8c5344ff37 Translated using Weblate (Thai)
Currently translated at 1.2% (195 of 15109 strings)
2023-03-29 15:40:36 +02:00
ssantos
91e49b6c4a Translated using Weblate (Portuguese)
Currently translated at 76.8% (11618 of 15109 strings)
2023-03-29 15:40:34 +02:00
Hong Quan
52cfb37b21 Added translation using Weblate (Vietnamese) 2023-03-27 16:12:56 +02:00
DragonChen TW
87886f08bb Translated using Weblate (Chinese (Traditional))
Currently translated at 6.6% (998 of 15109 strings)
2023-03-26 11:32:21 +02:00
Jiri Zizkin Zizka
a31d7f9589 Translated using Weblate (Czech)
Currently translated at 93.9% (14198 of 15109 strings)
2023-03-26 11:32:19 +02:00
DragonChen TW
5600957f32 Translated using Weblate (Chinese (Traditional))
Currently translated at 6.5% (996 of 15109 strings)
2023-03-25 11:39:22 +01:00
ilya
d6840a83c9 Translated using Weblate (Russian)
Currently translated at 100.0% (610 of 610 strings)
2023-03-25 11:39:20 +01:00
DragonChen TW
06fdd39648 Translated using Weblate (Chinese (Traditional))
Currently translated at 6.5% (990 of 15109 strings)
2023-03-23 22:42:13 +01:00
ilya
b5763e7f76 Translated using Weblate (Russian)
Currently translated at 100.0% (610 of 610 strings)
2023-03-23 22:42:10 +01:00
DragonChen TW
75f01f20b9 Translated using Weblate (Chinese (Traditional))
Currently translated at 6.4% (979 of 15109 strings)
2023-03-22 14:12:10 +01:00
Hong Quan
dd366ab69e Translated using Weblate (Vietnamese)
Currently translated at 0.1% (3 of 15108 strings)
2023-03-21 21:24:23 +01:00
DragonChen TW
6ab443ec2c Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (610 of 610 strings)
2023-03-21 21:24:21 +01:00
DragonChen TW
e0056cbf5c Translated using Weblate (Chinese (Traditional))
Currently translated at 6.4% (978 of 15109 strings)
2023-03-21 21:24:20 +01:00
ilya
9f9397e1f3 Translated using Weblate (Russian)
Currently translated at 100.0% (610 of 610 strings)
2023-03-21 21:24:18 +01:00
Hong Quan
d5a43cc7e1 Added translation using Weblate (Vietnamese) 2023-03-20 17:34:05 +01:00
DragonChen TW
408d8aa8b8 Translated using Weblate (Chinese (Traditional))
Currently translated at 97.5% (595 of 610 strings)
2023-03-19 08:40:41 +01:00
DragonChen TW
1e663069e8 Translated using Weblate (Chinese (Traditional))
Currently translated at 6.4% (977 of 15109 strings)
2023-03-19 08:40:40 +01:00
Nut.andor
dbcec1a199 James' PR 54 to master - redirected to branch development
Changed XP death penalty to 20%
Give the player 9 BC by default
2023-03-18 18:53:53 +01:00
Noza
04b4193548 Translated using Weblate (Indonesian)
Currently translated at 17.0% (2580 of 15109 strings)
2023-03-14 19:44:12 +01:00
Jiri Zizkin Zizka
058803184f Translated using Weblate (Czech)
Currently translated at 93.7% (14170 of 15109 strings)
2023-03-10 22:41:53 +01:00
Jiri Zizkin Zizka
5b5912c5bc Translated using Weblate (Czech)
Currently translated at 93.7% (14170 of 15109 strings)
2023-03-09 21:42:07 +01:00
Lacrom
759e632c07 Translated using Weblate (French)
Currently translated at 84.3% (12739 of 15109 strings)
2023-03-08 16:42:04 +01:00
Johny The Pvp God
6e311ecb64 Translated using Weblate (Romanian)
Currently translated at 56.2% (343 of 610 strings)
2023-03-07 00:41:35 +01:00
Jiri Zizkin Zizka
b480fd9173 Translated using Weblate (Czech)
Currently translated at 93.7% (14170 of 15109 strings)
2023-03-07 00:41:35 +01:00
Nut.andor
226459ddb8 skill improve text clarified 2023-03-05 18:05:46 +01:00
BE Kharel
92de033bc8 Translated using Weblate (Arabic)
Currently translated at 9.6% (1459 of 15108 strings)
2023-03-04 11:41:54 +01:00
BE Kharel
faf0dd061c Translated using Weblate (Bulgarian)
Currently translated at 0.5% (89 of 15109 strings)
2023-03-04 11:41:52 +01:00
Jiri Zizkin Zizka
9eaf9ea2ed Translated using Weblate (Czech)
Currently translated at 93.7% (14168 of 15109 strings)
2023-03-04 11:41:50 +01:00
ilya
00c4f77251 Translated using Weblate (Russian)
Currently translated at 100.0% (15109 of 15109 strings)
2023-03-04 11:41:47 +01:00
Nut.andor
96ef9eedbb Content format reference 2023-02-26 01:35:28 +01:00
Nut.andor
a5d94c03e2 Migration of links to git repo AndorsTrailRelease 2023-02-26 01:34:35 +01:00
Nut.andor
9d15d380a3 Migration of links to git repo AndorsTrailRelease 2023-02-26 01:27:10 +01:00
Nut.andor
bff780c837 reformat for better reading 2023-02-26 01:11:40 +01:00
Nut.andor
0c493952c8 Migration of links to git repo AndorsTrailRelease 2023-02-25 23:47:10 +01:00
Jiri Zizkin Zizka
a1f6e1d29c Translated using Weblate (Czech)
Currently translated at 93.5% (14135 of 15109 strings)
2023-02-25 05:40:05 +01:00
aircqsj
fc71f43755 Translated using Weblate (Chinese (Simplified))
Currently translated at 99.9% (15105 of 15109 strings)
2023-02-25 05:40:02 +01:00
Jiri Zizkin Zizka
16afcf4886 Translated using Weblate (Czech)
Currently translated at 93.4% (14114 of 15109 strings)
2023-02-23 02:46:02 +01:00
Daniel Stasiak
b64a3c2109 Translated using Weblate (Polish)
Currently translated at 91.8% (13884 of 15109 strings)
2023-02-23 02:45:59 +01:00
Casey Malessa
5c0dc66183 Translated using Weblate (Japanese)
Currently translated at 95.4% (582 of 610 strings)
2023-02-23 02:45:56 +01:00
Nut.andor
3047f653bd prep beta 2023-02-21 21:57:48 +01:00
Nut.andor
393a478d13 prep beta 2023-02-21 21:31:14 +01:00
Michael Bæk
560cb326f9 Added translation using Weblate (Danish) 2023-02-20 20:45:04 +01:00
Jiri Zizkin Zizka
3fe2d7260f Translated using Weblate (Czech)
Currently translated at 93.1% (14074 of 15109 strings)
2023-02-20 20:41:50 +01:00
Jiri Zizkin Zizka
2cd4bc7ee5 Translated using Weblate (Czech)
Currently translated at 92.6% (13997 of 15109 strings)
2023-02-15 23:40:12 +01:00
Daniel Stasiak
19468b591d Translated using Weblate (Polish)
Currently translated at 91.8% (13884 of 15109 strings)
2023-02-15 23:40:09 +01:00
ssantos
903117d32f Translated using Weblate (Portuguese)
Currently translated at 76.4% (11555 of 15109 strings)
2023-02-12 16:40:07 +01:00
Jiri Zizkin Zizka
f5bfc98c62 Translated using Weblate (Czech)
Currently translated at 92.6% (13995 of 15109 strings)
2023-02-10 11:39:33 +01:00
Daniel Stasiak
3274feb1e9 Translated using Weblate (Polish)
Currently translated at 91.8% (13884 of 15109 strings)
2023-02-10 11:39:30 +01:00
Daniel Stasiak
392b4d8577 Translated using Weblate (Polish)
Currently translated at 100.0% (610 of 610 strings)
2023-02-10 11:39:28 +01:00
Yan Chen
92e4afde4b Translated using Weblate (Esperanto)
Currently translated at 17.5% (107 of 610 strings)
2023-02-08 23:40:01 +01:00
Jiri Zizkin Zizka
0c7724fe33 Translated using Weblate (Czech)
Currently translated at 100.0% (610 of 610 strings)
2023-02-08 23:40:00 +01:00
Jiri Zizkin Zizka
ca5be34fc2 Translated using Weblate (Czech)
Currently translated at 92.5% (13986 of 15109 strings)
2023-02-08 23:40:00 +01:00
Daniel Stasiak
28c3c7a0ec Translated using Weblate (Polish)
Currently translated at 91.8% (13884 of 15109 strings)
2023-02-08 23:39:57 +01:00
Daniel Stasiak
7f39cf1a6f Translated using Weblate (Polish)
Currently translated at 91.8% (13884 of 15109 strings)
2023-02-07 15:40:44 +01:00
gallegonovato
365839571a Translated using Weblate (Spanish)
Currently translated at 100.0% (610 of 610 strings)
2023-02-04 20:39:45 +01:00
Daniel Stasiak
5c3a04ca77 Translated using Weblate (Polish)
Currently translated at 91.8% (13884 of 15109 strings)
2023-02-04 20:39:45 +01:00
Nut.andor
758a580063 changed png 2023-02-04 01:28:09 +01:00
Daniel Stasiak
ad5dbc9f9d Translated using Weblate (Polish)
Currently translated at 91.8% (13884 of 15109 strings)
2023-02-03 12:00:45 +01:00
Casey Malessa
4a86680928 Translated using Weblate (Japanese)
Currently translated at 92.2% (13933 of 15109 strings)
2023-02-03 12:00:42 +01:00
ilya
ece63cf442 Translated using Weblate (Russian)
Currently translated at 100.0% (15109 of 15109 strings)
2023-02-01 22:45:44 +01:00
Daniel Stasiak
b487140a1b Translated using Weblate (Polish)
Currently translated at 91.8% (13884 of 15109 strings)
2023-02-01 22:45:42 +01:00
Casey Malessa
ad72bf8895 Translated using Weblate (Japanese)
Currently translated at 92.1% (13928 of 15109 strings)
2023-02-01 22:45:40 +01:00
Nut.andor
5919c429d2 Next version 2023-01-31 22:14:49 +01:00
OMGeeky
1f365b170e improves the gradle tasks for copying the maps and translations
Instead of copying the files to the normal res folder they get copied
to the build folder, which gives the user the hint that they are
generated and should not be edited in this location.

> **Warning**
After pulling this commit both folders '/app/src/main/res' and 'app/src/main/assets'
should be deleted if they exist, since they are no longer ignored (since they don't get used anymore)!
2023-01-31 22:06:34 +01:00
Nut.andor
0b6580e7c9 whatsNew 69 v0.8.4.1 2023-01-31 21:14:03 +01:00
Nut.andor
6efb2b3860 unneeded files bloats the apk 2023-01-31 21:14:03 +01:00
ilya
7ae084073f Translated using Weblate (Russian)
Currently translated at 100.0% (15109 of 15109 strings)
2023-01-31 19:42:48 +01:00
Daniel Stasiak
36df0b1732 Translated using Weblate (Polish)
Currently translated at 91.8% (13884 of 15109 strings)
2023-01-31 19:42:45 +01:00
ilya
b8fb100bd5 Translated using Weblate (Russian)
Currently translated at 100.0% (610 of 610 strings)
2023-01-31 19:42:44 +01:00
Nut.andor
82b904d176 target 31 needed for Google Play + export 2023-01-30 22:04:10 +01:00
OMGeeky
44723978e1 Merge remote-tracking branch 'origin/AndroidX-Migration' into AndroidX-Migration
# Conflicts:
#	AndorsTrail/app/src/main/AndroidManifest.xml
#	AndorsTrail/app/src/main/java/com/gpl/rpg/AndorsTrail/util/AndroidStorage.java
#	AndorsTrail/build.gradle
#	AndorsTrail/gradle.properties
#	AndorsTrail/gradle/wrapper/gradle-wrapper.properties
2023-01-30 18:38:37 +01:00
OMGeeky
7c7b4829f6 gradle update 2023-01-30 18:29:06 +01:00
OMGeeky
050b027ff5 AndroidX-Migration 2023-01-30 18:02:23 +01:00
OMGeeky
8fac65e268 Upgrade Gradle & Build target version 2023-01-30 18:00:00 +01:00
Nut.andor
111aca868c hotfix 2023-01-29 22:40:51 +01:00
Nut.andor
2171c16d47 whatsNew 2023-01-29 18:38:37 +01:00
Nut.andor
acd4d84783 potc 2023-01-29 18:25:36 +01:00
Nut.andor
cc25cc97f1 Translations 2023-01-29 18:10:15 +01:00
Nut.andor
93ecebc448 Merge branch 'V0.8.4'
# Conflicts:
#	AndorsTrail/app/src/main/AndroidManifest.xml
#	AndorsTrail/app/src/main/java/com/gpl/rpg/AndorsTrail/AndorsTrailApplication.java
2023-01-29 17:58:55 +01:00
Nut.andor
f5713a3eb2 Merge remote-tracking branch 'hosted.weblate/master' 2023-01-29 17:51:49 +01:00
Jiri Zizkin Zizka
90001bb4d6 Translated using Weblate (Czech)
Currently translated at 93.0% (13958 of 14998 strings)
2023-01-29 17:48:01 +01:00
Daniel Stasiak
357cab9b1e Translated using Weblate (Polish)
Currently translated at 92.5% (13884 of 14998 strings)
2023-01-29 17:47:58 +01:00
Jiri Zizkin Zizka
5ea272f286 Translated using Weblate (Czech)
Currently translated at 100.0% (602 of 602 strings)
2023-01-28 00:57:24 +01:00
Jiri Zizkin Zizka
0c876bd1c5 Translated using Weblate (Czech)
Currently translated at 92.9% (13934 of 14998 strings)
2023-01-28 00:57:24 +01:00
Daniel Stasiak
0ac2999694 Translated using Weblate (Polish)
Currently translated at 92.5% (13884 of 14998 strings)
2023-01-28 00:57:22 +01:00
Nut.andor
49af3c4b6d some more map fixex 2023-01-24 21:30:37 +01:00
Nut.andor
2a54b31d31 beta version nbr 2023-01-24 21:29:05 +01:00
Nut.andor
64766ce50a potc 2023-01-24 20:47:39 +01:00
Nut.andor
311accfdd3 prep for beta 2023-01-24 20:21:38 +01:00
Nut.andor
2b5bf2fa4a Merge remote-tracking branch 'origin/V0.8.4' into V0.8.4 2023-01-21 13:32:42 +01:00
Nut
64342c96d7 Merge pull request #51 from OMGeeky/import-export-fix-1
Import/Export improvements
2023-01-21 13:31:28 +01:00
OMGeeky
f8649bb0a5 Cleanup 2023-01-21 12:55:16 +01:00
Nut.andor
fde6608c26 translations, copyright 2023-01-21 01:06:55 +01:00
Nut.andor
3f339c14a2 translations, copyright 2023-01-21 00:40:52 +01:00
Nut.andor
922db05c4d Merge remote-tracking branch 'hosted.weblate/master' into V0.8.4 2023-01-21 00:31:16 +01:00
Eduardo
b849de8b66 Translated using Weblate (Portuguese (Brazil))
Currently translated at 94.4% (14159 of 14998 strings)
2023-01-21 00:21:55 +01:00
Eduardo
f798b29729 Translated using Weblate (Portuguese)
Currently translated at 76.4% (11470 of 14998 strings)
2023-01-21 00:21:51 +01:00
MARCO ACORTE
e58e7a2588 Translated using Weblate (Italian)
Currently translated at 83.9% (12598 of 14998 strings)
2023-01-21 00:21:50 +01:00
Eduardo
a1ef339831 Translated using Weblate (Portuguese)
Currently translated at 76.4% (11466 of 14998 strings)
2023-01-20 00:59:15 +01:00
gallegonovato
2002d51f6b Translated using Weblate (Spanish)
Currently translated at 100.0% (602 of 602 strings)
2023-01-15 19:50:17 +01:00
Nut.andor
025283b70b ratdom graphics 2023-01-14 00:57:13 +01:00
Predrag
577b1aa034 Translated using Weblate (Serbian)
Currently translated at 1.8% (275 of 14997 strings)
2023-01-13 10:52:03 +01:00
Ömer Faruk Çakmak
da637c0cc8 Translated using Weblate (Turkish)
Currently translated at 36.1% (5416 of 14998 strings)
2023-01-13 10:52:01 +01:00
Vincenzo De Concilio
d026ff690a Translated using Weblate (Italian)
Currently translated at 96.8% (583 of 602 strings)
2023-01-13 10:51:59 +01:00
Predrag
d14ed56669 Added translation using Weblate (Serbian) 2023-01-12 09:31:54 +01:00
Predrag
64cfacb7ff Translated using Weblate (Serbian)
Currently translated at 0.9% (144 of 14997 strings)
2023-01-11 16:55:04 +01:00
Ömer Faruk Çakmak
98a800e070 Translated using Weblate (Turkish)
Currently translated at 100.0% (602 of 602 strings)
2023-01-11 16:55:02 +01:00
Predrag
35219c8e88 Translated using Weblate (Serbian)
Currently translated at 0.5% (89 of 14997 strings)
2023-01-11 16:22:50 +01:00
Predrag
b636cad347 Added translation using Weblate (Serbian) 2023-01-11 15:35:23 +01:00
Ian Lethe (Windseeker)
733328cd29 Translated using Weblate (Korean)
Currently translated at 9.3% (1408 of 14998 strings)
2023-01-09 12:13:27 +01:00
Ian Lethe (Windseeker)
36db28f805 Translated using Weblate (Korean)
Currently translated at 9.3% (1404 of 14998 strings)
2023-01-09 08:52:00 +01:00
Szabó Péter
6d4c1c3c14 Translated using Weblate (Hungarian)
Currently translated at 89.0% (536 of 602 strings)
2023-01-08 13:52:07 +01:00
David Tamas Szabo
eadb95f8e8 Translated using Weblate (Hungarian)
Currently translated at 27.8% (4177 of 14998 strings)
2023-01-08 13:52:07 +01:00
Szabó Péter
014f67f270 Translated using Weblate (Hungarian)
Currently translated at 27.8% (4177 of 14998 strings)
2023-01-08 13:52:06 +01:00
Nut.andor
cd8657adb4 QuickLearner 5% -> 10% 2023-01-08 00:57:36 +01:00
gallegonovato
c007fc4d1c Translated using Weblate (Spanish)
Currently translated at 100.0% (602 of 602 strings)
2023-01-01 19:52:07 +01:00
gallegonovato
7e6c864ba3 Translated using Weblate (Spanish)
Currently translated at 84.3% (12658 of 14998 strings)
2023-01-01 19:52:06 +01:00
Kristoffer Grundström
f2da8f767a Translated using Weblate (Swedish)
Currently translated at 4.5% (689 of 14998 strings)
2022-12-29 13:27:04 +01:00
Nut.andor
bd856541d6 fix Burhczyd 2022-12-25 01:34:00 +01:00
Dan
bdde2176d9 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (602 of 602 strings)
2022-12-15 21:48:06 +01:00
Dan
171893a2c1 Translated using Weblate (Ukrainian)
Currently translated at 9.8% (1478 of 14998 strings)
2022-12-14 13:51:22 +01:00
rabituwu
c6c1d6d03d Translated using Weblate (Filipino)
Currently translated at 1.9% (295 of 14997 strings)
2022-12-12 14:51:24 +01:00
Nut.andor
ec8b114782 fix Burhczyd 2022-12-12 08:52:43 +01:00
Nut.andor
aaecb8ae4a Reformatting json for better reading 2022-12-11 03:56:15 +01:00
OMGeeky
4e2e3b370c formatting 2022-12-08 17:56:41 +01:00
OMGeeky
c14f8f84a0 Import/Export of the worldmap changed to zip files & some clarifications 2022-12-08 00:18:28 +01:00
Lucas Araujo
13c8012710 Translated using Weblate (Portuguese (Brazil))
Currently translated at 92.9% (13935 of 14998 strings)
2022-12-03 16:48:55 +01:00
عادل نصري
3806d77b26 Translated using Weblate (Arabic)
Currently translated at 9.7% (1457 of 14997 strings)
2022-11-30 14:48:56 +01:00
عادل نصري
af94220715 Translated using Weblate (Arabic)
Currently translated at 100.0% (602 of 602 strings)
2022-11-29 20:48:04 +01:00
عادل نصري
af07c47832 Translated using Weblate (Arabic)
Currently translated at 9.7% (1456 of 14997 strings)
2022-11-29 20:48:03 +01:00
Nut.andor
322007e5ac Next version number v0-8-4 68 2022-11-19 00:23:26 +01:00
aircqsj
af5cdb9d49 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (602 of 602 strings)
2022-11-16 13:48:29 +01:00
Nut.andor
3ada8ceaa7 V0.8.3 2022-11-13 00:54:22 +01:00
3raven
68fa0068dc Translated using Weblate (French)
Currently translated at 84.8% (12733 of 14998 strings)
2022-11-09 22:50:27 +01:00
Nut.andor
7b5fc79375 fixes from beta 2022-11-09 07:30:19 +01:00
ilya
5dfa750227 Translated using Weblate (Russian)
Currently translated at 100.0% (602 of 602 strings)
2022-11-08 19:03:26 +01:00
ilya
cbe0773310 Translated using Weblate (Russian)
Currently translated at 100.0% (602 of 602 strings)
2022-11-07 14:03:24 +01:00
Nut.andor
72a19eeb80 fixes from beta 2022-11-06 21:47:25 +01:00
Nut.andor
a993cc5a08 translation state 2022-11-05 19:07:45 +01:00
Nut.andor
83724ba408 haunted content 2022-11-05 02:03:27 +01:00
Nut.andor
a4cd8f7460 Merge branch 'pulls/1829009049/48' 2022-11-05 00:43:35 +01:00
Nut.andor
7a52bbb9f3 Merge remote-tracking branch 'origin/v0.8.3' 2022-11-05 00:40:01 +01:00
Nut.andor
3552ff8a9f translations 2022-11-05 00:31:16 +01:00
Nut.andor
0e081f3319 authors 2022-11-05 00:30:56 +01:00
Nut.andor
1d94519e1c Merge remote-tracking branch 'hosted.weblate/master' into v0.8.3 2022-11-05 00:24:11 +01:00
Hosted Weblate
0bbc6adb4b Merge branch 'origin/master' into Weblate. 2022-11-05 00:21:51 +01:00
Nut.andor
b48ddd4999 whatsnew 2022-11-04 22:44:39 +01:00
Nut.andor
be8dad981d some new / fixed graphics 2022-11-04 22:44:38 +01:00
Nut.andor
f9708f48a4 whatsnew 2022-11-04 22:38:11 +01:00
Nut.andor
155b01bdea some new / fixed graphics 2022-11-04 22:07:10 +01:00
Nut.andor
19810b2099 Import Export 2022-11-04 21:57:27 +01:00
aircqsj
c6886f7a3e Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (14998 of 14998 strings)
2022-11-04 14:07:59 +01:00
OMGeeky
3bea24f9cc Fixed bug where the Logs folder would get exported instead of the Worldmap folder
+cleanup
+API level safety markers
2022-11-03 20:35:37 +01:00
Lacrom
4b8f5c4908 Translated using Weblate (French)
Currently translated at 84.7% (12717 of 14998 strings)
2022-10-29 06:34:15 +02:00
Nut
66d9618b1b Merge pull request #49 from OMGeeky/temp1
Remove ignored files
2022-10-28 22:16:00 +02:00
OMGeeky
488d6347d0 Remove ignore files that are still tracked 2022-10-28 21:39:41 +02:00
OMGeeky
d39d0c9265 AndroidX-Migration 2022-10-28 19:39:14 +02:00
OMGeeky
33fe96dada Upgrade Gradle & Build target version 2022-10-28 19:05:54 +02:00
OMGeeky
51fd0d0994 Add a loading animation. 2022-10-28 18:47:08 +02:00
Lacrom
50833af145 Translated using Weblate (French)
Currently translated at 84.7% (12704 of 14998 strings)
2022-10-28 07:50:32 +02:00
Lacrom
ca7c2388aa Translated using Weblate (French)
Currently translated at 83.2% (12479 of 14998 strings)
2022-10-27 08:48:11 +02:00
Lacrom
8e7d6adca5 Translated using Weblate (French)
Currently translated at 100.0% (582 of 582 strings)
2022-10-27 08:48:09 +02:00
aircqsj
17edb96ff8 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (14998 of 14998 strings)
2022-10-23 06:10:26 +02:00
ilya
3f3869916c Translated using Weblate (Russian)
Currently translated at 100.0% (14998 of 14998 strings)
2022-10-23 06:10:24 +02:00
Elton Viana Gonçalves da Luz
1d2fc7ade7 Translated using Weblate (Portuguese (Brazil))
Currently translated at 92.8% (13929 of 14998 strings)
2022-10-23 06:10:22 +02:00
OMGeeky
aa84e5a73d Improve import options when the target slot is already used. 2022-10-22 18:10:59 +02:00
OMGeeky
4ecf7d2dda Allow setting strings as message directly & add support for canceling the Dialog 2022-10-22 18:06:25 +02:00
Nut.andor
dca1cb676c New release version numbers and some basic files and settings 2022-10-20 00:14:37 +02:00
Nut.andor
9a4f41eac2 whatsnew 2022-10-19 23:21:43 +02:00
OMGeeky
23012b0d40 Update strings.xml 2022-10-19 22:33:06 +02:00
OMGeeky
916134bd9b Update strings.xml 2022-10-19 22:24:05 +02:00
Nut.andor
1d6777daae fix diamond 2022-10-19 20:14:29 +02:00
OMGeeky
4793751ba8 Improved error/success messages & fixed some bugs in 'Add as New' 2022-10-19 19:16:37 +02:00
OMGeeky
185c0eaf7c Enabling 'Load' button even if no saves exist (for imports) 2022-10-19 19:14:27 +02:00
Daniel Stasiak
4b50d13149 Translated using Weblate (Polish)
Currently translated at 92.5% (13884 of 14998 strings)
2022-10-19 18:07:41 +02:00
이정희
23b58c3e7c Translated using Weblate (Korean)
Currently translated at 9.3% (1403 of 14998 strings)
2022-10-19 18:07:39 +02:00
Ricardo
2d5ebc3b13 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (582 of 582 strings)
2022-10-19 18:07:38 +02:00
OMGeeky
59e2e3035c Hide the import/export options on devices with an Android version below 10 (Q or api level 29) 2022-10-18 22:34:08 +02:00
OMGeeky
6d5ddfdbfa Add option to 'Add as New' on import 2022-10-18 22:15:53 +02:00
OMGeeky
f8ae18721f Allow vertically stacked buttons in Dialogs 2022-10-18 22:13:17 +02:00
Nut.andor
63bc7c3a4e whatsnew and translation status 2022-10-17 23:44:05 +02:00
OMGeeky
8e72763314 Import Export 2022-10-17 23:20:16 +02:00
Nut.andor
9310d53362 potc 2022-10-17 23:15:48 +02:00
Nut.andor
a71dcc13a3 content 0.8.2 2022-10-17 23:06:34 +02:00
Nut.andor
ea95f4ff87 actual translations generated 2022-10-17 22:33:03 +02:00
Nut.andor
f35167d112 Merge remote-tracking branch 'hosted.weblate/master' 2022-10-17 22:27:58 +02:00
Daniel Stasiak
9f935190f2 Translated using Weblate (Polish)
Currently translated at 92.5% (13884 of 14995 strings)
2022-10-16 00:53:44 +02:00
Nut.andor
c11430cf6b beta icon and fileprovider 2022-10-15 22:46:16 +02:00
Daniel Stasiak
8f97a27ab7 Translated using Weblate (Polish)
Currently translated at 92.5% (13884 of 14995 strings)
2022-10-13 15:56:19 +02:00
Anupam Malhotra
9e36f848dc Translated using Weblate (Hindi)
Currently translated at 0.1% (4 of 14994 strings)
2022-10-12 08:50:37 +02:00
ilya
b24d52b1da Translated using Weblate (Russian)
Currently translated at 100.0% (14995 of 14995 strings)
2022-10-12 08:50:34 +02:00
Daniel Stasiak
e2a9307560 Translated using Weblate (Polish)
Currently translated at 92.5% (13884 of 14995 strings)
2022-10-12 08:50:31 +02:00
Nut.andor
e3ac804f61 Merge branch 'pulls/1829009049/47' 2022-10-11 19:20:06 +02:00
Nut.andor
fd504d2df5 Automated copying of files for build as gradle task 2022-10-11 18:58:05 +02:00
OMGeeky
0e615d3f11 Revert accidental wrong branch stuff 2022-10-11 18:31:01 +02:00
Nut.andor
47646457ab (Pull Request #46:) Fixed problems with older Android versions (below Android 7) 2022-10-11 00:00:00 +02:00
OMGeeky
8e393b93d8 Changed lint.xml to include StringFormatMatches and StringFormatInvalid 2022-10-10 15:43:34 +02:00
OMGeeky
3289bd6fb1 Configured lint-baseline file (for automatic builds on github) 2022-10-10 15:32:21 +02:00
OMGeeky
23a331d655 Merge remote-tracking branch 'origin/fix-older-android-versions' into gradle_copy_v1 2022-10-10 15:09:01 +02:00
OMGeeky
112301c444 Create build Action
(cherry picked from commit 462b6059218b1bdc1efa582ea2463d5eb3af1c22)
2022-10-10 15:05:01 +02:00
OMGeeky
f50e4f1d38 Migrate to AndroidX 2022-10-10 14:54:08 +02:00
OMGeeky
d623c22b38 Removed ignored files 2022-10-10 14:45:01 +02:00
OMGeeky
d11bf5b0aa Automated copying of files for build as gradle task 2022-10-10 09:22:18 +02:00
Nut.andor
e30f67e327 fix Master Ale bug 2022-10-09 02:43:01 +02:00
OMGeeky
6946b1f2b3 Fixed problems with older Android versions (below Android 7) 2022-10-09 02:00:52 +02:00
Nut Andor
96a1a5760a Translated using Weblate (German)
Currently translated at 94.0% (14096 of 14995 strings)
2022-10-09 01:15:46 +02:00
Nut.andor
58b802e911 whatsnew 2022-10-08 03:41:50 +02:00
Nut.andor
f9b095565b languages 2022-10-08 03:22:32 +02:00
Nut.andor
19817eb97d Merge branch 'v0.8.2' 2022-10-08 02:58:18 +02:00
Nut.andor
f46d2aedbf content v082 (Sullengard fixes) 2022-10-08 02:56:10 +02:00
Nut.andor
913b651953 Merge remote-tracking branch 'hosted.weblate/master' into v0.8.2 2022-10-08 01:04:59 +02:00
Nut Andor
5283eed28e Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (15016 of 15016 strings)
2022-10-08 01:04:14 +02:00
Nut Andor
deb824d50e Translated using Weblate (German)
Currently translated at 93.8% (14095 of 15016 strings)
2022-10-08 01:04:12 +02:00
Nut.andor
6841d862e4 Merge remote-tracking branch 'hosted.weblate/master' into v0.8.2 2022-10-08 00:43:26 +02:00
saoloer
f94723b0cd Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (15016 of 15016 strings)
2022-10-07 18:18:35 +02:00
Jr
ab41168736 Translated using Weblate (German)
Currently translated at 93.8% (14095 of 15016 strings)
2022-10-07 18:18:33 +02:00
Jr
2d73c4687a Translated using Weblate (German)
Currently translated at 100.0% (582 of 582 strings)
2022-10-07 18:18:30 +02:00
aircqsj
e454deb8b1 Translated using Weblate (Chinese (Simplified))
Currently translated at 99.9% (15015 of 15016 strings)
2022-10-05 20:56:26 +02:00
Lucas Araujo
074891805a Translated using Weblate (Portuguese (Brazil))
Currently translated at 92.7% (13928 of 15016 strings)
2022-10-05 20:56:21 +02:00
Daniel Stasiak
d2d32bc4ed Translated using Weblate (Polish)
Currently translated at 92.4% (13884 of 15016 strings)
2022-10-05 20:56:20 +02:00
Daniel Stasiak
22daeb0c33 Translated using Weblate (Polish)
Currently translated at 100.0% (582 of 582 strings)
2022-10-05 20:56:17 +02:00
Nut.andor
db30253baf v0.8.2 66 2022-10-03 00:47:11 +02:00
Nut.andor
312cb7dec7 ignore workspace.xml 2022-10-03 00:44:00 +02:00
Nut.andor
7befd27951 whatsnew release version 2022-10-02 21:05:38 +02:00
aircqsj
c1e3bfa7ed Translated using Weblate (Chinese (Simplified))
Currently translated at 94.0% (14128 of 15016 strings)
2022-10-02 07:56:33 +02:00
ilya
ddec991082 Translated using Weblate (Russian)
Currently translated at 100.0% (15016 of 15016 strings)
2022-10-02 07:56:02 +02:00
Nut.andor
79e6fe7b65 whatsnew
factionlist bug
2022-10-01 09:18:28 +02:00
ilya
25e36dc535 Translated using Weblate (Russian)
Currently translated at 100.0% (15016 of 15016 strings)
2022-09-30 18:31:04 +02:00
Jiri Zizkin Zizka
83c579a929 Translated using Weblate (Czech)
Currently translated at 100.0% (582 of 582 strings)
2022-09-29 23:16:22 +02:00
Jiri Zizkin Zizka
0c694115ee Translated using Weblate (Czech)
Currently translated at 92.7% (13932 of 15016 strings)
2022-09-29 23:16:22 +02:00
ilya
bf9723b0c1 Translated using Weblate (Russian)
Currently translated at 96.2% (14449 of 15016 strings)
2022-09-29 23:16:20 +02:00
ilya
b81bacb1fe Translated using Weblate (Russian)
Currently translated at 100.0% (582 of 582 strings)
2022-09-29 23:16:17 +02:00
Nut.andor
329acad741 authors 2022-09-28 00:44:23 +02:00
Nut.andor
41ad345a89 languages% 2022-09-28 00:10:39 +02:00
Nut.andor
f79633fb85 POTCPOTC incl. compile 2022-09-27 22:34:06 +02:00
Nut.andor
8071ebe28f fix https 2022-09-27 21:55:59 +02:00
Nut.andor
09ff14bd14 content sullengard 2022-09-27 21:54:13 +02:00
Nut.andor
fee94d4262 typo in authors 2022-09-27 21:50:45 +02:00
Nut.andor
ec14dbe917 compiled languages 2022-09-27 20:04:48 +02:00
Nut.andor
cc1d20aba6 Revert "Auxiliary commit to revert individual files from 4feebd058b2184486001bb77f9b2b4c48947f11d"
This reverts commit f8a9c8d2d40b69f5f4007320365d64127ef93fa4, reversing
changes made to 2dd9f8fcab.
2022-09-27 19:47:37 +02:00
Nut.andor
4feebd058b Merge remote-tracking branch 'hosted.weblate/master'
(an old state that must be reverted again, just to sync weblate)
2022-09-27 19:46:41 +02:00
Hosted Weblate
265469f88e Merge branch 'origin/master' into Weblate. 2022-09-26 23:19:16 +02:00
Nut.andor
2dd9f8fcab Merge commit '2705e1c20875e74aefdc5225e27c7cf8004edc15'
missing translations
2022-09-26 23:17:16 +02:00
Hosted Weblate
50c522c20a Merge branch 'origin/master' into Weblate. 2022-09-26 23:08:11 +02:00
Nut.andor
08dea48010 Revert "missing translations 20220821-2144 ... 20220924-2147"
This reverts commit 76127d9d85.
2022-09-26 23:07:49 +02:00
Hosted Weblate
781ddcf7a7 Merge branch 'origin/master' into Weblate. 2022-09-26 23:04:35 +02:00
Nut.andor
76127d9d85 missing translations 20220821-2144 ... 20220924-2147 2022-09-26 23:03:16 +02:00
Hosted Weblate
e826232611 Merge branch 'origin/master' into Weblate. 2022-09-26 22:42:24 +02:00
Nut.andor
d879629e4a Revert to next prod version 2022-09-26 22:41:03 +02:00
Nut.andor
2e7eb84f88 potc 2022-09-26 00:56:19 +02:00
Nut.andor
10ebaf925f content sullengard 2022-09-26 00:43:37 +02:00
Nut.andor
4c8302b11e compiled languages 2022-09-25 23:46:21 +02:00
Nut.andor
235f1c912d next prod version 0.8.1
authors
2022-09-25 23:46:02 +02:00
Nut.andor
a5721a4a25 gradle to gitignore 2022-09-25 23:15:32 +02:00
Nut.andor
5adbbd61b9 Next version 0.8.1
Burhczyd enhanced
Burhczyd typos
Some map changes,
beta icon
WhatsNew
map_tree_1+2.png changes
2022-09-25 19:46:17 +02:00
Nut.andor
196223bf73 - Large maps bugs
- Debug buttons
2022-09-25 15:36:10 +02:00
Nut.andor
d89a615990 Migration to actual AndroidStudio version - final touches for compile 2022-09-25 15:34:08 +02:00
Nut.andor
863cc1a0bb Preparation for Compile
- change  http://  to  https://
2022-09-25 14:34:23 +02:00
Nut.andor
1cec98249b Migration to actual AndroidStudio version
Copy  ...\AndorsTrailRelease\andors-trail\AndorsTrail  to  a temporary directory, then delete the content except the .git directory.   (C:\AT\AndorsTrailRelease_before_Mig_20220925)

Open Android Studio, any project
New >> Import project

> Import Project, select the AndorsTrail folder from the temporary location
	C:\AT\AndorsTrailRelease_before_Mig_20220925\andors-trail\AndorsTrail
  Destination: C:\AT\AndorsTrailRelease\andors-trail\AndorsTrail

Click next a few times.
It then shows some error about not finding build tools. Below it there should be the option to 'Add google Maven reposiroty and sync project'. Click that option and then 'Do Refactor' (Bottom Left).

In the newly created file 'app/build.gradle'
In line 4 change the compileSdkVersion to 30 (or higher?)
In line 9 change the minSdkVersion to 14 instead of 4
In line 22 change the version from '29.+' to '28.0.0' and the compile at the beginning to implementation
Then Click 'Sync Project with Gradle Files' (icon in top right) that should no longer give errors.
2022-09-25 13:16:57 +02:00
Nut.andor
15ba005062 Merge branch 'pulls/1829009049/37' 2022-09-25 11:56:03 +02:00
Nut.andor
86c1b7496d Merge branch 'pulls/1829009049/36' 2022-09-25 11:55:12 +02:00
Nut.andor
0a194f1e25 Merge branch 'pulls/1829009049/35' 2022-09-25 11:54:58 +02:00
Nut.andor
6ada4c9649 Merge remote-tracking branch 'Weblate_translations/master' 2022-09-25 11:44:21 +02:00
Daniel Stasiak
2705e1c208 Translated using Weblate (Polish)
Currently translated at 99.6% (13886 of 13929 strings)
2022-09-25 11:15:00 +02:00
Andrés Morgensen
3ec7a76ce2 Translated using Weblate (Spanish)
Currently translated at 90.8% (12659 of 13929 strings)
2022-09-17 01:23:39 +02:00
Wahyu Budi Laksono
5ec9a76c65 Translated using Weblate (Indonesian)
Currently translated at 18.4% (2573 of 13929 strings)
2022-09-09 17:23:41 +02:00
Budi
146f62b283 Translated using Weblate (Indonesian)
Currently translated at 18.0% (2520 of 13929 strings)
2022-09-07 21:05:11 +02:00
Neko Nekowazarashi
b9d4e52101 Translated using Weblate (Indonesian)
Currently translated at 17.9% (2507 of 13929 strings)
2022-09-05 16:23:44 +02:00
Kristoffer Grundström
934f578083 Translated using Weblate (Swedish)
Currently translated at 70.5% (410 of 581 strings)
2022-09-03 01:24:47 +02:00
Jiri Zizkin Zizka
0d604f6346 Translated using Weblate (Czech)
Currently translated at 100.0% (13929 of 13929 strings)
2022-09-03 01:24:46 +02:00
Daniel Stasiak
5a555d554c Translated using Weblate (Polish)
Currently translated at 99.6% (13886 of 13929 strings)
2022-08-31 13:26:13 +02:00
daudiffa
8ccaabfb0d Translated using Weblate (Indonesian)
Currently translated at 17.7% (2478 of 13929 strings)
2022-08-31 13:26:11 +02:00
Artem
fb887cc869 Translated using Weblate (Ukrainian)
Currently translated at 10.6% (1478 of 13929 strings)
2022-08-30 05:45:22 +02:00
Daniel Stasiak
368359af08 Translated using Weblate (Polish)
Currently translated at 99.6% (13886 of 13929 strings)
2022-08-30 05:45:20 +02:00
daudiffa
dc15a9ecde Translated using Weblate (Indonesian)
Currently translated at 17.3% (2412 of 13929 strings)
2022-08-30 05:45:18 +02:00
Artem
1f6db65a45 Translated using Weblate (Ukrainian)
Currently translated at 10.6% (1478 of 13929 strings)
2022-08-28 03:25:16 +02:00
Jiri Zizkin Zizka
0a70cdd852 Translated using Weblate (Czech)
Currently translated at 99.8% (13909 of 13929 strings)
2022-08-28 03:25:14 +02:00
Daniel Stasiak
493f3675dd Translated using Weblate (Polish)
Currently translated at 99.6% (13886 of 13929 strings)
2022-08-28 03:25:13 +02:00
Marco Santos
7b3b950982 Translated using Weblate (Filipino)
Currently translated at 46.8% (272 of 581 strings)
2022-08-24 06:18:40 +02:00
Jiri Zizkin Zizka
58cb83ee0c Translated using Weblate (Czech)
Currently translated at 99.8% (13903 of 13929 strings)
2022-08-24 06:18:40 +02:00
Daniel Stasiak
97d03a76c5 Translated using Weblate (Polish)
Currently translated at 99.6% (13886 of 13929 strings)
2022-08-24 06:18:39 +02:00
Jiri Zizkin Zizka
d42046dc30 Translated using Weblate (Czech)
Currently translated at 99.7% (13897 of 13929 strings)
2022-08-22 15:58:00 +02:00
Daniel Stasiak
fc6d11b096 Translated using Weblate (Polish)
Currently translated at 99.6% (13886 of 13929 strings)
2022-08-22 15:57:57 +02:00
Nut.andor
bb707047a0 gradle wrapper 2022-07-24 10:30:41 +02:00
Nut.andor
efe0691f74 gitignore 2022-07-24 10:25:17 +02:00
Nut.andor
5319a611bc keyboard/dpad diagonals and shortcut handling
# Conflicts:
#	AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/InputController.java
#	AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/MainView.java
2022-06-12 08:29:14 +02:00
Nut.andor
e179d0cdf6 Monsterstatus killcount 2022-06-12 08:08:24 +02:00
Nut.andor
f330a48f51 kill count stats by monster name instead of ID 2022-06-12 08:07:11 +02:00
Nut.andor
e6268fbd14 minor typo 2022-06-12 07:10:05 +02:00
Nut.andor
7c4ba2b2c7 release notes 2022-04-16 08:07:37 +02:00
Nut.andor
0368c112ad title translation fixed 2022-04-16 07:11:17 +02:00
Nut.andor
0d73255de0 Uncompressed release version 2022-04-16 06:43:34 +02:00
Nut.andor
7f0499c701 rename to prod version build, without debuggable and read_log 2022-04-15 16:50:31 +02:00
Nut.andor
09656bc4bf potc 2022-04-15 12:48:41 +02:00
Nut.andor
f47d395b94 translation status, without debug 2022-04-15 12:30:59 +02:00
Nut.andor
dba2900213 new content (bug fixes) 2022-04-15 11:58:33 +02:00
Nut.andor
cb8ef5e790 Merge remote-tracking branch 'AndorsTrailRelease/master' 2022-04-15 11:48:54 +02:00
Nut.andor
5378279d46 v0.7.17dev
package="com.gpl.rpg.AndorsTrail_beta1"
2022-04-08 23:30:14 +02:00
Nut.andor
cc6a573ef0 next version,
together with critical bugfix
2022-04-08 21:11:52 +02:00
Nut.andor
7447df12cf next dev version 17 (64) 2022-04-02 14:37:12 +02:00
Nut.andor
ba34e16290 Merge remote-tracking branch 'local_AndorsTrailRelease/master'
# Conflicts:
#	AndorsTrail/res/values/loadresources.xml
2022-04-02 14:34:45 +02:00
Nut.andor
0e41a885e3 Delivery 2022-02-13 18:44:23 +01:00
Nut.andor
93a00755da authors 2022-02-13 18:39:52 +01:00
Nut.andor
ee2d6258d3 preparation of next release 2022-02-13 17:21:05 +01:00
guru_meditation_no42
6d18e00535 Move canAcceptInput() checks into handler. 2021-04-17 09:23:42 -07:00
guru_meditation_no42
127cba55f5 Change keyMap to SparseInit array. 2021-04-17 08:54:58 -07:00
guru_meditation_no42
a4e95b1c98 Move keycode mapping to keyMap array instead of switch case entries. 2021-04-13 22:50:59 -07:00
guru_meditation_no42
2649471c5f Added shortcut to Hero Info activity, tweaked some button state logic a bit, added comments 2021-04-13 00:08:16 -07:00
guru_meditation_no42
bd17ea8cee Fixed whitespace. Again. D*mn editor. 2021-04-11 21:48:35 -07:00
guru_meditation_no42
c24c8d1444 Fix to attack shortcut logic 2021-04-11 19:46:12 -07:00
guru_meditation_no42
a3c632947b Fix whitespace changes, tweak canAcceptInput() handling. 2021-04-11 19:34:14 -07:00
guru_meditation_no42
edd147e970 Redo keyboard input handling to allow diagonal movement using either keypad or two-key combos, and add keyboard/dpad shortcuts for Flee, Attack, and End Turn. 2021-04-11 18:54:37 -07:00
guru_meditation_no42
4f1dd93ba6 Add body count to monster info display 2021-04-08 18:19:24 -07:00
guru_meditation_no42
737736dca2 Track and report monster kills by name instead of id 2021-04-08 10:25:19 -07:00
guru_meditation_no42
0f32f09b0d Track and report monster kills by name instead of id 2021-04-08 09:32:50 -07:00
guru_meditation_no42
324be2768c Track and report monster kills by name instead of id 2021-04-07 22:30:08 -07:00
1184 changed files with 1134935 additions and 47356 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/AndorsTrail/.idea/workspace.xml

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>

View File

@@ -1,8 +1,12 @@
# Android ignores
gen/
bin/
target/
local.properties
app/build/intermediates/
build/
debug/
release/
.gradle/
#IntelliJ
.idea/
@@ -14,3 +18,35 @@ out/test/
# Other
.metadata
.svn/
#copied from https://github.com/github/gitignore/blob/main/Gradle.gitignore
.gradle
**/build/
!src/**/build/
# Ignore Gradle GUI config
gradle-app.setting
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar
# Avoid ignore Gradle wrappper properties
!gradle-wrapper.properties
# Cache of project
.gradletasknamecache
# Eclipse Gradle plugin generated files
# Eclipse Core
.project
# JDT-specific (Eclipse Java Development Tools)
.classpath
#copied from https://github.com/github/gitignore/blob/main/Gradle.gitignore
/AndorsTrail/.gradle
/AndorsTrail/gradle/wrapper
/AndorsTrail/app/build/
/AndorsTrail/app/debug/
/AndorsTrail/app/release/

View File

@@ -1,33 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>AndorsTrail</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@@ -1,36 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="EclipseModuleManager" forced_jdk="true">
<conelement value="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK" />
<conelement value="com.android.ide.eclipse.adt.LIBRARIES" />
<src_description expected_position="1">
<src_folder value="file://$MODULE_DIR$/src" expected_position="0" />
<src_folder value="file://$MODULE_DIR$/gen" expected_position="1" />
</src_description>
</component>
<component name="FacetManager">
<facet type="android" name="Android">
<configuration />
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/bin/classes" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" generated="true" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/libs/android-support-v4.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
</component>
</module>

View File

@@ -1,79 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.gpl.rpg.AndorsTrail"
android:versionCode="63"
android:versionName="0.7.16"
android:installLocation="auto"
>
<uses-sdk
android:minSdkVersion="4"
android:targetSdkVersion="30"
/>
<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"
android:anyDensity="true"
/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:name=".AndorsTrailApplication"
android:label="@string/app_name"
android:icon="@drawable/icon"
android:description="@string/app_description"
android:allowBackup="true"
android:theme="@style/AndorsTrailTheme_Blue"
android:requestLegacyExternalStorage="true"
android:hasFragileUserData="true"
android:preserveLegacyExternalStorage="true"
>
<activity
android:name=".activity.StartScreenActivity"
android:clearTaskOnLaunch="true"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".activity.MainActivity"
android:label="@string/app_name"
android:theme="@style/AndorsTrailTheme_Blue.NoBackground"
/>
<activity android:name=".activity.HeroinfoActivity" />
<activity android:name=".activity.MonsterInfoActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name=".activity.ItemInfoActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name=".activity.LevelUpActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name=".activity.MonsterEncounterActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name=".activity.ConversationActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name=".activity.ShopActivity" />
<activity android:name=".activity.AboutActivity" />
<activity android:name=".activity.LoadingActivity" />
<activity android:name=".activity.Preferences" />
<activity android:name=".activity.LoadSaveActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name=".activity.ActorConditionInfoActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name=".activity.BulkSelectionInterface" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name=".activity.SkillInfoActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name=".activity.DisplayWorldMapActivity" />
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.gpl.rpg.AndorsTrail.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/fileprovider" />
</provider>
</application>
</manifest>

View File

@@ -0,0 +1,77 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 34
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.gpl.rpg.AndorsTrail"
minSdkVersion 14
targetSdkVersion 34
}
buildTypes {
release {
manifestPlaceholders icon_name: 'icon', fileproviderPath: 'AndorsTrail'
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
debug {
manifestPlaceholders icon_name: 'icon_beta', fileproviderPath: 'AndorsTrail.beta2'
applicationIdSuffix 'beta2'
signingConfig signingConfigs.debug
}
}
namespace 'com.gpl.rpg.AndorsTrail'
sourceSets {
main {
res.srcDirs = ['build/gen-res', 'src/main/res']
assets.srcDirs = ['build/gen-assets', 'src/main/assets']
}
}
}
dependencies {
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
}
task copyRes(type: Copy) {
description "Copies the res folder to the modules res folder (& renames .tmx to .xml)"
from "${rootDir}/res"
into "${projectDir}/build/gen-res"
rename "(.*)\\.tmx", "\$1.xml"
}
task copyResValuesIn(type: Copy) {
description "Exception Indonesian language code (Old IN was renamed to now ID)"
from "${rootDir}/res/values-id/"
into "${projectDir}/build/gen-res/values-in/"
}
task copyTranslation(type: Copy) {
description("Copies the translation files to the modules translations folder")
from "${rootDir}/assets/translation"
into "${projectDir}/build/gen-assets/translation"
}
task cleanup(type: Delete) {
description("Deletes the assets/translation and the res folder from the modules folder")
delete "${projectDir}/build/gen-res", "${projectDir}/build/gen-assets/translation"
}
afterEvaluate {
project.tasks.copyRes.dependsOn project.tasks.copyResValuesIn
mergeDebugResources.dependsOn project.tasks.copyRes
extractDeepLinksDebug.dependsOn project.tasks.copyRes
mergeReleaseResources.dependsOn project.tasks.copyRes
extractDeepLinksRelease.dependsOn project.tasks.copyRes
mergeDebugAssets.dependsOn project.tasks.copyTranslation
mergeReleaseAssets.dependsOn project.tasks.copyTranslation
extractDeepLinksDebug.dependsOn project.tasks.copyTranslation
extractDeepLinksRelease.dependsOn project.tasks.copyTranslation
clean.dependsOn project.tasks.cleanup
}

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="utf-8"?>
<lint>
<issue id="MissingTranslation" severity="ignore" />
<issue id="TypographyDashes" severity="ignore" />

View File

@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.gpl.rpg.AndorsTrail"
android:versionCode="75"
android:versionName="0.8.9dev"
android:installLocation="auto"
>
<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"
android:anyDensity="true"
/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:name="com.gpl.rpg.AndorsTrail.AndorsTrailApplication"
android:label="@string/app_name"
android:icon="@drawable/${icon_name}"
android:description="@string/app_description"
android:allowBackup="true"
android:theme="@style/AndorsTrailTheme_Blue"
android:requestLegacyExternalStorage="true"
android:hasFragileUserData="true"
android:preserveLegacyExternalStorage="true"
>
<activity
android:exported="true"
android:name="com.gpl.rpg.AndorsTrail.activity.StartScreenActivity"
android:clearTaskOnLaunch="true"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.gpl.rpg.AndorsTrail.activity.MainActivity"
android:label="@string/app_name"
android:theme="@style/AndorsTrailTheme_Blue.NoBackground"
/>
<activity android:name="com.gpl.rpg.AndorsTrail.activity.HeroinfoActivity" />
<activity android:name="com.gpl.rpg.AndorsTrail.activity.MonsterInfoActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name="com.gpl.rpg.AndorsTrail.activity.ItemInfoActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name="com.gpl.rpg.AndorsTrail.activity.LevelUpActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name="com.gpl.rpg.AndorsTrail.activity.MonsterEncounterActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name="com.gpl.rpg.AndorsTrail.activity.ConversationActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name="com.gpl.rpg.AndorsTrail.activity.ShopActivity" />
<activity android:name="com.gpl.rpg.AndorsTrail.activity.AboutActivity" />
<activity android:name="com.gpl.rpg.AndorsTrail.activity.LoadingActivity" />
<activity android:name="com.gpl.rpg.AndorsTrail.activity.Preferences" />
<activity android:name="com.gpl.rpg.AndorsTrail.activity.LoadSaveActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name="com.gpl.rpg.AndorsTrail.activity.ActorConditionInfoActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name="com.gpl.rpg.AndorsTrail.activity.BulkSelectionInterface" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name="com.gpl.rpg.AndorsTrail.activity.SkillInfoActivity" android:theme="@style/AndorsTrailDialogTheme_Blue" />
<activity android:name="com.gpl.rpg.AndorsTrail.activity.DisplayWorldMapActivity" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/fileprovider" />
</provider>
</application>
</manifest>

View File

@@ -1,169 +1,169 @@
package com.gpl.rpg.AndorsTrail;
import java.io.File;
import java.io.IOException;
import java.util.Locale;
import com.gpl.rpg.AndorsTrail.context.ControllerContext;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.controller.Constants;
import com.gpl.rpg.AndorsTrail.util.AndroidStorage;
import com.gpl.rpg.AndorsTrail.util.Pair;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Environment;
import android.view.Window;
import android.view.WindowManager;
public final class AndorsTrailApplication extends Application {
public static final boolean DEVELOPMENT_DEBUGRESOURCES = false;
public static final boolean DEVELOPMENT_FORCE_STARTNEWGAME = false;
public static final boolean DEVELOPMENT_FORCE_CONTINUEGAME = false;
public static final boolean DEVELOPMENT_DEBUGBUTTONS = false;
public static final boolean DEVELOPMENT_FASTSPEED = false;
public static final boolean DEVELOPMENT_VALIDATEDATA = false;
public static final boolean DEVELOPMENT_DEBUGMESSAGES = false;
public static final String CURRENT_VERSION_DISPLAY = "0.7.16";
public static final boolean IS_RELEASE_VERSION = !CURRENT_VERSION_DISPLAY.matches(".*[a-d].*");
public static final boolean DEVELOPMENT_INCOMPATIBLE_SAVEGAMES = DEVELOPMENT_DEBUGRESOURCES || DEVELOPMENT_DEBUGBUTTONS || DEVELOPMENT_FASTSPEED || !IS_RELEASE_VERSION;
public static final int DEVELOPMENT_INCOMPATIBLE_SAVEGAME_VERSION = 999;
public static final int CURRENT_VERSION = DEVELOPMENT_INCOMPATIBLE_SAVEGAMES ? DEVELOPMENT_INCOMPATIBLE_SAVEGAME_VERSION : 63;
private final AndorsTrailPreferences preferences = new AndorsTrailPreferences();
private WorldContext world = new WorldContext();
private ControllerContext controllers = new ControllerContext(this, world);
private WorldSetup setup = new WorldSetup(world, controllers, this);
public WorldContext getWorld() { return world; }
public WorldSetup getWorldSetup() { return setup; }
public AndorsTrailPreferences getPreferences() { return preferences; }
public ControllerContext getControllerContext() { return controllers; }
public static AndorsTrailApplication getApplicationFromActivity(Activity activity) {
return ((AndorsTrailApplication) activity.getApplication());
}
public static AndorsTrailApplication getApplicationFromActivityContext(Context context) {
return getApplicationFromActivity(getActivityFromActivityContext(context));
}
private static Activity getActivityFromActivityContext(Context context) {
return (Activity) context;
}
public boolean isInitialized() { return world.model != null; }
public void setWindowParameters(Activity activity) {
activity.requestWindowFeature(Window.FEATURE_NO_TITLE);
if (preferences.fullscreen) {
activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
} else {
activity.getWindow().setFlags(0, WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
}
//Get default locale at startup, as somehow it seems that changing the app's
//configured locale impacts the value returned by Locale.getDefault() nowadays.
private final Locale defaultLocale = Locale.getDefault();
private Pair<String, Locale> lastLocale = null;
public boolean setLocale(Activity context) {
Resources res = context.getResources();
Configuration conf = res.getConfiguration();
Locale targetLocale;
if (lastLocale != null && lastLocale.first == preferences.language) {
targetLocale = lastLocale.second;
} else {
targetLocale = localeForLanguageTag(preferences.language);
lastLocale = new Pair<String, Locale>(preferences.language, targetLocale);
}
if (targetLocale.equals(conf.locale)) {
return false;
}
conf.locale = targetLocale;
res.updateConfiguration(conf, res.getDisplayMetrics());
this.getResources().updateConfiguration(conf, res.getDisplayMetrics());
return true;
}
// Supports language or language_COUNTRY in short form e.g. "en" or "en_US"
private Locale localeForLanguageTag(String languageTag) {
Locale locale = null;
if (languageTag != null && !languageTag.equalsIgnoreCase("default")) {
final int pos = languageTag.indexOf('-');
if (pos == -1) {
locale = new Locale(languageTag);
}
else locale = new Locale(languageTag.substring(0, pos), languageTag.substring(pos+1));
}
if (locale == null) {
locale = defaultLocale;
}
return locale;
}
/**
* Logging to text file system as found on https://stackoverflow.com/questions/19565685/saving-logcat-to-a-text-file-in-android-device
*/
public void onCreate() {
super.onCreate();
if ( DEVELOPMENT_DEBUGMESSAGES && isExternalStorageWritable() ) {
File appDirectory = AndroidStorage.getStorageDirectory(getApplicationContext(), Constants.FILENAME_SAVEGAME_DIRECTORY);
File logDirectory = new File( appDirectory, "log" );
File logFile = new File( logDirectory, "logcat" + System.currentTimeMillis() + ".txt" );
// create app folder
if ( !appDirectory.exists() ) {
appDirectory.mkdir();
}
// create log folder
if ( !logDirectory.exists() ) {
logDirectory.mkdir();
}
// clear the previous logcat and then write the new one to the file
try {
Process process = Runtime.getRuntime().exec("logcat -c");
process = Runtime.getRuntime().exec("logcat -f " + logFile+" *:W");
} catch ( IOException e ) {
e.printStackTrace();
}
}
}
/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if ( Environment.MEDIA_MOUNTED.equals( state ) ) {
return true;
}
return false;
}
/* Checks if external storage is available to at least read */
public boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
if ( Environment.MEDIA_MOUNTED.equals( state ) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals( state ) ) {
return true;
}
return false;
}
public void discardWorld() {
world = new WorldContext();
controllers = new ControllerContext(this, world);
setup = new WorldSetup(world, controllers, getApplicationContext());
}
}
package com.gpl.rpg.AndorsTrail;
import java.io.File;
import java.io.IOException;
import java.util.Locale;
import com.gpl.rpg.AndorsTrail.context.ControllerContext;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.controller.Constants;
import com.gpl.rpg.AndorsTrail.util.AndroidStorage;
import com.gpl.rpg.AndorsTrail.util.Pair;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Environment;
import android.view.Window;
import android.view.WindowManager;
public final class AndorsTrailApplication extends Application {
public static final boolean DEVELOPMENT_DEBUGRESOURCES = false;
public static final boolean DEVELOPMENT_FORCE_STARTNEWGAME = false;
public static final boolean DEVELOPMENT_FORCE_CONTINUEGAME = false;
public static final boolean DEVELOPMENT_DEBUGBUTTONS = true;
public static final boolean DEVELOPMENT_FASTSPEED = false;
public static final boolean DEVELOPMENT_VALIDATEDATA = true;
public static final boolean DEVELOPMENT_DEBUGMESSAGES = true;
public static final String CURRENT_VERSION_DISPLAY = "0.8.9dev";
public static final boolean IS_RELEASE_VERSION = !CURRENT_VERSION_DISPLAY.matches(".*[a-d].*");
public static final boolean DEVELOPMENT_INCOMPATIBLE_SAVEGAMES = DEVELOPMENT_DEBUGRESOURCES || DEVELOPMENT_DEBUGBUTTONS || DEVELOPMENT_FASTSPEED || !IS_RELEASE_VERSION;
public static final int DEVELOPMENT_INCOMPATIBLE_SAVEGAME_VERSION = 999;
public static final int CURRENT_VERSION = DEVELOPMENT_INCOMPATIBLE_SAVEGAMES ? DEVELOPMENT_INCOMPATIBLE_SAVEGAME_VERSION : 75;
private final AndorsTrailPreferences preferences = new AndorsTrailPreferences();
private WorldContext world = new WorldContext();
private ControllerContext controllers = new ControllerContext(this, world);
private WorldSetup setup = new WorldSetup(world, controllers, this);
public WorldContext getWorld() { return world; }
public WorldSetup getWorldSetup() { return setup; }
public AndorsTrailPreferences getPreferences() { return preferences; }
public ControllerContext getControllerContext() { return controllers; }
public static AndorsTrailApplication getApplicationFromActivity(Activity activity) {
return ((AndorsTrailApplication) activity.getApplication());
}
public static AndorsTrailApplication getApplicationFromActivityContext(Context context) {
return getApplicationFromActivity(getActivityFromActivityContext(context));
}
private static Activity getActivityFromActivityContext(Context context) {
return (Activity) context;
}
public boolean isInitialized() { return world.model != null; }
public void setWindowParameters(Activity activity) {
activity.requestWindowFeature(Window.FEATURE_NO_TITLE);
if (preferences.fullscreen) {
activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
} else {
activity.getWindow().setFlags(0, WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
}
//Get default locale at startup, as somehow it seems that changing the app's
//configured locale impacts the value returned by Locale.getDefault() nowadays.
private final Locale defaultLocale = Locale.getDefault();
private Pair<String, Locale> lastLocale = null;
public boolean setLocale(Activity context) {
Resources res = context.getResources();
Configuration conf = res.getConfiguration();
Locale targetLocale;
if (lastLocale != null && lastLocale.first == preferences.language) {
targetLocale = lastLocale.second;
} else {
targetLocale = localeForLanguageTag(preferences.language);
lastLocale = new Pair<String, Locale>(preferences.language, targetLocale);
}
if (targetLocale.equals(conf.locale)) {
return false;
}
conf.locale = targetLocale;
res.updateConfiguration(conf, res.getDisplayMetrics());
this.getResources().updateConfiguration(conf, res.getDisplayMetrics());
return true;
}
// Supports language or language_COUNTRY in short form e.g. "en" or "en_US"
private Locale localeForLanguageTag(String languageTag) {
Locale locale = null;
if (languageTag != null && !languageTag.equalsIgnoreCase("default")) {
final int pos = languageTag.indexOf('-');
if (pos == -1) {
locale = new Locale(languageTag);
}
else locale = new Locale(languageTag.substring(0, pos), languageTag.substring(pos+1));
}
if (locale == null) {
locale = defaultLocale;
}
return locale;
}
/**
* Logging to text file system as found on https://stackoverflow.com/questions/19565685/saving-logcat-to-a-text-file-in-android-device
*/
public void onCreate() {
super.onCreate();
if ( DEVELOPMENT_DEBUGMESSAGES && isExternalStorageWritable() ) {
File appDirectory = AndroidStorage.getStorageDirectory(getApplicationContext(), Constants.FILENAME_SAVEGAME_DIRECTORY);
File logDirectory = new File( appDirectory, "log" );
File logFile = new File( logDirectory, "logcat" + System.currentTimeMillis() + ".txt" );
// create app folder
if ( !appDirectory.exists() ) {
appDirectory.mkdir();
}
// create log folder
if ( !logDirectory.exists() ) {
logDirectory.mkdir();
}
// clear the previous logcat and then write the new one to the file
try {
Process process = Runtime.getRuntime().exec("logcat -c");
process = Runtime.getRuntime().exec("logcat -f " + logFile+" *:W");
} catch ( IOException e ) {
e.printStackTrace();
}
}
}
/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if ( Environment.MEDIA_MOUNTED.equals( state ) ) {
return true;
}
return false;
}
/* Checks if external storage is available to at least read */
public boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
if ( Environment.MEDIA_MOUNTED.equals( state ) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals( state ) ) {
return true;
}
return false;
}
public void discardWorld() {
world = new WorldContext();
controllers = new ControllerContext(this, world);
setup = new WorldSetup(world, controllers, getApplicationContext());
}
}

View File

@@ -1,114 +1,112 @@
package com.gpl.rpg.AndorsTrail;
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
public final class AndorsTrailPreferences {
public static final int DISPLAYLOOT_DIALOG_ALWAYS = 0;
public static final int DISPLAYLOOT_DIALOG_FOR_ITEMS = 3;
public static final int DISPLAYLOOT_DIALOG_FOR_ITEMS_ELSE_TOAST = 4;
public static final int DISPLAYLOOT_TOAST = 1;
public static final int DISPLAYLOOT_TOAST_FOR_ITEMS = 5;
public static final int DISPLAYLOOT_NONE = 2;
public static final int MOVEMENTMETHOD_STRAIGHT = 0;
public static final int MOVEMENTMETHOD_DIRECTIONAL = 1;
public static final int MOVEMENTAGGRESSIVENESS_NORMAL = 0;
public static final int MOVEMENTAGGRESSIVENESS_AGGRESSIVE = 1;
public static final int MOVEMENTAGGRESSIVENESS_DEFENSIVE = 2;
public static final int DPAD_POSITION_DISABLED = 0;
public static final int DPAD_POSITION_LOWER_RIGHT = 1;
public static final int DPAD_POSITION_LOWER_LEFT = 2;
public static final int DPAD_POSITION_LOWER_CENTER = 3;
public static final int DPAD_POSITION_CENTER_LEFT = 4;
public static final int DPAD_POSITION_CENTER_RIGHT = 5;
public static final int DPAD_POSITION_UPPER_LEFT = 6;
public static final int DPAD_POSITION_UPPER_RIGHT = 7;
public static final int DPAD_POSITION_UPPER_CENTER = 8;
public static final int DPAD_TRANSPARENCY_30_PERCENT = 0;
public static final int DPAD_TRANSPARENCY_40_PERCENT = 1;
public static final int DPAD_TRANSPARENCY_50_PERCENT = 2;
public static final int DPAD_TRANSPARENCY_60_PERCENT = 3;
public static final int DPAD_TRANSPARENCY_70_PERCENT = 4;
public static final int CONFIRM_OVERWRITE_SAVEGAME_ALWAYS = 0;
public static final int CONFIRM_OVERWRITE_SAVEGAME_WHEN_PLAYERNAME_DIFFERS = 1;
public static final int CONFIRM_OVERWRITE_SAVEGAME_NEVER = 2;
public static final int QUICKSLOTS_POSITION_HORIZONTAL_CENTER_BOTTOM = 0;
public static final int QUICKSLOTS_POSITION_VERTICAL_CENTER_LEFT = 1;
public static final int QUICKSLOTS_POSITION_VERTICAL_CENTER_RIGHT = 2;
public static final int QUICKSLOTS_POSITION_VERTICAL_BOTTOM_LEFT = 3;
public static final int QUICKSLOTS_POSITION_HORIZONTAL_BOTTOM_LEFT = 4;
public static final int QUICKSLOTS_POSITION_HORIZONTAL_BOTTOM_RIGHT = 5;
public static final int QUICKSLOTS_POSITION_VERTICAL_BOTTOM_RIGHT = 6;
public static final int ATTACKSPEED_DEFAULT_MILLISECONDS = 1000;
public boolean confirmRest = true;
public boolean confirmAttack = true;
public int displayLoot = DISPLAYLOOT_DIALOG_ALWAYS;
public boolean fullscreen = true;
public int attackspeed_milliseconds = 1000;
public int movementMethod = MOVEMENTMETHOD_STRAIGHT;
public int movementAggressiveness = MOVEMENTAGGRESSIVENESS_NORMAL;
public float scalingFactor = 1.0f;
public int dpadPosition;
public int dpadTransparency;
public boolean dpadMinimizeable = true;
public boolean optimizedDrawing = false;
public boolean highQualityFilters = true;
public boolean enableUiAnimations = true;
public int displayOverwriteSavegame = CONFIRM_OVERWRITE_SAVEGAME_ALWAYS;
public int quickslotsPosition = QUICKSLOTS_POSITION_HORIZONTAL_CENTER_BOTTOM;
public boolean showQuickslotsWhenToolboxIsVisible = false;
public String language = "default";
public int selectedTheme = 0;
public void read(final Context androidContext) {
AndorsTrailPreferences dest = this;
try {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(androidContext);
dest.confirmRest = prefs.getBoolean("confirm_rest", true);
dest.confirmAttack = prefs.getBoolean("confirm_attack", true);
dest.displayLoot = Integer.parseInt(prefs.getString("display_lootdialog", Integer.toString(DISPLAYLOOT_DIALOG_ALWAYS)));
dest.fullscreen = prefs.getBoolean("fullscreen", true);
dest.attackspeed_milliseconds = Integer.parseInt(prefs.getString("attackspeed", "1000"));
dest.movementMethod = Integer.parseInt(prefs.getString("movementmethod", Integer.toString(MOVEMENTMETHOD_STRAIGHT)));
dest.scalingFactor = Float.parseFloat(prefs.getString("scaling_factor", "1.0f"));
dest.dpadPosition = Integer.parseInt(prefs.getString("dpadposition", Integer.toString(DPAD_POSITION_DISABLED)));
dest.dpadTransparency = Integer.parseInt(prefs.getString("dpadtransparency", Integer.toString(DPAD_TRANSPARENCY_50_PERCENT)));
dest.dpadMinimizeable = prefs.getBoolean("dpadMinimizeable", true);
dest.optimizedDrawing = prefs.getBoolean("optimized_drawing", false);
dest.highQualityFilters = prefs.getBoolean("high_quality_filters", true);
dest.enableUiAnimations = prefs.getBoolean("enableUiAnimations", true);
dest.displayOverwriteSavegame = Integer.parseInt(prefs.getString("display_overwrite_savegame", Integer.toString(CONFIRM_OVERWRITE_SAVEGAME_ALWAYS)));
dest.quickslotsPosition = Integer.parseInt(prefs.getString("quickslots_placement", Integer.toString(QUICKSLOTS_POSITION_HORIZONTAL_CENTER_BOTTOM)));
dest.showQuickslotsWhenToolboxIsVisible = prefs.getBoolean("showQuickslotsWhenToolboxIsVisible", false);
dest.language = prefs.getString("language", "default");
dest.selectedTheme = Integer.parseInt(prefs.getString("selectedTheme", Integer.toString(0)));
// This might be implemented as a skill in the future.
//dest.movementAggressiveness = Integer.parseInt(prefs.getString("movementaggressiveness", Integer.toString(MOVEMENTAGGRESSIVENESS_NORMAL)));
} catch (Exception e) {
dest.confirmRest = true;
dest.confirmAttack = true;
dest.displayLoot = DISPLAYLOOT_DIALOG_ALWAYS;
dest.fullscreen = true;
dest.attackspeed_milliseconds = 1000;
dest.movementMethod = MOVEMENTMETHOD_STRAIGHT;
dest.movementAggressiveness = MOVEMENTAGGRESSIVENESS_NORMAL;
dest.scalingFactor = 1.0f;
dest.dpadPosition = DPAD_POSITION_DISABLED;
dest.dpadTransparency = DPAD_TRANSPARENCY_50_PERCENT;
dest.dpadMinimizeable = true;
dest.optimizedDrawing = false;
dest.highQualityFilters = true;
dest.enableUiAnimations = true;
dest.displayOverwriteSavegame = CONFIRM_OVERWRITE_SAVEGAME_ALWAYS;
dest.quickslotsPosition = QUICKSLOTS_POSITION_HORIZONTAL_CENTER_BOTTOM;
dest.showQuickslotsWhenToolboxIsVisible = false;
dest.language = "default";
dest.selectedTheme = 0;
}
}
}
package com.gpl.rpg.AndorsTrail;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
public final class AndorsTrailPreferences {
public static final int DISPLAYLOOT_DIALOG_ALWAYS = 0;
public static final int DISPLAYLOOT_DIALOG_FOR_ITEMS = 3;
public static final int DISPLAYLOOT_DIALOG_FOR_ITEMS_ELSE_TOAST = 4;
public static final int DISPLAYLOOT_TOAST = 1;
public static final int DISPLAYLOOT_TOAST_FOR_ITEMS = 5;
public static final int DISPLAYLOOT_NONE = 2;
public static final int MOVEMENTMETHOD_STRAIGHT = 0;
public static final int MOVEMENTMETHOD_DIRECTIONAL = 1;
public static final int MOVEMENTAGGRESSIVENESS_NORMAL = 0;
public static final int MOVEMENTAGGRESSIVENESS_AGGRESSIVE = 1;
public static final int MOVEMENTAGGRESSIVENESS_DEFENSIVE = 2;
public static final int DPAD_POSITION_DISABLED = 0;
public static final int DPAD_POSITION_LOWER_RIGHT = 1;
public static final int DPAD_POSITION_LOWER_LEFT = 2;
public static final int DPAD_POSITION_LOWER_CENTER = 3;
public static final int DPAD_POSITION_CENTER_LEFT = 4;
public static final int DPAD_POSITION_CENTER_RIGHT = 5;
public static final int DPAD_POSITION_UPPER_LEFT = 6;
public static final int DPAD_POSITION_UPPER_RIGHT = 7;
public static final int DPAD_POSITION_UPPER_CENTER = 8;
public static final int DPAD_TRANSPARENCY_30_PERCENT = 0;
public static final int DPAD_TRANSPARENCY_40_PERCENT = 1;
public static final int DPAD_TRANSPARENCY_50_PERCENT = 2;
public static final int DPAD_TRANSPARENCY_60_PERCENT = 3;
public static final int DPAD_TRANSPARENCY_70_PERCENT = 4;
public static final int CONFIRM_OVERWRITE_SAVEGAME_ALWAYS = 0;
public static final int CONFIRM_OVERWRITE_SAVEGAME_WHEN_PLAYERNAME_DIFFERS = 1;
public static final int CONFIRM_OVERWRITE_SAVEGAME_NEVER = 2;
public static final int QUICKSLOTS_POSITION_HORIZONTAL_CENTER_BOTTOM = 0;
public static final int QUICKSLOTS_POSITION_VERTICAL_CENTER_LEFT = 1;
public static final int QUICKSLOTS_POSITION_VERTICAL_CENTER_RIGHT = 2;
public static final int QUICKSLOTS_POSITION_VERTICAL_BOTTOM_LEFT = 3;
public static final int QUICKSLOTS_POSITION_HORIZONTAL_BOTTOM_LEFT = 4;
public static final int QUICKSLOTS_POSITION_HORIZONTAL_BOTTOM_RIGHT = 5;
public static final int QUICKSLOTS_POSITION_VERTICAL_BOTTOM_RIGHT = 6;
public static final int ATTACKSPEED_DEFAULT_MILLISECONDS = 1000;
public boolean confirmRest = true;
public boolean confirmAttack = true;
public int displayLoot = DISPLAYLOOT_DIALOG_ALWAYS;
public boolean fullscreen = true;
public int attackspeed_milliseconds = 1000;
public int movementMethod = MOVEMENTMETHOD_STRAIGHT;
public int movementAggressiveness = MOVEMENTAGGRESSIVENESS_NORMAL;
public float scalingFactor = 1.0f;
public int dpadPosition;
public int dpadTransparency;
public boolean dpadMinimizeable = true;
public boolean optimizedDrawing = false;
public boolean highQualityFilters = true;
public boolean enableUiAnimations = true;
public int displayOverwriteSavegame = CONFIRM_OVERWRITE_SAVEGAME_ALWAYS;
public int quickslotsPosition = QUICKSLOTS_POSITION_HORIZONTAL_CENTER_BOTTOM;
public boolean showQuickslotsWhenToolboxIsVisible = false;
public String language = "default";
public int selectedTheme = 0;
public void read(final Context androidContext) {
AndorsTrailPreferences dest = this;
try {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(androidContext);
dest.confirmRest = prefs.getBoolean("confirm_rest", true);
dest.confirmAttack = prefs.getBoolean("confirm_attack", true);
dest.displayLoot = Integer.parseInt(prefs.getString("display_lootdialog", Integer.toString(DISPLAYLOOT_DIALOG_ALWAYS)));
dest.fullscreen = prefs.getBoolean("fullscreen", true);
dest.attackspeed_milliseconds = Integer.parseInt(prefs.getString("attackspeed", "1000"));
dest.movementMethod = Integer.parseInt(prefs.getString("movementmethod", Integer.toString(MOVEMENTMETHOD_STRAIGHT)));
dest.scalingFactor = Float.parseFloat(prefs.getString("scaling_factor", "1.0f"));
dest.dpadPosition = Integer.parseInt(prefs.getString("dpadposition", Integer.toString(DPAD_POSITION_DISABLED)));
dest.dpadTransparency = Integer.parseInt(prefs.getString("dpadtransparency", Integer.toString(DPAD_TRANSPARENCY_50_PERCENT)));
dest.dpadMinimizeable = prefs.getBoolean("dpadMinimizeable", true);
dest.optimizedDrawing = prefs.getBoolean("optimized_drawing", false);
dest.highQualityFilters = prefs.getBoolean("high_quality_filters", false);
dest.enableUiAnimations = prefs.getBoolean("enableUiAnimations", true);
dest.displayOverwriteSavegame = Integer.parseInt(prefs.getString("display_overwrite_savegame", Integer.toString(CONFIRM_OVERWRITE_SAVEGAME_ALWAYS)));
dest.quickslotsPosition = Integer.parseInt(prefs.getString("quickslots_placement", Integer.toString(QUICKSLOTS_POSITION_HORIZONTAL_CENTER_BOTTOM)));
dest.showQuickslotsWhenToolboxIsVisible = prefs.getBoolean("showQuickslotsWhenToolboxIsVisible", false);
dest.language = prefs.getString("language", "default");
dest.selectedTheme = Integer.parseInt(prefs.getString("selectedTheme", Integer.toString(0)));
// This might be implemented as a skill in the future.
//dest.movementAggressiveness = Integer.parseInt(prefs.getString("movementaggressiveness", Integer.toString(MOVEMENTAGGRESSIVENESS_NORMAL)));
} catch (Exception e) {
dest.confirmRest = true;
dest.confirmAttack = true;
dest.displayLoot = DISPLAYLOOT_DIALOG_ALWAYS;
dest.fullscreen = true;
dest.attackspeed_milliseconds = 1000;
dest.movementMethod = MOVEMENTMETHOD_STRAIGHT;
dest.movementAggressiveness = MOVEMENTAGGRESSIVENESS_NORMAL;
dest.scalingFactor = 1.0f;
dest.dpadPosition = DPAD_POSITION_DISABLED;
dest.dpadTransparency = DPAD_TRANSPARENCY_50_PERCENT;
dest.dpadMinimizeable = true;
dest.optimizedDrawing = false;
dest.highQualityFilters = true;
dest.enableUiAnimations = true;
dest.displayOverwriteSavegame = CONFIRM_OVERWRITE_SAVEGAME_ALWAYS;
dest.quickslotsPosition = QUICKSLOTS_POSITION_HORIZONTAL_CENTER_BOTTOM;
dest.showQuickslotsWhenToolboxIsVisible = false;
dest.language = "default";
dest.selectedTheme = 0;
}
}
}

View File

@@ -1,478 +1,476 @@
package com.gpl.rpg.AndorsTrail;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import android.*;
import android.Manifest;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import com.gpl.rpg.AndorsTrail.activity.ActorConditionInfoActivity;
import com.gpl.rpg.AndorsTrail.activity.BulkSelectionInterface;
import com.gpl.rpg.AndorsTrail.activity.ConversationActivity;
import com.gpl.rpg.AndorsTrail.activity.ItemInfoActivity;
import com.gpl.rpg.AndorsTrail.activity.LevelUpActivity;
import com.gpl.rpg.AndorsTrail.activity.LoadSaveActivity;
import com.gpl.rpg.AndorsTrail.activity.MainActivity;
import com.gpl.rpg.AndorsTrail.activity.MonsterEncounterActivity;
import com.gpl.rpg.AndorsTrail.activity.MonsterInfoActivity;
import com.gpl.rpg.AndorsTrail.activity.SkillInfoActivity;
import com.gpl.rpg.AndorsTrail.activity.fragment.StartScreenActivity_MainMenu;
import com.gpl.rpg.AndorsTrail.context.ControllerContext;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.model.ability.ActorConditionType;
import com.gpl.rpg.AndorsTrail.model.ability.SkillCollection;
import com.gpl.rpg.AndorsTrail.model.actor.Monster;
import com.gpl.rpg.AndorsTrail.model.item.Inventory;
import com.gpl.rpg.AndorsTrail.model.item.ItemType;
import com.gpl.rpg.AndorsTrail.model.item.Loot;
import com.gpl.rpg.AndorsTrail.model.map.MapObject;
import com.gpl.rpg.AndorsTrail.savegames.Savegames;
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory;
import com.gpl.rpg.AndorsTrail.view.ItemContainerAdapter;
public final class Dialogs {
private static void showDialogAndPause(Dialog d, final ControllerContext context) {
showDialogAndPause(d, context, null);
}
private static void showDialogAndPause(Dialog d, final ControllerContext context, final OnDismissListener onDismiss) {
context.gameRoundController.pause();
CustomDialogFactory.setDismissListener(d, new OnDismissListener() {
@Override
public void onDismiss(DialogInterface arg0) {
if (onDismiss != null) onDismiss.onDismiss(arg0);
context.gameRoundController.resume();
}
});
CustomDialogFactory.show(d);
}
public static void showKeyArea(final MainActivity currentActivity, final ControllerContext context, String phraseID) {
showConversation(currentActivity, context, phraseID, null);
}
public static void showMapSign(final MainActivity currentActivity, final ControllerContext context, String phraseID) {
showConversation(currentActivity, context, phraseID, null);
}
public static void showMapScriptMessage(final MainActivity currentActivity, final ControllerContext context, String phraseID) {
showConversation(currentActivity, context, phraseID, null, false);
}
public static void showConversation(final MainActivity currentActivity, final ControllerContext context, final String phraseID, final Monster npc) {
showConversation(currentActivity, context, phraseID, npc, true);
}
private static void showConversation(final MainActivity currentActivity, final ControllerContext context, final String phraseID, final Monster npc, boolean applyScriptEffectsForFirstPhrase) {
context.gameRoundController.pause();
Intent intent = new Intent(currentActivity, ConversationActivity.class);
intent.setData(Uri.parse("content://com.gpl.rpg.AndorsTrail/conversation/" + phraseID));
intent.putExtra("applyScriptEffectsForFirstPhrase", applyScriptEffectsForFirstPhrase);
addMonsterIdentifiers(intent, npc);
currentActivity.startActivityForResult(intent, MainActivity.INTENTREQUEST_CONVERSATION);
}
public static void addMonsterIdentifiers(Intent intent, Monster monster) {
if (monster == null) return;
intent.putExtra("x", monster.position.x);
intent.putExtra("y", monster.position.y);
}
public static void addMonsterIdentifiers(Bundle bundle, Monster monster) {
if (monster == null) return;
bundle.putInt("x", monster.position.x);
bundle.putInt("y", monster.position.y);
}
public static Monster getMonsterFromIntent(Intent intent, final WorldContext world) {
return getMonsterFromBundle(intent.getExtras(), world);
}
public static Monster getMonsterFromBundle(Bundle params, final WorldContext world) {
if (params == null) return null;
if (!params.containsKey("x")) return null;
int x = params.getInt("x");
int y = params.getInt("y");
return world.model.currentMaps.map.getMonsterAt(x, y);
}
public static void showMonsterEncounter(final MainActivity currentActivity, final ControllerContext context, final Monster monster) {
context.gameRoundController.pause();
Intent intent = new Intent(currentActivity, MonsterEncounterActivity.class);
intent.setData(Uri.parse("content://com.gpl.rpg.AndorsTrail/monsterencounter"));
addMonsterIdentifiers(intent, monster);
currentActivity.startActivityForResult(intent, MainActivity.INTENTREQUEST_MONSTERENCOUNTER);
}
public static void showMonsterInfo(final Context context, final Monster monster) {
Intent intent = new Intent(context, MonsterInfoActivity.class);
intent.setData(Uri.parse("content://com.gpl.rpg.AndorsTrail/monsterinfo"));
addMonsterIdentifiers(intent, monster);
context.startActivity(intent);
}
public static String getGroundLootFoundMessage(final Context ctx, final Loot loot) {
StringBuilder sb = new StringBuilder(60);
if (!loot.items.isEmpty()) {
sb.append(ctx.getString(R.string.dialog_groundloot_message));
}
appendGoldPickedUpMessage(ctx, loot, sb);
return sb.toString();
}
public static String getGroundLootPickedUpMessage(final Context ctx, final Loot loot) {
StringBuilder sb = new StringBuilder(60);
appendLootPickedUpMessage(ctx, loot, sb);
return sb.toString();
}
public static String getMonsterLootFoundMessage(final Context ctx, final Loot combinedLoot, final int exp) {
StringBuilder sb = new StringBuilder(60);
appendMonsterEncounterSurvivedMessage(ctx, sb, exp);
appendGoldPickedUpMessage(ctx, combinedLoot, sb);
return sb.toString();
}
public static String getMonsterLootPickedUpMessage(final Context ctx, final Loot combinedLoot, final int exp) {
StringBuilder sb = new StringBuilder(60);
appendMonsterEncounterSurvivedMessage(ctx, sb, exp);
appendLootPickedUpMessage(ctx, combinedLoot, sb);
return sb.toString();
}
private static void appendMonsterEncounterSurvivedMessage(final Context ctx, final StringBuilder sb, final int exp) {
sb.append(ctx.getString(R.string.dialog_monsterloot_message));
if (exp > 0) {
sb.append(' ');
sb.append(ctx.getString(R.string.dialog_monsterloot_gainedexp, exp));
}
}
private static void appendGoldPickedUpMessage(final Context ctx, final Loot loot, final StringBuilder sb) {
if (loot.gold > 0) {
sb.append(' ');
sb.append(ctx.getString(R.string.dialog_loot_foundgold, loot.gold));
}
}
private static void appendLootPickedUpMessage(final Context ctx, final Loot loot, final StringBuilder sb) {
appendGoldPickedUpMessage(ctx, loot, sb);
int numItems = loot.items.countItems();
if (numItems == 1) {
sb.append(' ');
sb.append(ctx.getString(R.string.dialog_loot_pickedupitem));
} else if (numItems > 1){
sb.append(' ');
sb.append(ctx.getString(R.string.dialog_loot_pickedupitems, numItems));
}
}
public static void showMonsterLoot(final MainActivity mainActivity, final ControllerContext controllers, final WorldContext world, final Collection<Loot> lootBags, final Loot combinedLoot, final String msg) {
// CombatController will do killedMonsterBags.clear() after this method has been called,
// so we need to keep the list of objects. Therefore, we create a shallow copy of the list of bags.
ArrayList<Loot> bags = new ArrayList<Loot>(lootBags);
showLoot(mainActivity, controllers, world, combinedLoot, bags, R.string.dialog_monsterloot_title, msg);
}
public static void showGroundLoot(final MainActivity mainActivity, final ControllerContext controllers, final WorldContext world, final Loot loot, final String msg) {
showLoot(mainActivity, controllers, world, loot, Collections.singletonList(loot), R.string.dialog_groundloot_title, msg);
}
private static void showLoot(final MainActivity mainActivity, final ControllerContext controllers, final WorldContext world, final Loot combinedLoot, final Iterable<Loot> lootBags, final int title, final String msg) {
final ListView itemList = new ListView(mainActivity);
itemList.setBackgroundResource(android.R.color.transparent);
itemList.setLayoutParams(new ListView.LayoutParams(ListView.LayoutParams.MATCH_PARENT, ListView.LayoutParams.WRAP_CONTENT));
// itemList.setPadding(20, 0, 20, 20);
itemList.setAdapter(new ItemContainerAdapter(mainActivity, world.tileManager, combinedLoot.items, world.model.player));
final Dialog d = CustomDialogFactory.createDialog(mainActivity,
mainActivity.getResources().getString(title),
mainActivity.getResources().getDrawable(R.drawable.ui_icon_equipment),
msg,
combinedLoot.items.isEmpty() ? null : itemList,
true,
false);
itemList.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
final String itemTypeID = ((ItemContainerAdapter) parent.getAdapter()).getItem(position).itemType.id;
boolean removeFromCombinedLoot = true;
for (Loot l : lootBags) {
if (l == combinedLoot) removeFromCombinedLoot = false;
if (l.items.removeItem(itemTypeID)) {
controllers.itemController.removeLootBagIfEmpty(l);
break;
}
}
if (removeFromCombinedLoot) {
combinedLoot.items.removeItem(itemTypeID);
}
if (((ItemContainerAdapter) parent.getAdapter()).isEmpty()) {
ViewGroup vg = (ViewGroup) d.findViewById(R.id.dialog_content_container);
vg.setVisibility(View.GONE);
}
ItemType type = world.itemTypes.getItemType(itemTypeID);
world.model.player.inventory.addItem(type);
((ItemContainerAdapter) itemList.getAdapter()).notifyDataSetChanged();
}
});
if (!itemList.getAdapter().isEmpty()) {
CustomDialogFactory.addButton(d, R.string.dialog_loot_pickall, new View.OnClickListener() {
@Override
public void onClick(View v) {
controllers.itemController.pickupAll(lootBags);
}
});
}
CustomDialogFactory.addDismissButton(d, R.string.dialog_close);
showDialogAndPause(d, controllers, new OnDismissListener() {
@Override
public void onDismiss(DialogInterface arg0) {
controllers.itemController.removeLootBagIfEmpty(lootBags);
}
});
}
public static void showHeroDied(final MainActivity mainActivity, final ControllerContext controllers) {
final Dialog d = CustomDialogFactory.createDialog(mainActivity,
mainActivity.getResources().getString(R.string.dialog_game_over_title),
mainActivity.getResources().getDrawable(R.drawable.ui_icon_combat),
mainActivity.getResources().getString(R.string.dialog_game_over_text),
null,
true,
false);
CustomDialogFactory.addDismissButton(d, android.R.string.ok);
showDialogAndPause(d, controllers, new OnDismissListener() {
@Override
public void onDismiss(DialogInterface arg0) {
mainActivity.finish();
}
});
}
public static Intent getIntentForItemInfo(final Context ctx, String itemTypeID, ItemInfoActivity.ItemInfoAction actionType, String buttonText, boolean buttonEnabled, Inventory.WearSlot inventorySlot) {
Intent intent = new Intent(ctx, ItemInfoActivity.class);
intent.putExtra("buttonText", buttonText);
intent.putExtra("buttonEnabled", buttonEnabled);
intent.putExtra("moreActions", (actionType == ItemInfoActivity.ItemInfoAction.equip || actionType == ItemInfoActivity.ItemInfoAction.use || actionType == ItemInfoActivity.ItemInfoAction.none));
intent.putExtra("itemTypeID", itemTypeID);
intent.putExtra("actionType", actionType.name());
if (inventorySlot != null) intent.putExtra("inventorySlot", inventorySlot.name());
intent.setData(Uri.parse("content://com.gpl.rpg.AndorsTrail/iteminfo/" + itemTypeID));
return intent;
}
public static Intent getIntentForLevelUp(final Context ctx) {
Intent intent = new Intent(ctx, LevelUpActivity.class);
intent.setData(Uri.parse("content://com.gpl.rpg.AndorsTrail/levelup"));
return intent;
}
public static void showConfirmRest(final Activity currentActivity, final ControllerContext controllerContext, final MapObject area) {
final Dialog d = CustomDialogFactory.createDialog(currentActivity,
currentActivity.getResources().getString(R.string.dialog_rest_title),
null,
currentActivity.getResources().getString(R.string.dialog_rest_confirm_message),
null,
true);
CustomDialogFactory.addButton(d, android.R.string.yes, new View.OnClickListener() {
@Override
public void onClick(View v) {
controllerContext.mapController.rest(area);
}
});
CustomDialogFactory.addDismissButton(d, android.R.string.no);
showDialogAndPause(d, controllerContext);
}
public static void showRested(final Activity currentActivity, final ControllerContext controllerContext) {
// Dialog d = new AlertDialog.Builder(new ContextThemeWrapper(currentActivity, R.style.AndorsTrailStyle))
// .setTitle(R.string.dialog_rest_title)
// .setMessage(R.string.dialog_rest_message)
// .setNeutralButton(android.R.string.ok, null)
// .create();
final Dialog d = CustomDialogFactory.createDialog(currentActivity,
currentActivity.getResources().getString(R.string.dialog_rest_title),
null,
currentActivity.getResources().getString(R.string.dialog_rest_message),
null,
true);
CustomDialogFactory.addDismissButton(d, android.R.string.ok);
showDialogAndPause(d, controllerContext);
}
public static void showNewVersion(final Activity currentActivity, final OnDismissListener onDismiss) {
// new AlertDialog.Builder(new ContextThemeWrapper(currentActivity, R.style.AndorsTrailStyle))
// .setTitle(R.string.dialog_newversion_title)
// .setMessage(R.string.dialog_newversion_message)
// .setNeutralButton(android.R.string.ok, null)
// .show();
String text = currentActivity.getResources().getString(R.string.dialog_newversion_message);
if (!hasPermissions(currentActivity) && Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
text += currentActivity.getResources().getString(R.string.dialog_newversion_permission_information);
}
final Dialog d = CustomDialogFactory.createDialog(currentActivity,
currentActivity.getResources().getString(R.string.dialog_newversion_title),
null,
text,
null,
true);
CustomDialogFactory.addDismissButton(d, android.R.string.ok);
CustomDialogFactory.setDismissListener(d, new OnDismissListener() {
@Override
public void onDismiss(DialogInterface arg0) {
if (onDismiss != null) onDismiss.onDismiss(arg0);
}
});
CustomDialogFactory.show(d);
}
@TargetApi(23)
private static boolean hasPermissions(final Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (activity.getApplicationContext().checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
|| activity.getApplicationContext().checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
public static boolean showSave(final Activity mainActivity, final ControllerContext controllerContext, final WorldContext world) {
if (world.model.uiSelections.isInCombat) {
Toast.makeText(mainActivity, R.string.menu_save_saving_not_allowed_in_combat, Toast.LENGTH_SHORT).show();
return false;
}
if (!world.model.statistics.hasUnlimitedSaves()) {
final Dialog d = CustomDialogFactory.createDialog(mainActivity,
mainActivity.getResources().getString(R.string.menu_save_switch_character_title),
null,
mainActivity.getResources().getString(R.string.menu_save_switch_character),
null,
true);
CustomDialogFactory.addButton(d, android.R.string.ok, new View.OnClickListener() {
@Override
public void onClick(View v) {
controllerContext.gameRoundController.pause();
Intent intent = new Intent(mainActivity, LoadSaveActivity.class);
intent.setData(Uri.parse("content://com.gpl.rpg.AndorsTrail/save"));
mainActivity.startActivityForResult(intent, MainActivity.INTENTREQUEST_SAVEGAME);
}
});
CustomDialogFactory.addDismissButton(d, android.R.string.cancel);
CustomDialogFactory.show(d);
return false;
} else {
controllerContext.gameRoundController.pause();
Intent intent = new Intent(mainActivity, LoadSaveActivity.class);
intent.setData(Uri.parse("content://com.gpl.rpg.AndorsTrail/save"));
mainActivity.startActivityForResult(intent, MainActivity.INTENTREQUEST_SAVEGAME);
return true;
}
}
public static void showLoad(final Activity currentActivity) {
Intent intent = new Intent(currentActivity, LoadSaveActivity.class);
intent.setData(Uri.parse("content://com.gpl.rpg.AndorsTrail/load"));
currentActivity.startActivityForResult(intent, StartScreenActivity_MainMenu.INTENTREQUEST_LOADGAME);
}
public static void showLoad(final Fragment currentFragment) {
Intent intent = new Intent(currentFragment.getActivity(), LoadSaveActivity.class);
intent.setData(Uri.parse("content://com.gpl.rpg.AndorsTrail/load"));
currentFragment.startActivityForResult(intent, StartScreenActivity_MainMenu.INTENTREQUEST_LOADGAME);
}
public static void showActorConditionInfo(final Context context, ActorConditionType conditionType) {
Intent intent = new Intent(context, ActorConditionInfoActivity.class);
intent.setData(Uri.parse("content://com.gpl.rpg.AndorsTrail/actorconditioninfo/" + conditionType.conditionTypeID));
context.startActivity(intent);
}
public static Intent getIntentForBulkBuyingInterface(final Context ctx, String itemTypeID, int totalAvailableAmount) {
return getIntentForBulkSelectionInterface(ctx, itemTypeID, totalAvailableAmount, BulkSelectionInterface.BulkInterfaceType.buy);
}
public static Intent getIntentForBulkSellingInterface(final Context ctx, String itemTypeID, int totalAvailableAmount) {
return getIntentForBulkSelectionInterface(ctx, itemTypeID, totalAvailableAmount, BulkSelectionInterface.BulkInterfaceType.sell);
}
public static Intent getIntentForBulkDroppingInterface(final Context ctx, String itemTypeID, int totalAvailableAmount) {
return getIntentForBulkSelectionInterface(ctx, itemTypeID, totalAvailableAmount, BulkSelectionInterface.BulkInterfaceType.drop);
}
private static Intent getIntentForBulkSelectionInterface(final Context ctx, String itemTypeID, int totalAvailableAmount, BulkSelectionInterface.BulkInterfaceType interfaceType) {
Intent intent = new Intent(ctx, BulkSelectionInterface.class);
intent.putExtra("itemTypeID", itemTypeID);
intent.putExtra("totalAvailableAmount", totalAvailableAmount);
intent.putExtra("interfaceType", interfaceType.name());
intent.setData(Uri.parse("content://com.gpl.rpg.AndorsTrail/bulkselection/" + itemTypeID));
return intent;
}
public static Intent getIntentForSkillInfo(final Context ctx, SkillCollection.SkillID skillID) {
Intent intent = new Intent(ctx, SkillInfoActivity.class);
intent.putExtra("skillID", skillID.name());
intent.setData(Uri.parse("content://com.gpl.rpg.AndorsTrail/showskillinfo/" + skillID));
return intent;
}
public static void showCombatLog(final Context context, final ControllerContext controllerContext, final WorldContext world) {
String[] combatLogMessages = world.model.combatLog.getAllMessages();
View view = null;
ListView itemList = null;
itemList = new ListView(context);
itemList.setLayoutParams(new ListView.LayoutParams(ListView.LayoutParams.MATCH_PARENT, ListView.LayoutParams.WRAP_CONTENT));
itemList.setStackFromBottom(true);
itemList.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
itemList.setChoiceMode(ListView.CHOICE_MODE_NONE);
itemList.setBackgroundColor(ThemeHelper.getThemeColor(context, R.attr.ui_theme_stdframe_bg_color));
if (combatLogMessages.length <= 0) {
combatLogMessages = new String[] {context.getResources().getString(R.string.combat_log_noentries)};
}
itemList.setAdapter(new ArrayAdapter<String>(context, R.layout.combatlog_row, android.R.id.text1, combatLogMessages));
view = itemList;
final Dialog d = CustomDialogFactory.createDialog(context,
context.getResources().getString(R.string.combat_log_title),
context.getResources().getDrawable(R.drawable.ui_icon_combat),
null,
view,
true);
CustomDialogFactory.addDismissButton(d, R.string.dialog_close);
showDialogAndPause(d, controllerContext);
}
}
package com.gpl.rpg.AndorsTrail;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import com.gpl.rpg.AndorsTrail.activity.ActorConditionInfoActivity;
import com.gpl.rpg.AndorsTrail.activity.BulkSelectionInterface;
import com.gpl.rpg.AndorsTrail.activity.ConversationActivity;
import com.gpl.rpg.AndorsTrail.activity.ItemInfoActivity;
import com.gpl.rpg.AndorsTrail.activity.LevelUpActivity;
import com.gpl.rpg.AndorsTrail.activity.LoadSaveActivity;
import com.gpl.rpg.AndorsTrail.activity.MainActivity;
import com.gpl.rpg.AndorsTrail.activity.MonsterEncounterActivity;
import com.gpl.rpg.AndorsTrail.activity.MonsterInfoActivity;
import com.gpl.rpg.AndorsTrail.activity.SkillInfoActivity;
import com.gpl.rpg.AndorsTrail.activity.fragment.StartScreenActivity_MainMenu;
import com.gpl.rpg.AndorsTrail.context.ControllerContext;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.model.ability.ActorConditionType;
import com.gpl.rpg.AndorsTrail.model.ability.SkillCollection;
import com.gpl.rpg.AndorsTrail.model.actor.Monster;
import com.gpl.rpg.AndorsTrail.model.item.Inventory;
import com.gpl.rpg.AndorsTrail.model.item.ItemType;
import com.gpl.rpg.AndorsTrail.model.item.Loot;
import com.gpl.rpg.AndorsTrail.model.map.MapObject;
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory;
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory.CustomDialog;
import com.gpl.rpg.AndorsTrail.view.ItemContainerAdapter;
public final class Dialogs {
private static void showDialogAndPause(CustomDialog d, final ControllerContext context) {
showDialogAndPause(d, context, null);
}
private static void showDialogAndPause(CustomDialog d, final ControllerContext context, final OnDismissListener onDismiss) {
context.gameRoundController.pause();
CustomDialogFactory.setDismissListener(d, new OnDismissListener() {
@Override
public void onDismiss(DialogInterface arg0) {
if (onDismiss != null) onDismiss.onDismiss(arg0);
context.gameRoundController.resume();
}
});
CustomDialogFactory.show(d);
}
public static void showKeyArea(final MainActivity currentActivity, final ControllerContext context, String phraseID) {
showConversation(currentActivity, context, phraseID, null);
}
public static void showMapSign(final MainActivity currentActivity, final ControllerContext context, String phraseID) {
showConversation(currentActivity, context, phraseID, null);
}
public static void showMapScriptMessage(final MainActivity currentActivity, final ControllerContext context, String phraseID) {
showConversation(currentActivity, context, phraseID, null, false);
}
public static void showConversation(final MainActivity currentActivity, final ControllerContext context, final String phraseID, final Monster npc) {
showConversation(currentActivity, context, phraseID, npc, true);
}
private static void showConversation(final MainActivity currentActivity, final ControllerContext context, final String phraseID, final Monster npc, boolean applyScriptEffectsForFirstPhrase) {
context.gameRoundController.pause();
Intent intent = new Intent(currentActivity, ConversationActivity.class);
intent.setData(Uri.parse("content://com.gpl.rpg.AndorsTrail/conversation/" + phraseID));
intent.putExtra("applyScriptEffectsForFirstPhrase", applyScriptEffectsForFirstPhrase);
addMonsterIdentifiers(intent, npc);
currentActivity.startActivityForResult(intent, MainActivity.INTENTREQUEST_CONVERSATION);
}
public static void addMonsterIdentifiers(Intent intent, Monster monster) {
if (monster == null) return;
intent.putExtra("x", monster.position.x);
intent.putExtra("y", monster.position.y);
}
public static void addMonsterIdentifiers(Bundle bundle, Monster monster) {
if (monster == null) return;
bundle.putInt("x", monster.position.x);
bundle.putInt("y", monster.position.y);
}
public static Monster getMonsterFromIntent(Intent intent, final WorldContext world) {
return getMonsterFromBundle(intent.getExtras(), world);
}
public static Monster getMonsterFromBundle(Bundle params, final WorldContext world) {
if (params == null) return null;
if (!params.containsKey("x")) return null;
int x = params.getInt("x");
int y = params.getInt("y");
return world.model.currentMaps.map.getMonsterAt(x, y);
}
public static void showMonsterEncounter(final MainActivity currentActivity, final ControllerContext context, final Monster monster) {
context.gameRoundController.pause();
Intent intent = new Intent(currentActivity, MonsterEncounterActivity.class);
intent.setData(Uri.parse("content://com.gpl.rpg.AndorsTrail/monsterencounter"));
addMonsterIdentifiers(intent, monster);
currentActivity.startActivityForResult(intent, MainActivity.INTENTREQUEST_MONSTERENCOUNTER);
}
public static void showMonsterInfo(final Context context, final Monster monster) {
Intent intent = new Intent(context, MonsterInfoActivity.class);
intent.setData(Uri.parse("content://com.gpl.rpg.AndorsTrail/monsterinfo"));
addMonsterIdentifiers(intent, monster);
context.startActivity(intent);
}
public static String getGroundLootFoundMessage(final Context ctx, final Loot loot) {
StringBuilder sb = new StringBuilder(60);
if (!loot.items.isEmpty()) {
sb.append(ctx.getString(R.string.dialog_groundloot_message));
}
appendGoldPickedUpMessage(ctx, loot, sb);
return sb.toString();
}
public static String getGroundLootPickedUpMessage(final Context ctx, final Loot loot) {
StringBuilder sb = new StringBuilder(60);
appendLootPickedUpMessage(ctx, loot, sb);
return sb.toString();
}
public static String getMonsterLootFoundMessage(final Context ctx, final Loot combinedLoot, final int exp) {
StringBuilder sb = new StringBuilder(60);
appendMonsterEncounterSurvivedMessage(ctx, sb, exp);
appendGoldPickedUpMessage(ctx, combinedLoot, sb);
return sb.toString();
}
public static String getMonsterLootPickedUpMessage(final Context ctx, final Loot combinedLoot, final int exp) {
StringBuilder sb = new StringBuilder(60);
appendMonsterEncounterSurvivedMessage(ctx, sb, exp);
appendLootPickedUpMessage(ctx, combinedLoot, sb);
return sb.toString();
}
private static void appendMonsterEncounterSurvivedMessage(final Context ctx, final StringBuilder sb, final int exp) {
sb.append(ctx.getString(R.string.dialog_monsterloot_message));
if (exp > 0) {
sb.append(' ');
sb.append(ctx.getString(R.string.dialog_monsterloot_gainedexp, exp));
}
}
private static void appendGoldPickedUpMessage(final Context ctx, final Loot loot, final StringBuilder sb) {
if (loot.gold > 0) {
sb.append(' ');
sb.append(ctx.getString(R.string.dialog_loot_foundgold, loot.gold));
}
}
private static void appendLootPickedUpMessage(final Context ctx, final Loot loot, final StringBuilder sb) {
appendGoldPickedUpMessage(ctx, loot, sb);
int numItems = loot.items.countItems();
if (numItems == 1) {
sb.append(' ');
sb.append(ctx.getString(R.string.dialog_loot_pickedupitem));
} else if (numItems > 1){
sb.append(' ');
sb.append(ctx.getString(R.string.dialog_loot_pickedupitems, numItems));
}
}
public static void showMonsterLoot(final MainActivity mainActivity, final ControllerContext controllers, final WorldContext world, final Collection<Loot> lootBags, final Loot combinedLoot, final String msg) {
// CombatController will do killedMonsterBags.clear() after this method has been called,
// so we need to keep the list of objects. Therefore, we create a shallow copy of the list of bags.
ArrayList<Loot> bags = new ArrayList<Loot>(lootBags);
showLoot(mainActivity, controllers, world, combinedLoot, bags, R.string.dialog_monsterloot_title, msg);
}
public static void showGroundLoot(final MainActivity mainActivity, final ControllerContext controllers, final WorldContext world, final Loot loot, final String msg) {
showLoot(mainActivity, controllers, world, loot, Collections.singletonList(loot), R.string.dialog_groundloot_title, msg);
}
private static void showLoot(final MainActivity mainActivity, final ControllerContext controllers, final WorldContext world, final Loot combinedLoot, final Iterable<Loot> lootBags, final int title, final String msg) {
final ListView itemList = new ListView(mainActivity);
itemList.setBackgroundResource(android.R.color.transparent);
itemList.setLayoutParams(new ListView.LayoutParams(ListView.LayoutParams.MATCH_PARENT, ListView.LayoutParams.WRAP_CONTENT));
// itemList.setPadding(20, 0, 20, 20);
itemList.setAdapter(new ItemContainerAdapter(mainActivity, world.tileManager, combinedLoot.items, world.model.player));
final CustomDialog d = CustomDialogFactory.createDialog(mainActivity,
mainActivity.getResources().getString(title),
mainActivity.getResources().getDrawable(R.drawable.ui_icon_equipment),
msg,
combinedLoot.items.isEmpty() ? null : itemList,
true,
false);
itemList.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
final String itemTypeID = ((ItemContainerAdapter) parent.getAdapter()).getItem(position).itemType.id;
boolean removeFromCombinedLoot = true;
for (Loot l : lootBags) {
if (l == combinedLoot) removeFromCombinedLoot = false;
if (l.items.removeItem(itemTypeID)) {
controllers.itemController.removeLootBagIfEmpty(l);
break;
}
}
if (removeFromCombinedLoot) {
combinedLoot.items.removeItem(itemTypeID);
}
if (((ItemContainerAdapter) parent.getAdapter()).isEmpty()) {
ViewGroup vg = (ViewGroup) d.findViewById(R.id.dialog_content_container);
vg.setVisibility(View.GONE);
}
ItemType type = world.itemTypes.getItemType(itemTypeID);
world.model.player.inventory.addItem(type);
((ItemContainerAdapter) itemList.getAdapter()).notifyDataSetChanged();
}
});
if (!itemList.getAdapter().isEmpty()) {
CustomDialogFactory.addButton(d, R.string.dialog_loot_pickall, new View.OnClickListener() {
@Override
public void onClick(View v) {
controllers.itemController.pickupAll(lootBags);
}
});
}
CustomDialogFactory.addDismissButton(d, R.string.dialog_close);
showDialogAndPause(d, controllers, new OnDismissListener() {
@Override
public void onDismiss(DialogInterface arg0) {
controllers.itemController.removeLootBagIfEmpty(lootBags);
}
});
}
public static void showHeroDied(final MainActivity mainActivity, final ControllerContext controllers) {
final CustomDialog d = CustomDialogFactory.createDialog(mainActivity,
mainActivity.getResources().getString(R.string.dialog_game_over_title),
mainActivity.getResources().getDrawable(R.drawable.ui_icon_combat),
mainActivity.getResources().getString(R.string.dialog_game_over_text),
null,
true,
false);
CustomDialogFactory.addDismissButton(d, android.R.string.ok);
showDialogAndPause(d, controllers, new OnDismissListener() {
@Override
public void onDismiss(DialogInterface arg0) {
mainActivity.finish();
}
});
}
public static Intent getIntentForItemInfo(final Context ctx, String itemTypeID, ItemInfoActivity.ItemInfoAction actionType, String buttonText, boolean buttonEnabled, Inventory.WearSlot inventorySlot) {
Intent intent = new Intent(ctx, ItemInfoActivity.class);
intent.putExtra("buttonText", buttonText);
intent.putExtra("buttonEnabled", buttonEnabled);
intent.putExtra("moreActions", (actionType == ItemInfoActivity.ItemInfoAction.equip || actionType == ItemInfoActivity.ItemInfoAction.use || actionType == ItemInfoActivity.ItemInfoAction.none));
intent.putExtra("itemTypeID", itemTypeID);
intent.putExtra("actionType", actionType.name());
if (inventorySlot != null) intent.putExtra("inventorySlot", inventorySlot.name());
intent.setData(Uri.parse("content://com.gpl.rpg.AndorsTrail/iteminfo/" + itemTypeID));
return intent;
}
public static Intent getIntentForLevelUp(final Context ctx) {
Intent intent = new Intent(ctx, LevelUpActivity.class);
intent.setData(Uri.parse("content://com.gpl.rpg.AndorsTrail/levelup"));
return intent;
}
public static void showConfirmRest(final Activity currentActivity, final ControllerContext controllerContext, final MapObject area) {
final CustomDialog d = CustomDialogFactory.createDialog(currentActivity,
currentActivity.getResources().getString(R.string.dialog_rest_title),
null,
currentActivity.getResources().getString(R.string.dialog_rest_confirm_message),
null,
true);
CustomDialogFactory.addButton(d, android.R.string.yes, new View.OnClickListener() {
@Override
public void onClick(View v) {
controllerContext.mapController.rest(area);
}
});
CustomDialogFactory.addDismissButton(d, android.R.string.no);
showDialogAndPause(d, controllerContext);
}
public static void showRested(final Activity currentActivity, final ControllerContext controllerContext) {
// Dialog d = new AlertDialog.Builder(new ContextThemeWrapper(currentActivity, R.style.AndorsTrailStyle))
// .setTitle(R.string.dialog_rest_title)
// .setMessage(R.string.dialog_rest_message)
// .setNeutralButton(android.R.string.ok, null)
// .create();
final CustomDialog d = CustomDialogFactory.createDialog(currentActivity,
currentActivity.getResources().getString(R.string.dialog_rest_title),
null,
currentActivity.getResources().getString(R.string.dialog_rest_message),
null,
true);
CustomDialogFactory.addDismissButton(d, android.R.string.ok);
showDialogAndPause(d, controllerContext);
}
public static void showNewVersion(final Activity currentActivity, final OnDismissListener onDismiss) {
// new AlertDialog.Builder(new ContextThemeWrapper(currentActivity, R.style.AndorsTrailStyle))
// .setTitle(R.string.dialog_newversion_title)
// .setMessage(R.string.dialog_newversion_message)
// .setNeutralButton(android.R.string.ok, null)
// .show();
String text = currentActivity.getResources().getString(R.string.dialog_newversion_message);
if (!hasPermissions(currentActivity) && Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
text += currentActivity.getResources().getString(R.string.dialog_newversion_permission_information);
}
final CustomDialog d = CustomDialogFactory.createDialog(currentActivity,
currentActivity.getResources().getString(R.string.dialog_newversion_title),
null,
text,
null,
true);
CustomDialogFactory.addDismissButton(d, android.R.string.ok);
CustomDialogFactory.setDismissListener(d, new OnDismissListener() {
@Override
public void onDismiss(DialogInterface arg0) {
if (onDismiss != null) onDismiss.onDismiss(arg0);
}
});
CustomDialogFactory.show(d);
}
@TargetApi(23)
private static boolean hasPermissions(final Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (activity.getApplicationContext().checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
|| activity.getApplicationContext().checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
public static boolean showSave(final Activity mainActivity, final ControllerContext controllerContext, final WorldContext world) {
if (world.model.uiSelections.isInCombat) {
Toast.makeText(mainActivity, R.string.menu_save_saving_not_allowed_in_combat, Toast.LENGTH_SHORT).show();
return false;
}
if (!world.model.statistics.hasUnlimitedSaves()) {
final CustomDialog d = CustomDialogFactory.createDialog(mainActivity,
mainActivity.getResources().getString(R.string.menu_save_switch_character_title),
null,
mainActivity.getResources().getString(R.string.menu_save_switch_character),
null,
true);
CustomDialogFactory.addButton(d, android.R.string.ok, new View.OnClickListener() {
@Override
public void onClick(View v) {
controllerContext.gameRoundController.pause();
Intent intent = new Intent(mainActivity, LoadSaveActivity.class);
intent.setData(Uri.parse("content://com.gpl.rpg.AndorsTrail/save"));
mainActivity.startActivityForResult(intent, MainActivity.INTENTREQUEST_SAVEGAME);
}
});
CustomDialogFactory.addDismissButton(d, android.R.string.cancel);
CustomDialogFactory.show(d);
return false;
} else {
controllerContext.gameRoundController.pause();
Intent intent = new Intent(mainActivity, LoadSaveActivity.class);
intent.setData(Uri.parse("content://com.gpl.rpg.AndorsTrail/save"));
mainActivity.startActivityForResult(intent, MainActivity.INTENTREQUEST_SAVEGAME);
return true;
}
}
public static void showLoad(final Activity currentActivity) {
Intent intent = new Intent(currentActivity, LoadSaveActivity.class);
intent.setData(Uri.parse("content://com.gpl.rpg.AndorsTrail/load"));
currentActivity.startActivityForResult(intent, StartScreenActivity_MainMenu.INTENTREQUEST_LOADGAME);
}
public static void showLoad(final Fragment currentFragment) {
Intent intent = new Intent(currentFragment.getActivity(), LoadSaveActivity.class);
intent.setData(Uri.parse("content://com.gpl.rpg.AndorsTrail/load"));
currentFragment.startActivityForResult(intent, StartScreenActivity_MainMenu.INTENTREQUEST_LOADGAME);
}
public static void showActorConditionInfo(final Context context, ActorConditionType conditionType) {
Intent intent = new Intent(context, ActorConditionInfoActivity.class);
intent.setData(Uri.parse("content://com.gpl.rpg.AndorsTrail/actorconditioninfo/" + conditionType.conditionTypeID));
context.startActivity(intent);
}
public static Intent getIntentForBulkBuyingInterface(final Context ctx, String itemTypeID, int totalAvailableAmount) {
return getIntentForBulkSelectionInterface(ctx, itemTypeID, totalAvailableAmount, BulkSelectionInterface.BulkInterfaceType.buy);
}
public static Intent getIntentForBulkSellingInterface(final Context ctx, String itemTypeID, int totalAvailableAmount) {
return getIntentForBulkSelectionInterface(ctx, itemTypeID, totalAvailableAmount, BulkSelectionInterface.BulkInterfaceType.sell);
}
public static Intent getIntentForBulkDroppingInterface(final Context ctx, String itemTypeID, int totalAvailableAmount) {
return getIntentForBulkSelectionInterface(ctx, itemTypeID, totalAvailableAmount, BulkSelectionInterface.BulkInterfaceType.drop);
}
private static Intent getIntentForBulkSelectionInterface(final Context ctx, String itemTypeID, int totalAvailableAmount, BulkSelectionInterface.BulkInterfaceType interfaceType) {
Intent intent = new Intent(ctx, BulkSelectionInterface.class);
intent.putExtra("itemTypeID", itemTypeID);
intent.putExtra("totalAvailableAmount", totalAvailableAmount);
intent.putExtra("interfaceType", interfaceType.name());
intent.setData(Uri.parse("content://com.gpl.rpg.AndorsTrail/bulkselection/" + itemTypeID));
return intent;
}
public static Intent getIntentForSkillInfo(final Context ctx, SkillCollection.SkillID skillID) {
Intent intent = new Intent(ctx, SkillInfoActivity.class);
intent.putExtra("skillID", skillID.name());
intent.setData(Uri.parse("content://com.gpl.rpg.AndorsTrail/showskillinfo/" + skillID));
return intent;
}
public static void showCombatLog(final Context context, final ControllerContext controllerContext, final WorldContext world) {
String[] combatLogMessages = world.model.combatLog.getAllMessages();
View view = null;
ListView itemList = null;
itemList = new ListView(context);
itemList.setLayoutParams(new ListView.LayoutParams(ListView.LayoutParams.MATCH_PARENT, ListView.LayoutParams.WRAP_CONTENT));
itemList.setStackFromBottom(true);
itemList.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
itemList.setChoiceMode(ListView.CHOICE_MODE_NONE);
itemList.setBackgroundColor(ThemeHelper.getThemeColor(context, R.attr.ui_theme_stdframe_bg_color));
if (combatLogMessages.length <= 0) {
combatLogMessages = new String[] {context.getResources().getString(R.string.combat_log_noentries)};
}
itemList.setAdapter(new ArrayAdapter<String>(context, R.layout.combatlog_row, android.R.id.text1, combatLogMessages));
view = itemList;
final CustomDialog d = CustomDialogFactory.createDialog(context,
context.getResources().getString(R.string.combat_log_title),
context.getResources().getDrawable(R.drawable.ui_icon_combat),
null,
view,
true);
CustomDialogFactory.addDismissButton(d, R.string.dialog_close);
showDialogAndPause(d, controllerContext);
}
}

View File

@@ -1,6 +1,5 @@
package com.gpl.rpg.AndorsTrail.activity;
import android.app.Activity;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;

View File

@@ -1,6 +1,5 @@
package com.gpl.rpg.AndorsTrail.activity;
import android.app.Activity;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.View;

View File

@@ -1,12 +1,9 @@
package com.gpl.rpg.AndorsTrail.activity;
import android.app.Activity;
import android.content.res.Resources;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import androidx.fragment.app.FragmentActivity;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
public abstract class AndorsTrailBaseFragmentActivity extends FragmentActivity {
@Override

View File

@@ -1,6 +1,5 @@
package com.gpl.rpg.AndorsTrail.activity;
import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.content.res.Resources;
@@ -24,6 +23,7 @@ import com.gpl.rpg.AndorsTrail.controller.ItemController;
import com.gpl.rpg.AndorsTrail.model.item.ItemType;
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory;
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory.CustomDialog;
/**
* @author ejwessel
@@ -207,7 +207,7 @@ public final class BulkSelectionInterface extends AndorsTrailBaseActivity implem
// })
// .setNegativeButton(android.R.string.no, null)
// .show();
final Dialog d = CustomDialogFactory.createDialog(v.getContext(),
final CustomDialog d = CustomDialogFactory.createDialog(v.getContext(),
v.getContext().getResources().getString(R.string.bulkselection_sell_confirmation_title),
v.getContext().getResources().getDrawable(android.R.drawable.ic_dialog_info),
message,

View File

@@ -2,7 +2,6 @@ package com.gpl.rpg.AndorsTrail.activity;
import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;

View File

@@ -0,0 +1,390 @@
package com.gpl.rpg.AndorsTrail.activity;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.context.ControllerContext;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.controller.Constants;
import com.gpl.rpg.AndorsTrail.model.item.ItemType;
import com.gpl.rpg.AndorsTrail.model.map.MapObject;
import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap;
import com.gpl.rpg.AndorsTrail.view.MainView;
import android.content.Context;
import android.content.res.Resources;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.Toast;
public final class DebugInterface {
private final ControllerContext controllerContext;
private final MainActivity mainActivity;
private final Resources res;
private final WorldContext world;
private DebugButton[] buttons;
private List<DebugButton> tpButtons = new ArrayList<DebugButton>();
private List<DebugButton> tpButtons2 = new ArrayList<DebugButton>();
public DebugInterface(ControllerContext controllers, WorldContext world, MainActivity mainActivity) {
this.controllerContext = controllers;
this.world = world;
this.res = mainActivity.getResources();
this.mainActivity = mainActivity;
}
public void addDebugButtons() {
if (!AndorsTrailApplication.DEVELOPMENT_DEBUGBUTTONS) return;
List<DebugButton> buttonList = new ArrayList<DebugButton>();
buttonList.addAll(Arrays.asList(new DebugButton[] {
new DebugButton("dbg", new OnClickListener() {
boolean hidden = false;
@Override
public void onClick(View arg0) {
hidden = !hidden;
for (int i = 1; i < buttons.length; i++) {
buttons[i].b.setVisibility(hidden ? View.GONE : View.VISIBLE);
}
for (DebugButton b : tpButtons) {
b.b.setVisibility(View.GONE);
}
for (DebugButton b : tpButtons2) {
b.b.setVisibility(View.GONE);
}
}
})
,new DebugButton("teleport", new OnClickListener() {
public void onClick(View arg0) {
for (int i = 0; i < buttons.length; i++) {
buttons[i].b.setVisibility(View.GONE);
}
for (DebugButton tpButton : tpButtons) {
tpButton.b.setVisibility(View.VISIBLE);
}
}
})
,new DebugButton("dmg", new OnClickListener() {
@Override
public void onClick(View arg0) {
world.model.player.damagePotential.set(500, 500);
world.model.player.attackChance = 500;
world.model.player.attackCost = 1;
showToast(mainActivity, "DEBUG: damagePotential=500, chance=500%, cost=1", Toast.LENGTH_SHORT);
}
})
/*,new DebugButton("dmg=1", new OnClickListener() {
@Override
public void onClick(View arg0) {
world.model.player.damagePotential.set(1, 1);
showToast(mainActivity, "DEBUG: damagePotential=1", Toast.LENGTH_SHORT);
}
})*/
,new DebugButton("itm", new OnClickListener() {
@Override
public void onClick(View arg0) {
for (ItemType item : world.itemTypes.UNITTEST_getAllItemTypes().values()) {
world.model.player.inventory.addItem(item, 10);
}
world.model.player.inventory.gold += 50000;
showToast(mainActivity, "DEBUG: added items", Toast.LENGTH_SHORT);
}
})
,new DebugButton("xp", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.actorStatsController.addExperience(10000);
showToast(mainActivity, "DEBUG: given 10000 exp", Toast.LENGTH_SHORT);
}
})
,new DebugButton("rst", new OnClickListener() {
@Override
public void onClick(View arg0) {
for(PredefinedMap map : world.maps.getAllMaps()) {
map.resetTemporaryData();
}
showToast(mainActivity, "DEBUG: maps respawned", Toast.LENGTH_SHORT);
}
})
,new DebugButton("hp", new OnClickListener() {
@Override
public void onClick(View arg0) {
world.model.player.baseTraits.maxHP = 500;
world.model.player.health.max = world.model.player.baseTraits.maxHP;
controllerContext.actorStatsController.setActorMaxHealth(world.model.player);
world.model.player.conditions.clear();
showToast(mainActivity, "DEBUG: hp set to max", Toast.LENGTH_SHORT);
}
})
,new DebugButton("skl", new OnClickListener() {
@Override
public void onClick(View arg0) {
world.model.player.availableSkillIncreases += 10;
showToast(mainActivity, "DEBUG: 10 skill points", Toast.LENGTH_SHORT);
}
})
,new DebugButton("spd", new OnClickListener() {
boolean fast = Constants.MINIMUM_INPUT_INTERVAL == Constants.MINIMUM_INPUT_INTERVAL_FAST;
@Override
public void onClick(View arg0) {
fast = !fast;
if (fast) {
Constants.MINIMUM_INPUT_INTERVAL = Constants.MINIMUM_INPUT_INTERVAL_FAST;
} else {
Constants.MINIMUM_INPUT_INTERVAL = Constants.MINIMUM_INPUT_INTERVAL_STD;
}
MainView.SCROLL_DURATION = Constants.MINIMUM_INPUT_INTERVAL;
AndorsTrailApplication.getApplicationFromActivity(mainActivity).getControllerContext().movementController.resetMovementHandler();
}
})
,new DebugButton("map", new OnClickListener() {
@Override
public void onClick(View arg0) {
showToast(mainActivity, "DEBUG: map=" + world.model.currentMaps.map.name , Toast.LENGTH_SHORT);
}
})
}));
tpButtons.addAll(Arrays.asList(new DebugButton[] {
new DebugButton("teleport", new OnClickListener() {
@Override
public void onClick(View arg0) {
for (DebugButton tpButton : tpButtons2) {
tpButton.b.setVisibility(View.VISIBLE);
}
for (DebugButton tpButton : tpButtons) {
tpButton.b.setVisibility(View.GONE);
}
}
})
,new DebugButton("cg", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "crossglen", "hall", 0, 0);
}
})
,new DebugButton("vg", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "vilegard_s", "tavern", 0, 0);
}
})
,new DebugButton("cr", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "houseatcrossroads4", "down", 0, 0);
}
})
,new DebugButton("lf", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "loneford9", "south", 0, 0);
}
})
,new DebugButton("fh", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "fallhaven_ne", "clothes", 0, 0);
}
})
,new DebugButton("prm", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "blackwater_mountain29", "south", 0, 0);
}
})
,new DebugButton("bwm", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "blackwater_mountain43", "south", 0, 0);
}
})
,new DebugButton("rmg", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "remgard0", "east", 0, 0);
}
})
,new DebugButton("chr", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "waytolostmine2", "minerhouse4", 0, 0);
}
})
,new DebugButton("ldr", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "lodarhouse0", "lodarhouse", 0, 0);
}
})
,new DebugButton("sf", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "wild20", "south2", 0, 0);
}
})
,new DebugButton("gm", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "guynmart_wood_1", "farmhouse", 0, 0);
}
})
}));
buttonList.addAll(tpButtons);
tpButtons2.addAll(Arrays.asList(new DebugButton[] {
new DebugButton("teleport", new OnClickListener() {
@Override
public void onClick(View arg0) {
for (int i = 0; i < buttons.length; i++) {
buttons[i].b.setVisibility(View.VISIBLE);
}
for (DebugButton tpButton : tpButtons) {
tpButton.b.setVisibility(View.GONE);
}
for (DebugButton tpButton : tpButtons2) {
tpButton.b.setVisibility(View.GONE);
}
}
})
,new DebugButton("brv", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "brimhaven4", "south2", 0, 0);
}
})
,new DebugButton("aru", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "mountainlake5", "north", 0, 0);
}
})
,new DebugButton("ws", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "woodsettlement0", "east", 0, 0);
}
})
,new DebugButton("sul", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "sullengard2", "south", 0, 0);
}
})
,new DebugButton("gal", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "galmore_19", "south", 0, 0);
}
})
,new DebugButton("apl", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "sullengard_apple_farm_east", "house", 0, 0);
}
})
,new DebugButton("wch", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "lake_shore_road_0", "west", 0, 0);
}
})
,new DebugButton("la1", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "laerothisland1", "west", 0, 0);
}
})
,new DebugButton("la2", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "island3", "cave", 0, 0);
}
})
,new DebugButton("#1", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "waterway11_east", "west", 0, 0);
}
})
,new DebugButton("#2", new OnClickListener() {
@Override
public void onClick(View arg0) {
controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, "mountainlake8", "north", 0, 0);
}
})
}));
buttonList.addAll(tpButtons2);
buttons = buttonList.toArray(new DebugButton[buttonList.size()]);
addDebugButtons(buttons);
for (DebugButton b : tpButtons) {
b.b.setVisibility(View.GONE);
}
for (DebugButton b : tpButtons2) {
b.b.setVisibility(View.GONE);
}
}
private void showToast(Context context, String msg, int duration) {
Toast.makeText(context, msg, duration).show();
}
private static class DebugButton {
public final String text;
public final OnClickListener listener;
public Button b = null;
public DebugButton(String text, OnClickListener listener) {
this.text = text;
this.listener = listener;
}
public void makeButton(Context c, int id) {
b = new Button(c);
b.setText(text);
b.setTextSize(10);//res.getDimension(R.dimen.actionbar_text));
b.setId(id);
b.setOnClickListener(listener);
}
}
private void addDebugButton(DebugButton button, int id, RelativeLayout layout) {
if (!AndorsTrailApplication.DEVELOPMENT_DEBUGBUTTONS) return;
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, res.getDimensionPixelSize(R.dimen.smalltext_buttonheight));
if (id == 1)
lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
else
lp.addRule(RelativeLayout.RIGHT_OF, id - 1);
lp.addRule(RelativeLayout.ABOVE, R.id.main_statusview);
button.makeButton(mainActivity, id);
button.b.setLayoutParams(lp);
layout.addView(button.b);
}
private void addDebugButtons(DebugButton[] buttons) {
if (!AndorsTrailApplication.DEVELOPMENT_DEBUGBUTTONS) return;
if (buttons == null || buttons.length <= 0) return;
RelativeLayout layout = (RelativeLayout) mainActivity.findViewById(R.id.main_container);
int id = 1;
for (DebugButton b : buttons) {
addDebugButton(b, id, layout);
++id;
}
}
}

View File

@@ -1,172 +1,168 @@
package com.gpl.rpg.AndorsTrail.activity;
import java.io.File;
import java.io.FileNotFoundException;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.controller.WorldMapController;
import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap;
import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment;
import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment.WorldMapSegmentMap;
import com.gpl.rpg.AndorsTrail.util.AndroidStorage;
import com.gpl.rpg.AndorsTrail.util.Coord;
import com.gpl.rpg.AndorsTrail.util.L;
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.content.FileProvider;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.Toast;
public final class DisplayWorldMapActivity extends AndorsTrailBaseActivity {
private WorldContext world;
private WebView displayworldmap_webview;
private String worldMapSegmentName;
@Override
public void onCreate(Bundle savedInstanceState) {
setTheme(ThemeHelper.getBaseTheme());
super.onCreate(savedInstanceState);
AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this);
if (!app.isInitialized()) { finish(); return; }
this.world = app.getWorld();
app.setWindowParameters(this);
setContentView(R.layout.displayworldmap);
displayworldmap_webview = (WebView) findViewById(R.id.displayworldmap_webview);
displayworldmap_webview.setBackgroundColor(ThemeHelper.getThemeColor(this, R.attr.ui_theme_displayworldmap_bg_color));
displayworldmap_webview.getSettings().setBuiltInZoomControls(true);
displayworldmap_webview.getSettings().setUseWideViewPort(true);
displayworldmap_webview.setVerticalScrollBarEnabled(true);
displayworldmap_webview.setHorizontalScrollBarEnabled(true);
displayworldmap_webview.getSettings().setAllowFileAccess(true);
enableJavascript();
Button b = (Button) findViewById(R.id.displayworldmap_close);
b.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
DisplayWorldMapActivity.this.finish();
}
});
b = (Button) findViewById(R.id.displayworldmap_recenter);
b.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
recenter();
}
});
worldMapSegmentName = getIntent().getStringExtra("worldMapSegmentName");
}
@SuppressLint("SetJavaScriptEnabled")
public void enableJavascript() {
displayworldmap_webview.getSettings().setJavaScriptEnabled(true);
}
@Override
public void onResume() {
super.onResume();
update();
}
WorldMapSegmentMap map;
Coord offsetWorldmapTo;
@SuppressLint("NewApi")
private void update() {
File worldmap = WorldMapController.getCombinedWorldMapFile(this, worldMapSegmentName);
if (!worldmap.exists()) {
Toast.makeText(this, getResources().getString(R.string.menu_button_worldmap_failed), Toast.LENGTH_LONG).show();
this.finish();
}
WorldMapSegment segment = world.maps.worldMapSegments.get(worldMapSegmentName);
map = segment.maps.get(world.model.currentMaps.map.name);
if (map == null) {
this.finish();
return;
}
offsetWorldmapTo = new Coord(999999, 999999);
for (WorldMapSegmentMap map : segment.maps.values()) {
PredefinedMap predefinedMap = world.maps.findPredefinedMap(map.mapName);
if (predefinedMap == null) continue;
if (!predefinedMap.visited) continue;
if (!WorldMapController.fileForMapExists(this, predefinedMap)) continue;
offsetWorldmapTo.x = Math.min(offsetWorldmapTo.x, map.worldPosition.x);
offsetWorldmapTo.y = Math.min(offsetWorldmapTo.y, map.worldPosition.y);
}
String url = AndroidStorage.getUrlForFile(this, worldmap) + '?'
+ (world.model.player.position.x + map.worldPosition.x) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE
+ ','
+ (world.model.player.position.y + map.worldPosition.y-1) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE;
L.log("Showing " + url);
displayworldmap_webview.loadUrl(url);
displayworldmap_webview.setBackgroundColor(ThemeHelper.getThemeColor(this, R.attr.ui_theme_displayworldmap_bg_color));
displayworldmap_webview.setWebViewClient(new WebViewClient() {
@SuppressLint("NewApi")
@Override
public void onPageFinished(WebView view, String url)
{
recenter();
}
});
}
private void recenter() {
displayworldmap_webview.postDelayed(new Runnable() {
@Override
public void run() {
if (map != null) {
//Local map to global worldmap
int x = world.model.player.position.x + map.worldPosition.x - offsetWorldmapTo.x;
//Tile coord to pixel coord
x *= WorldMapController.WORLDMAP_DISPLAY_TILESIZE;
x += WorldMapController.WORLDMAP_DISPLAY_TILESIZE/2;
//Zoom level
x = (int)(x * displayworldmap_webview.getScale());
//Center
x -= displayworldmap_webview.getWidth() / 2;
//Local map to global worldmap
int y = world.model.player.position.y + map.worldPosition.y - offsetWorldmapTo.y;
//Tile coord to pixel coord
y *= WorldMapController.WORLDMAP_DISPLAY_TILESIZE;
y += WorldMapController.WORLDMAP_DISPLAY_TILESIZE/2;
//Zoom level
y = (int)(y * displayworldmap_webview.getScale());
//Center
y -= displayworldmap_webview.getHeight() / 2;
displayworldmap_webview.scrollTo(x, y);
}
}
}, 100);
}
@Override
public void finish() {
ViewGroup view = (ViewGroup) getWindow().getDecorView();
view.removeAllViews();
super.finish();
}
}
package com.gpl.rpg.AndorsTrail.activity;
import java.io.File;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.controller.WorldMapController;
import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap;
import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment;
import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment.WorldMapSegmentMap;
import com.gpl.rpg.AndorsTrail.util.AndroidStorage;
import com.gpl.rpg.AndorsTrail.util.Coord;
import com.gpl.rpg.AndorsTrail.util.L;
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.Toast;
public final class DisplayWorldMapActivity extends AndorsTrailBaseActivity {
private WorldContext world;
private WebView displayworldmap_webview;
private String worldMapSegmentName;
@Override
public void onCreate(Bundle savedInstanceState) {
setTheme(ThemeHelper.getBaseTheme());
super.onCreate(savedInstanceState);
AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this);
if (!app.isInitialized()) { finish(); return; }
this.world = app.getWorld();
app.setWindowParameters(this);
setContentView(R.layout.displayworldmap);
displayworldmap_webview = (WebView) findViewById(R.id.displayworldmap_webview);
displayworldmap_webview.setBackgroundColor(ThemeHelper.getThemeColor(this, R.attr.ui_theme_displayworldmap_bg_color));
displayworldmap_webview.getSettings().setBuiltInZoomControls(true);
displayworldmap_webview.getSettings().setUseWideViewPort(true);
displayworldmap_webview.setVerticalScrollBarEnabled(true);
displayworldmap_webview.setHorizontalScrollBarEnabled(true);
displayworldmap_webview.getSettings().setAllowFileAccess(true);
enableJavascript();
Button b = (Button) findViewById(R.id.displayworldmap_close);
b.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
DisplayWorldMapActivity.this.finish();
}
});
b = (Button) findViewById(R.id.displayworldmap_recenter);
b.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
recenter();
}
});
worldMapSegmentName = getIntent().getStringExtra("worldMapSegmentName");
}
@SuppressLint("SetJavaScriptEnabled")
public void enableJavascript() {
displayworldmap_webview.getSettings().setJavaScriptEnabled(true);
}
@Override
public void onResume() {
super.onResume();
update();
}
WorldMapSegmentMap map;
Coord offsetWorldmapTo;
@SuppressLint("NewApi")
private void update() {
File worldmap = WorldMapController.getCombinedWorldMapFile(this, worldMapSegmentName);
if (!worldmap.exists()) {
Toast.makeText(this, getResources().getString(R.string.menu_button_worldmap_failed), Toast.LENGTH_LONG).show();
this.finish();
}
WorldMapSegment segment = world.maps.worldMapSegments.get(worldMapSegmentName);
map = segment.maps.get(world.model.currentMaps.map.name);
if (map == null) {
this.finish();
return;
}
offsetWorldmapTo = new Coord(999999, 999999);
for (WorldMapSegmentMap map : segment.maps.values()) {
PredefinedMap predefinedMap = world.maps.findPredefinedMap(map.mapName);
if (predefinedMap == null) continue;
if (!predefinedMap.visited) continue;
if (!WorldMapController.fileForMapExists(this, predefinedMap)) continue;
offsetWorldmapTo.x = Math.min(offsetWorldmapTo.x, map.worldPosition.x);
offsetWorldmapTo.y = Math.min(offsetWorldmapTo.y, map.worldPosition.y);
}
String url = AndroidStorage.getUrlForFile(this, worldmap) + '?'
+ (world.model.player.position.x + map.worldPosition.x) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE
+ ','
+ (world.model.player.position.y + map.worldPosition.y-1) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE;
L.log("Showing " + url);
displayworldmap_webview.loadUrl(url);
displayworldmap_webview.setBackgroundColor(ThemeHelper.getThemeColor(this, R.attr.ui_theme_displayworldmap_bg_color));
displayworldmap_webview.setWebViewClient(new WebViewClient() {
@SuppressLint("NewApi")
@Override
public void onPageFinished(WebView view, String url)
{
recenter();
}
});
}
private void recenter() {
displayworldmap_webview.postDelayed(new Runnable() {
@Override
public void run() {
if (map != null) {
//Local map to global worldmap
int x = world.model.player.position.x + map.worldPosition.x - offsetWorldmapTo.x;
//Tile coord to pixel coord
x *= WorldMapController.WORLDMAP_DISPLAY_TILESIZE;
x += WorldMapController.WORLDMAP_DISPLAY_TILESIZE/2;
//Zoom level
x = (int)(x * displayworldmap_webview.getScale());
//Center
x -= displayworldmap_webview.getWidth() / 2;
//Local map to global worldmap
int y = world.model.player.position.y + map.worldPosition.y - offsetWorldmapTo.y;
//Tile coord to pixel coord
y *= WorldMapController.WORLDMAP_DISPLAY_TILESIZE;
y += WorldMapController.WORLDMAP_DISPLAY_TILESIZE/2;
//Zoom level
y = (int)(y * displayworldmap_webview.getScale());
//Center
y -= displayworldmap_webview.getHeight() / 2;
displayworldmap_webview.scrollTo(x, y);
}
}
}, 100);
}
@Override
public void finish() {
ViewGroup view = (ViewGroup) getWindow().getDecorView();
view.removeAllViews();
super.finish();
}
}

View File

@@ -1,10 +1,8 @@
package com.gpl.rpg.AndorsTrail.activity;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTabHost;
import androidx.fragment.app.FragmentTabHost;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.ImageView;

View File

@@ -1,139 +1,139 @@
package com.gpl.rpg.AndorsTrail.activity;
import java.util.Collections;
import android.app.Activity;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.model.item.ItemType;
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
import com.gpl.rpg.AndorsTrail.view.ItemEffectsView;
public final class ItemInfoActivity extends AndorsTrailBaseActivity {
public static enum ItemInfoAction {
none, use, equip, unequip, buy, sell
}
public static final int RESULT_MORE_ACTIONS = Activity.RESULT_FIRST_USER;
@Override
public void onCreate(Bundle savedInstanceState) {
setTheme(ThemeHelper.getDialogTheme());
super.onCreate(savedInstanceState);
AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this);
if (!app.isInitialized()) { finish(); return; }
final WorldContext world = app.getWorld();
app.setWindowParameters(this);
final Intent intent = getIntent();
Bundle params = intent.getExtras();
String itemTypeID = params.getString("itemTypeID");
final ItemType itemType = world.itemTypes.getItemType(itemTypeID);
final String buttonText = params.getString("buttonText");
boolean buttonEnabled = params.getBoolean("buttonEnabled");
boolean moreButtonEnabled = params.getBoolean("moreActions");
setContentView(R.layout.iteminfo);
TextView tv = (TextView) findViewById(R.id.iteminfo_title);
tv.setText(itemType.getName(world.model.player));
world.tileManager.setImageViewTileForSingleItemType(getResources(), tv, itemType);
tv = (TextView) findViewById(R.id.iteminfo_description);
String description = itemType.getDescription();
if (description != null) {
tv.setText(description);
tv.setVisibility(View.VISIBLE);
} else {
tv.setVisibility(View.GONE);
}
tv = (TextView) findViewById(R.id.iteminfo_category);
tv.setText(itemType.category.displayName);
((ItemEffectsView) findViewById(R.id.iteminfo_effects)).update(
itemType.effects_equip,
itemType.effects_use == null ? null : Collections.singletonList(itemType.effects_use),
itemType.effects_hit == null ? null : Collections.singletonList(itemType.effects_hit),
itemType.effects_kill == null ? null : Collections.singletonList(itemType.effects_kill),
itemType.effects_hitReceived == null ? null : Collections.singletonList(itemType.effects_hitReceived),
null,
itemType.isWeapon()
);
Button b = (Button) findViewById(R.id.iteminfo_close);
b.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
setResult(RESULT_CANCELED);
ItemInfoActivity.this.finish();
}
});
b = (Button) findViewById(R.id.iteminfo_more);
if (!moreButtonEnabled) {
b.setVisibility(View.GONE);
} else {
b.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Intent result = new Intent();
result.putExtras(intent);
setResult(RESULT_MORE_ACTIONS, intent);
ItemInfoActivity.this.finish();
}
});
}
b = (Button) findViewById(R.id.iteminfo_action);
if (buttonText != null && buttonText.length() > 0) {
b.setVisibility(View.VISIBLE);
b.setEnabled(buttonEnabled);
b.setText(buttonText);
} else {
b.setVisibility(View.GONE);
}
b.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Intent result = new Intent();
result.putExtras(intent);
setResult(RESULT_OK, result);
ItemInfoActivity.this.finish();
}
});
tv = (TextView) findViewById(R.id.iteminfo_displaytype);
if (itemType.isOrdinaryItem()) {
tv.setVisibility(View.GONE);
} else {
tv.setVisibility(View.VISIBLE);
final String diplayType = getDisplayTypeString(getResources(), itemType);
tv.setText(diplayType);
}
}
public static String getDisplayTypeString(Resources res, ItemType itemType) {
switch (itemType.displayType) {
case rare: return res.getString(R.string.iteminfo_displaytypes_rare);
case extraordinary: return res.getString(R.string.iteminfo_displaytypes_extraordinary);
case legendary: return res.getString(R.string.iteminfo_displaytypes_legendary);
case ordinary: return res.getString(R.string.iteminfo_displaytypes_ordinary);
case quest: return res.getString(R.string.iteminfo_displaytypes_quest);
default: return "";
}
}
}
package com.gpl.rpg.AndorsTrail.activity;
import java.util.Collections;
import android.app.Activity;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.model.item.ItemType;
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
import com.gpl.rpg.AndorsTrail.view.ItemEffectsView;
public final class ItemInfoActivity extends AndorsTrailBaseActivity {
public static enum ItemInfoAction {
none, use, equip, unequip, buy, sell
}
public static final int RESULT_MORE_ACTIONS = Activity.RESULT_FIRST_USER;
@Override
public void onCreate(Bundle savedInstanceState) {
setTheme(ThemeHelper.getDialogTheme());
super.onCreate(savedInstanceState);
AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this);
if (!app.isInitialized()) { finish(); return; }
final WorldContext world = app.getWorld();
app.setWindowParameters(this);
final Intent intent = getIntent();
Bundle params = intent.getExtras();
String itemTypeID = params.getString("itemTypeID");
final ItemType itemType = world.itemTypes.getItemType(itemTypeID);
final String buttonText = params.getString("buttonText");
boolean buttonEnabled = params.getBoolean("buttonEnabled");
boolean moreButtonEnabled = params.getBoolean("moreActions");
setContentView(R.layout.iteminfo);
TextView tv = (TextView) findViewById(R.id.iteminfo_title);
tv.setText(itemType.getName(world.model.player));
world.tileManager.setImageViewTileForSingleItemType(getResources(), tv, itemType);
tv = (TextView) findViewById(R.id.iteminfo_description);
String description = itemType.getDescription();
if (description != null) {
tv.setText(description);
tv.setVisibility(View.VISIBLE);
} else {
tv.setVisibility(View.GONE);
}
tv = (TextView) findViewById(R.id.iteminfo_category);
tv.setText(itemType.category.displayName);
((ItemEffectsView) findViewById(R.id.iteminfo_effects)).update(
itemType.effects_equip,
itemType.effects_use == null ? null : Collections.singletonList(itemType.effects_use),
itemType.effects_hit == null ? null : Collections.singletonList(itemType.effects_hit),
itemType.effects_kill == null ? null : Collections.singletonList(itemType.effects_kill),
itemType.effects_hitReceived == null ? null : Collections.singletonList(itemType.effects_hitReceived),
null,
itemType.isWeapon()
);
Button b = (Button) findViewById(R.id.iteminfo_close);
b.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
setResult(RESULT_CANCELED);
ItemInfoActivity.this.finish();
}
});
b = (Button) findViewById(R.id.iteminfo_more);
if (!moreButtonEnabled) {
b.setVisibility(View.GONE);
} else {
b.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Intent result = new Intent();
result.putExtras(intent);
setResult(RESULT_MORE_ACTIONS, intent);
ItemInfoActivity.this.finish();
}
});
}
b = (Button) findViewById(R.id.iteminfo_action);
if (buttonText != null && buttonText.length() > 0) {
b.setVisibility(View.VISIBLE);
b.setEnabled(buttonEnabled);
b.setText(buttonText);
} else {
b.setVisibility(View.GONE);
}
b.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Intent result = new Intent();
result.putExtras(intent);
setResult(RESULT_OK, result);
ItemInfoActivity.this.finish();
}
});
tv = (TextView) findViewById(R.id.iteminfo_displaytype);
if (itemType.isOrdinaryItem()) {
tv.setVisibility(View.GONE);
} else {
tv.setVisibility(View.VISIBLE);
final String diplayType = getDisplayTypeString(getResources(), itemType);
tv.setText(diplayType);
}
}
public static String getDisplayTypeString(Resources res, ItemType itemType) {
switch (itemType.displayType) {
case rare: return res.getString(R.string.iteminfo_displaytypes_rare);
case extraordinary: return res.getString(R.string.iteminfo_displaytypes_extraordinary);
case legendary: return res.getString(R.string.iteminfo_displaytypes_legendary);
case ordinary: return res.getString(R.string.iteminfo_displaytypes_ordinary);
case quest: return res.getString(R.string.iteminfo_displaytypes_quest);
default: return "";
}
}
}

View File

@@ -1,6 +1,5 @@
package com.gpl.rpg.AndorsTrail.activity;
import android.app.Activity;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.View;

View File

@@ -0,0 +1,876 @@
package com.gpl.rpg.AndorsTrail.activity;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import android.Manifest;
import android.app.Activity;
import android.content.ClipData;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import androidx.annotation.RequiresApi;
import androidx.documentfile.provider.DocumentFile;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.AndorsTrailPreferences;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.controller.Constants;
import com.gpl.rpg.AndorsTrail.model.ModelContainer;
import com.gpl.rpg.AndorsTrail.resource.tiles.TileManager;
import com.gpl.rpg.AndorsTrail.savegames.Savegames;
import com.gpl.rpg.AndorsTrail.savegames.Savegames.FileHeader;
import com.gpl.rpg.AndorsTrail.util.AndroidStorage;
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory;
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory.CustomDialog;
public final class LoadSaveActivity extends AndorsTrailBaseActivity implements OnClickListener {
private boolean isLoading = true;
//region special slot numbers
private static final int SLOT_NUMBER_CREATE_NEW_SLOT = -1;
public static final int SLOT_NUMBER_EXPORT_SAVEGAMES = -2;
public static final int SLOT_NUMBER_IMPORT_SAVEGAMES = -3;
public static final int SLOT_NUMBER_IMPORT_WORLDMAP = -4;
private static final int SLOT_NUMBER_FIRST_SLOT = 1;
//endregion
private ModelContainer model;
private TileManager tileManager;
private AndorsTrailPreferences preferences;
@Override
public void onCreate(Bundle savedInstanceState) {
setTheme(ThemeHelper.getDialogTheme());
super.onCreate(savedInstanceState);
final AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this);
app.setWindowParameters(this);
this.model = app.getWorld().model;
this.preferences = app.getPreferences();
this.tileManager = app.getWorld().tileManager;
String loadsave = getIntent().getData().getLastPathSegment();
isLoading = (loadsave.equalsIgnoreCase("load"));
setContentView(R.layout.loadsave);
TextView tv = (TextView) findViewById(R.id.loadsave_title);
if (isLoading) {
tv.setCompoundDrawablesWithIntrinsicBounds(android.R.drawable.ic_menu_search, 0, 0, 0);
tv.setText(R.string.loadsave_title_load);
} else {
tv.setCompoundDrawablesWithIntrinsicBounds(android.R.drawable.ic_menu_save, 0, 0, 0);
tv.setText(R.string.loadsave_title_save);
}
ViewGroup slotList = (ViewGroup) findViewById(R.id.loadsave_slot_list);
Button slotTemplateButton = (Button) findViewById(R.id.loadsave_slot_n);
LayoutParams params = slotTemplateButton.getLayoutParams();
slotList.removeView(slotTemplateButton);
ViewGroup newSlotContainer = (ViewGroup) findViewById(R.id.loadsave_save_to_new_slot_container);
Button createNewSlot = (Button) findViewById(R.id.loadsave_save_to_new_slot);
Button exportSaves = (Button) findViewById(R.id.loadsave_export_save);
Button importSaves = (Button) findViewById(R.id.loadsave_import_save);
Button importWorldmap = (Button) findViewById(R.id.loadsave_import_worldmap);
exportSaves.setTag(SLOT_NUMBER_EXPORT_SAVEGAMES);
importSaves.setTag(SLOT_NUMBER_IMPORT_SAVEGAMES);
importWorldmap.setTag(SLOT_NUMBER_IMPORT_WORLDMAP);
ViewGroup exportImportContainer = (ViewGroup) findViewById(R.id.loadsave_export_import_save_container);
addSavegameSlotButtons(slotList, params, Savegames.getUsedSavegameSlots(this));
checkAndRequestPermissions();
if (!isLoading) {
createNewSlot.setTag(SLOT_NUMBER_CREATE_NEW_SLOT);
createNewSlot.setOnClickListener(this);
newSlotContainer.setVisibility(View.VISIBLE);
exportImportContainer.setVisibility(View.GONE);
} else {
newSlotContainer.setVisibility(View.GONE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
exportSaves.setOnClickListener(this);
importSaves.setOnClickListener(this);
importWorldmap.setOnClickListener(this);
exportImportContainer.setVisibility(View.VISIBLE);
boolean hasSavegames = !Savegames.getUsedSavegameSlots(this).isEmpty();
exportSaves.setEnabled(hasSavegames);
} else {
exportImportContainer.setVisibility(View.GONE);
}
}
}
private static final int READ_EXTERNAL_STORAGE_REQUEST = 1;
private static final int WRITE_EXTERNAL_STORAGE_REQUEST = 2;
private void checkAndRequestPermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
&& Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
if (getApplicationContext().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
this.requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
READ_EXTERNAL_STORAGE_REQUEST);
}
if (getApplicationContext().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
this.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
WRITE_EXTERNAL_STORAGE_REQUEST);
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (grantResults.length > 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, R.string.storage_permissions_mandatory, Toast.LENGTH_LONG).show();
((AndorsTrailApplication) getApplication()).discardWorld();
finish();
}
}
private void addSavegameSlotButtons(ViewGroup parent,
LayoutParams params,
List<Integer> usedSavegameSlots) {
int unused = 1;
for (int slot : usedSavegameSlots) {
final FileHeader header = Savegames.quickload(this, slot);
if (header == null) {
continue;
}
while (unused < slot) {
Button b = new Button(this);
b.setLayoutParams(params);
b.setTag(unused);
b.setOnClickListener(this);
b.setText(getString(R.string.loadsave_empty_slot, unused));
tileManager.setImageViewTileForPlayer(getResources(), b, header.iconID);
parent.addView(b, params);
unused++;
}
unused++;
Button b = new Button(this);
b.setLayoutParams(params);
b.setTag(slot);
b.setOnClickListener(this);
b.setText(slot + ". " + header.describe());
tileManager.setImageViewTileForPlayer(getResources(), b, header.iconID);
parent.addView(b, params);
}
}
private void cancelLoadSaveActivity(int slot) {
completeLoadSaveActivity(slot, false);
}
private void completeLoadSaveActivity(int slot) {
completeLoadSaveActivity(slot, true);
}
private void completeLoadSaveActivity(int slot, boolean success) {
Intent i = new Intent();
if (slot == SLOT_NUMBER_CREATE_NEW_SLOT) {
slot = getFirstFreeSlot();
} else if (slot == SLOT_NUMBER_EXPORT_SAVEGAMES
|| slot == SLOT_NUMBER_IMPORT_SAVEGAMES
|| slot == SLOT_NUMBER_IMPORT_WORLDMAP) {
i.putExtra("import_export", true);
if (slot == SLOT_NUMBER_IMPORT_WORLDMAP) {
i.putExtra("import_worldmap", true);
}
if (slot == SLOT_NUMBER_IMPORT_SAVEGAMES) {
i.putExtra("import_savegames", true);
}
if (slot == SLOT_NUMBER_EXPORT_SAVEGAMES) {
i.putExtra("export", true);
}
} else if (slot < SLOT_NUMBER_FIRST_SLOT) {
slot = SLOT_NUMBER_FIRST_SLOT;
}
i.putExtra("slot", slot);
if (success) {
setResult(Activity.RESULT_OK, i);
} else {
setResult(Activity.RESULT_CANCELED, i);
}
LoadSaveActivity.this.finish();
}
private int getFirstFreeSlot() {
int slot;
List<Integer> usedSlots = Savegames.getUsedSavegameSlots(this);
if (usedSlots.isEmpty()) {
slot = SLOT_NUMBER_FIRST_SLOT;
} else {
slot = Collections.max(usedSlots) + 1;
}
return slot;
}
private String getConfirmOverwriteQuestion(int slot) {
if (isLoading) {
return null;
}
return getConfirmOverwriteQuestionIgnoringLoading(slot);
}
private String getConfirmOverwriteQuestionIgnoringLoading(int slot) {
if (slot == SLOT_NUMBER_CREATE_NEW_SLOT) {
return null;//creating a new savegame
}
if (!Savegames.getSlotFile(slot, this).exists()) {
return null;//nothing in slot to overwrite
}
if (preferences.displayOverwriteSavegame
== AndorsTrailPreferences.CONFIRM_OVERWRITE_SAVEGAME_ALWAYS) {
return getString(R.string.loadsave_save_overwrite_confirmation_all);
}
if (preferences.displayOverwriteSavegame == AndorsTrailPreferences.CONFIRM_OVERWRITE_SAVEGAME_NEVER) {
return null;
}
final String currentPlayerName = model.player.getName();
final FileHeader header = Savegames.quickload(this, slot);
if (header == null) {
return null;
}
final String savedPlayerName = header.playerName;
if (currentPlayerName.equals(savedPlayerName)) {
return null; //if the names match
}
return getString(R.string.loadsave_save_overwrite_confirmation, savedPlayerName, currentPlayerName);
}
@Override
public void onClick(View view) {
final int slot = (Integer) view.getTag();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
switch (slot) {
case SLOT_NUMBER_IMPORT_WORLDMAP:
clickImportWorldmap();
return;
case SLOT_NUMBER_IMPORT_SAVEGAMES:
clickImportSaveGames();
return;
case SLOT_NUMBER_EXPORT_SAVEGAMES:
clickExportSaveGames();
return;
}
}
if (!isLoading
&& slot != SLOT_NUMBER_CREATE_NEW_SLOT
&& AndorsTrailApplication.CURRENT_VERSION
== AndorsTrailApplication.DEVELOPMENT_INCOMPATIBLE_SAVEGAME_VERSION) {
if (!isOverwriteTargetInIncompatibleVersion(slot)) {
saveOrOverwriteSavegame(slot);
}
} else if (isLoading) {
loadSaveGame(slot);
} else {
saveOrOverwriteSavegame(slot);
}
}
private void saveOrOverwriteSavegame(int slot) {
final String message = getConfirmOverwriteQuestion(slot);
if (message != null) {
showConfirmOverwriteQuestion(slot, message);
} else {
completeLoadSaveActivity(slot);
}
}
private boolean isOverwriteTargetInIncompatibleVersion(int slot) {
final FileHeader header = Savegames.quickload(this, slot);
if (header != null
&& header.fileversion != AndorsTrailApplication.DEVELOPMENT_INCOMPATIBLE_SAVEGAME_VERSION) {
final CustomDialog d = CustomDialogFactory.createErrorDialog(this,
"Overwriting not allowed",
"You are currently using a development version of Andor's trail. Overwriting a regular savegame is not allowed in development mode.");
CustomDialogFactory.show(d);
return true;
}
return false;
}
//region Imports/Exports
//region Export
@RequiresApi(api = Build.VERSION_CODES.P)
private void exportSaveGames(Intent data) {
Uri uri = data.getData();
Context context = getApplicationContext();
ContentResolver resolver = AndorsTrailApplication.getApplicationFromActivity(this)
.getContentResolver();
File storageDir = AndroidStorage.getStorageDirectory(context,
Constants.FILENAME_SAVEGAME_DIRECTORY);
DocumentFile target = DocumentFile.fromTreeUri(context, uri);
if (target == null) {
return;
}
File[] files = storageDir.listFiles();
if (files == null) {
showErrorExportingSaveGamesUnknown();
return;
}
boolean hasExistingFiles = false;
for (File file : files) {
String fileName = file.getName();
DocumentFile existingFile = target.findFile(fileName);
if (existingFile != null) {
hasExistingFiles = true;
break;
}
}
if (hasExistingFiles) {
showConfirmOverwriteByExportQuestion(resolver, target, files);
} else {
exportSaveGamesFolderContentToFolder(target, files);
}
}
@RequiresApi(api = Build.VERSION_CODES.P)
private void exportSaveGamesFolderContentToFolder(DocumentFile target, File[] files) {
DocumentFile[] sourceFiles = new DocumentFile[files.length];
File[] worldmapFiles = null;
for (int i = 0; i < files.length; i++) {
File file = files[i];
if (file.isFile()) {
sourceFiles[i] = DocumentFile.fromFile(file);
} else if (file.isDirectory() && Objects.equals(file.getName(),
Constants.FILENAME_WORLDMAP_DIRECTORY)) {
worldmapFiles = file.listFiles();
}
}
Context context = this;
File[] finalWorldmapFiles = worldmapFiles;
CopyFilesToExternalFolder(target, sourceFiles, context, finalWorldmapFiles);
}
@RequiresApi(api = Build.VERSION_CODES.P)
private void CopyFilesToExternalFolder(DocumentFile target,
DocumentFile[] sourceFiles,
Context context,
File[] finalWorldmapFiles) {
AndroidStorage.copyDocumentFilesToDirAsync(sourceFiles,
context,
target,
getString(R.string.loadsave_exporting_savegames),
(success) -> {
if (success) {
CopyWorldmapFilesAsZip(target,
context,
finalWorldmapFiles);
} else {
completeLoadSaveActivity(
SLOT_NUMBER_EXPORT_SAVEGAMES,
false);
}
});
}
@RequiresApi(api = Build.VERSION_CODES.P)
private void CopyWorldmapFilesAsZip(DocumentFile target,
Context context,
File[] finalWorldmapFiles) {
AndroidStorage.createZipDocumentFileFromFilesAsync(finalWorldmapFiles,
context,
target,
Constants.FILENAME_WORLDMAP_DIRECTORY,
getString(R.string.loadsave_exporting_worldmap),
(successWorldmap) -> completeLoadSaveActivity(
SLOT_NUMBER_EXPORT_SAVEGAMES,
successWorldmap));
}
//endregion
@RequiresApi(api = Build.VERSION_CODES.P)
private void importSaveGames(Intent data) {
Uri uri = data.getData();
ClipData uris = data.getClipData();
if (uri == null && uris == null) {
//no file was selected
return;
}
Context context = getApplicationContext();
ContentResolver resolver = AndorsTrailApplication.getApplicationFromActivity(this)
.getContentResolver();
File storageDir = AndroidStorage.getStorageDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY);
DocumentFile appSavegameFolder = DocumentFile.fromFile(storageDir);
List<Uri> uriList = new ArrayList<>();
if (uri != null) {
uriList.add(uri);
} else {
for (int i = 0; i < uris.getItemCount(); i++) {
uriList.add(uris.getItemAt(i).getUri());
}
}
importSaveGamesFromUris(context, resolver, appSavegameFolder, uriList);
}
@RequiresApi(api = Build.VERSION_CODES.P)
private void importSaveGamesFromUris(Context context,
ContentResolver resolver,
DocumentFile appSavegameFolder,
List<Uri> uriList) {
int count = uriList.size();
ArrayList<DocumentFile> alreadyExistingFiles = new ArrayList<>();
ArrayList<DocumentFile> newFiles = new ArrayList<>();
for (int i = 0; i < count; i++) {
Uri item = uriList.get(i);
DocumentFile itemFile = DocumentFile.fromSingleUri(context, item);
boolean fileAlreadyExists = getExistsSavegameInOwnFiles(itemFile, appSavegameFolder);
if (fileAlreadyExists) {
alreadyExistingFiles.add(itemFile);
} else {
newFiles.add(itemFile);
}
}
if (alreadyExistingFiles.size() > 0) {
showConfirmOverwriteByImportQuestion(resolver, appSavegameFolder, alreadyExistingFiles, newFiles);
} else {
importSaveGames(resolver, appSavegameFolder, newFiles);
}
}
@RequiresApi(api = Build.VERSION_CODES.P)
private void importSaveGames(ContentResolver resolver,
DocumentFile appSavegameFolder,
List<DocumentFile> saveFiles) {
int size = saveFiles.size();
DocumentFile[] sources = new DocumentFile[size];
DocumentFile[] targets = new DocumentFile[size];
boolean saveAsNew = false;
for (int i = 0; i < size; i++) {
DocumentFile file = saveFiles.get(i);
if (file == null) {//null is value a marker that the next should be saved as new
saveAsNew = true;
continue;
}
int slot = getSlotFromSavegameFileName(file.getName());
if (slot == -1) {
//invalid file name
continue;
}
if (saveAsNew) {
slot = getFirstFreeSlot();
saveAsNew = false;
}
String targetName = Savegames.getSlotFileName(slot);
sources[i] = file;
targets[i] = getOrCreateDocumentFile(appSavegameFolder, targetName);
}
AndroidStorage.copyDocumentFilesFromToAsync(sources,
this,
targets,
getString(R.string.loadsave_importing_savegames),
(sucess) -> completeLoadSaveActivity(
SLOT_NUMBER_IMPORT_SAVEGAMES,
sucess));
}
private boolean getExistsSavegameInOwnFiles(DocumentFile savegameFile, DocumentFile appSavegameFolder) {
if (savegameFile == null) {
return false;
}
DocumentFile foundFile = appSavegameFolder.findFile(Objects.requireNonNull(savegameFile.getName()));
return foundFile != null && foundFile.exists();
}
private int getSlotFromSavegameFileName(String fileName) {
if (fileName == null || !fileName.startsWith(Constants.FILENAME_SAVEGAME_FILENAME_PREFIX)) {
return -1;
}
String slotStr = fileName.substring(Constants.FILENAME_SAVEGAME_FILENAME_PREFIX.length());
int slot;
try {
slot = Integer.parseInt(slotStr);
return slot;
} catch (NumberFormatException e) {
return -1;
}
}
private DocumentFile getOrCreateDocumentFile(DocumentFile folder, String targetName) {
DocumentFile targetFile = folder.findFile(targetName);//try finding the file
if (targetFile == null)//no file found, creating new one
{
targetFile = folder.createFile(Constants.NO_FILE_EXTENSION_MIME_TYPE, targetName);
}
return targetFile;
}
@RequiresApi(api = Build.VERSION_CODES.P)
private void importWorldmap(Intent data) {
Uri uri = data.getData();
Context context = AndorsTrailApplication.getApplicationFromActivity(this).getApplicationContext();
DocumentFile chosenZip = DocumentFile.fromSingleUri(context, uri);
if (chosenZip == null || !chosenZip.isFile()) {
showErrorImportingWorldmapWrongDirectory();
return;
}
String chosenZipName = chosenZip.getName();
if (!chosenZipName.startsWith(Constants.FILENAME_WORLDMAP_DIRECTORY)) {
showErrorImportingWorldmapWrongDirectory();
return;
}
File ownWorldmapFolder = getOwnWorldmapFolder(context);
AndroidStorage.unzipDocumentFileToDirectoryAsync(chosenZip,
this,
ownWorldmapFolder,
false,
getString(R.string.loadsave_importing_worldmap),
(success) -> completeLoadSaveActivity(
SLOT_NUMBER_IMPORT_WORLDMAP,
success));
}
private File getOwnWorldmapFolder(Context context) {
File storageDir = AndroidStorage.getStorageDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY);
File ownWorldmapFolder = null;
for (File f : storageDir.listFiles()) {
if (f.getName().equals(Constants.FILENAME_WORLDMAP_DIRECTORY)) {
ownWorldmapFolder = f;
break;
}
}
if (ownWorldmapFolder == null) {
ownWorldmapFolder = new File(storageDir, Constants.FILENAME_WORLDMAP_DIRECTORY);
ownWorldmapFolder.mkdir();
}
return ownWorldmapFolder;
}
@RequiresApi(api = Build.VERSION_CODES.P)
private void clickExportSaveGames() {
showStartExportInfo(view -> startActivityForResult(AndroidStorage.getNewOpenDirectoryIntent(),
-SLOT_NUMBER_EXPORT_SAVEGAMES));
}
@RequiresApi(api = Build.VERSION_CODES.P)
private void clickImportSaveGames() {
showStartImportSavesInfo(view -> startActivityForResult(AndroidStorage.getNewSelectMultipleSavegameFilesIntent(),
-SLOT_NUMBER_IMPORT_SAVEGAMES));
}
@RequiresApi(api = Build.VERSION_CODES.P)
private void clickImportWorldmap() {
showStartImportWorldmapInfo(view -> startActivityForResult(AndroidStorage.getNewSelectZipIntent(),
-SLOT_NUMBER_IMPORT_WORLDMAP));
}
@RequiresApi(api = Build.VERSION_CODES.P)
private void showConfirmOverwriteByExportQuestion(ContentResolver resolver,
DocumentFile targetFolder,
File[] files) {
final CustomDialog d = CustomDialogFactory.createDialog(this,
getString(R.string.loadsave_export_overwrite_confirmation_title),
getResources().getDrawable(android.R.drawable.ic_dialog_alert),
getString(R.string.loadsave_export_overwrite_confirmation),
null,
true);
CustomDialogFactory.addButton(d,
android.R.string.yes,
v -> exportSaveGamesFolderContentToFolder(targetFolder, files));
CustomDialogFactory.addDismissButton(d, android.R.string.no);
CustomDialogFactory.show(d);
}
@RequiresApi(api = Build.VERSION_CODES.P)
private void showConfirmOverwriteByImportQuestion(ContentResolver resolver,
DocumentFile appSavegameFolder,
List<DocumentFile> alreadyExistingFiles,
List<DocumentFile> newFiles) {
final String title = getString(R.string.loadsave_import_overwrite_confirmation_title);
String message = getString(R.string.loadsave_import_file_exists_question);
StringBuilder sb = new StringBuilder();
sb.append('\n');
int amount = alreadyExistingFiles.size();
Context context = AndorsTrailApplication.getApplicationFromActivity(this).getApplicationContext();
ArrayList<CustomDialog> dialogs = new ArrayList<>(amount);
for (int i = 0; i < amount; i++) {
DocumentFile alreadyExistingFile = alreadyExistingFiles.get(i);
int slot = getSlotFromSavegameFileName(alreadyExistingFile.getName());
FileHeader existingFileHeader = Savegames.quickload(context, slot);
FileHeader importedFileHeader = null;
try (InputStream stream = resolver.openInputStream(alreadyExistingFile.getUri());
DataInputStream dataStream = new DataInputStream(stream)) {
importedFileHeader = new FileHeader(dataStream, true);
} catch (FileNotFoundException e) {
e.printStackTrace();
continue;
} catch (IOException e) {
e.printStackTrace();
continue;
}
StringBuilder messageSb = new StringBuilder();
String existingFileDescription = getString(R.string.loadsave_import_existing_description,
Integer.toString(slot),
existingFileHeader.describe());
String importedFileDescription = getString(R.string.loadsave_import_imported_description,
Integer.toString(slot),
importedFileHeader.describe());
messageSb.append(getString(R.string.loadsave_import_file_exists_question,
existingFileDescription,
importedFileDescription));
String m = messageSb.toString();
CustomDialog dialog = CustomDialogFactory.createDialog(this,
title,
getResources().getDrawable(android.R.drawable.ic_dialog_alert),
m,
null,
true,
false,
true);
CustomDialogFactory.addButton(dialog, R.string.loadsave_import_option_keep_existing, v -> {
//do nothing
GoToNextConflictOrFinish(resolver, appSavegameFolder, newFiles, dialogs);
});
CustomDialogFactory.addButton(dialog, R.string.loadsave_import_option_keep_imported, v -> {
newFiles.add(alreadyExistingFile);
GoToNextConflictOrFinish(resolver, appSavegameFolder, newFiles, dialogs);
});
CustomDialogFactory.addButton(dialog, R.string.loadsave_import_option_add_as_new, v -> {
newFiles.add(null);//add a null element as marker to know later if the next file
// should be imported as new or overwrite the existing one
newFiles.add(alreadyExistingFile);
GoToNextConflictOrFinish(resolver, appSavegameFolder, newFiles, dialogs);
});
CustomDialogFactory.addCancelButton(dialog, android.R.string.cancel);
CustomDialogFactory.setCancelListener(dialog, v -> {
completeLoadSaveActivity(SLOT_NUMBER_IMPORT_SAVEGAMES, false);
});
dialogs.add(dialog);
}
GoToNextConflictOrFinish(resolver, appSavegameFolder, newFiles, dialogs);
}
@RequiresApi(api = Build.VERSION_CODES.P)
private void GoToNextConflictOrFinish(ContentResolver resolver,
DocumentFile appSavegameFolder,
List<DocumentFile> newFiles,
ArrayList<CustomDialog> dialogs) {
if (dialogs.stream().count() > 0) {
CustomDialog d = dialogs.remove(0);
CustomDialogFactory.show(d);
} else {
importSaveGames(resolver, appSavegameFolder, newFiles);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != Activity.RESULT_OK) {
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
switch (-requestCode) {
case SLOT_NUMBER_EXPORT_SAVEGAMES:
exportSaveGames(data);
return;
case SLOT_NUMBER_IMPORT_SAVEGAMES:
importSaveGames(data);
return;
case SLOT_NUMBER_IMPORT_WORLDMAP:
importWorldmap(data);
return;
}
}
}
//endregion
private void loadSaveGame(int slot) {
if (!Savegames.getSlotFile(slot, this).exists()) {
showErrorLoadingEmptySlot();
} else {
final FileHeader header = Savegames.quickload(this, slot);
if (header != null && !header.hasUnlimitedSaves) {
showSlotGetsDeletedOnLoadWarning(slot);
} else {
completeLoadSaveActivity(slot);
}
}
}
//region show Dialogs
//region Import/Export
@RequiresApi(api = Build.VERSION_CODES.P)
private void showStartExportInfo(OnClickListener onOk) {
final CustomDialog d = CustomDialogFactory.createDialog(this,
getString(R.string.loadsave_export),
getResources().getDrawable(android.R.drawable.ic_dialog_info),
getString(R.string.loadsave_export_info),
null,
true);
CustomDialogFactory.addButton(d, android.R.string.yes, onOk);
CustomDialogFactory.addDismissButton(d, android.R.string.no);
CustomDialogFactory.show(d);
}
@RequiresApi(api = Build.VERSION_CODES.P)
private void showStartImportSavesInfo(OnClickListener onOk) {
final CustomDialog d = CustomDialogFactory.createDialog(this,
getString(R.string.loadsave_import_save),
getResources().getDrawable(android.R.drawable.ic_dialog_info),
getString(R.string.loadsave_import_save_info),
null,
true);
CustomDialogFactory.addButton(d, android.R.string.yes, onOk);
CustomDialogFactory.addDismissButton(d, android.R.string.no);
CustomDialogFactory.show(d);
}
@RequiresApi(api = Build.VERSION_CODES.P)
private void showStartImportWorldmapInfo(OnClickListener onOk) {
final CustomDialog d = CustomDialogFactory.createDialog(this,
getString(R.string.loadsave_import_worldmap),
getResources().getDrawable(android.R.drawable.ic_dialog_info),
getString(R.string.loadsave_import_worldmap_info),
null,
true);
CustomDialogFactory.addButton(d, android.R.string.yes, onOk);
CustomDialogFactory.addDismissButton(d, android.R.string.no);
CustomDialogFactory.show(d);
}
private void showErrorImportingWorldmapWrongDirectory() {
final CustomDialog d = CustomDialogFactory.createErrorDialog(this,
getString(R.string.loadsave_import_worldmap_unsuccessfull),
getString(R.string.loadsave_import_worldmap_wrong_file));
CustomDialogFactory.show(d);
}
private void showErrorExportingSaveGamesUnknown() {
final CustomDialog d = CustomDialogFactory.createErrorDialog(this,
getString(R.string.loadsave_export_unsuccessfull),
getString(R.string.loadsave_export_error_unknown));
CustomDialogFactory.show(d);
}
//endregion
private void showErrorLoadingEmptySlot() {
final CustomDialog d = CustomDialogFactory.createErrorDialog(this,
getString(R.string.startscreen_error_loading_game),
getString(R.string.startscreen_error_loading_empty_slot));
CustomDialogFactory.show(d);
}
private void showSlotGetsDeletedOnLoadWarning(final int slot) {
final CustomDialog d = CustomDialogFactory.createDialog(this,
getString(R.string.startscreen_attention_slot_gets_delete_on_load),
getResources().getDrawable(android.R.drawable.ic_dialog_alert),
getString(R.string.startscreen_attention_message_slot_gets_delete_on_load),
null,
true);
CustomDialogFactory.addButton(d, android.R.string.ok, v -> completeLoadSaveActivity(slot));
CustomDialogFactory.show(d);
}
private void showConfirmOverwriteQuestion(final int slot, String message) {
final String title = getString(R.string.loadsave_save_overwrite_confirmation_title) + ' '
+ getString(R.string.loadsave_save_overwrite_confirmation_slot, slot);
final CustomDialog d = CustomDialogFactory.createDialog(this,
title,
getResources().getDrawable(android.R.drawable.ic_dialog_alert),
message,
null,
true);
CustomDialogFactory.addButton(d, android.R.string.yes, v -> completeLoadSaveActivity(slot));
CustomDialogFactory.addDismissButton(d, android.R.string.no);
CustomDialogFactory.show(d);
}
//endregion
}

View File

@@ -1,180 +1,180 @@
package com.gpl.rpg.AndorsTrail.activity;
import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.content.Intent;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
import android.widget.TextView;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.WorldSetup;
import com.gpl.rpg.AndorsTrail.WorldSetup.OnResourcesLoadedListener;
import com.gpl.rpg.AndorsTrail.WorldSetup.OnSceneLoadedListener;
import com.gpl.rpg.AndorsTrail.savegames.Savegames;
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
import com.gpl.rpg.AndorsTrail.view.CloudsAnimatorView;
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory;
public final class LoadingActivity extends AndorsTrailBaseActivity implements OnResourcesLoadedListener, OnSceneLoadedListener {
private WorldSetup setup;
private Dialog progressDialog;
private CloudsAnimatorView clouds_back, clouds_mid, clouds_front;
boolean loaded = false;
private Object semaphore = new Object();
@Override
public void onCreate(Bundle savedInstanceState) {
setTheme(ThemeHelper.getBaseTheme());
super.onCreate(savedInstanceState);
AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this);
app.setWindowParameters(this);
setContentView(R.layout.startscreen);
TextView tv = (TextView) findViewById(R.id.startscreen_version);
tv.setVisibility(View.GONE);
clouds_back = (CloudsAnimatorView) findViewById(R.id.ts_clouds_animator_back);
if (clouds_back != null) clouds_back.setCloudsCountAndLayer(40, CloudsAnimatorView.Layer.below);
clouds_mid = (CloudsAnimatorView) findViewById(R.id.ts_clouds_animator_mid);
if (clouds_mid != null) clouds_mid.setCloudsCountAndLayer(15, CloudsAnimatorView.Layer.center);
clouds_front = (CloudsAnimatorView) findViewById(R.id.ts_clouds_animator_front);
if (clouds_front != null) clouds_front.setCloudsCountAndLayer(8, CloudsAnimatorView.Layer.above);
this.setup = app.getWorldSetup();
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
((AnimationDrawable)((ImageView)findViewById(R.id.title_logo)).getDrawable()).start();
ImageView iv = (ImageView) findViewById(R.id.ts_foreground);
int ivWidth = iv.getWidth();
int drawableWidth = iv.getDrawable().getIntrinsicWidth();
float ratio = ((float)ivWidth) / ((float)drawableWidth);
if (clouds_back != null) {
clouds_back.setScalingRatio(ratio);
}
if (clouds_mid != null) {
clouds_mid.setScalingRatio(ratio);
}
if (clouds_front != null) {
clouds_front.setScalingRatio(ratio);
}
if (progressDialog == null) {
progressDialog = CustomDialogFactory.createDialog(this, getResources().getString(R.string.dialog_loading_message),
getResources().getDrawable(R.drawable.loading_anim), null, null, false, false);
synchronized (semaphore) {
if (!loaded) {
progressDialog.setOwnerActivity(this);
CustomDialogFactory.show(progressDialog);
}
}
}
}
}
@Override
public void onResume() {
super.onResume();
setup.setOnResourcesLoadedListener(this);
final ImageView iv = (ImageView) findViewById(R.id.ts_foreground);
iv.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
float[] point = new float[]{0f,0.25f * iv.getDrawable().getIntrinsicHeight()};
iv.getImageMatrix().mapPoints(point);
int imgY = (int) (iv.getTop() + point[1]);
if (clouds_back != null) {
clouds_back.setYMax(imgY);
}
if (clouds_mid != null) {
clouds_mid.setYMax(imgY);
}
if (clouds_front != null) {
clouds_front.setYMax(imgY);
}
iv.getViewTreeObserver().removeOnPreDrawListener(this);
return true;
}
});
if (clouds_back != null)clouds_back.resumeAnimation();
if (clouds_mid != null)clouds_mid.resumeAnimation();
if (clouds_front != null)clouds_front.resumeAnimation();
}
@Override
public void onPause() {
super.onPause();
setup.setOnResourcesLoadedListener(null);
setup.removeOnSceneLoadedListener(this);
if (clouds_back != null)clouds_back.pauseAnimation();
if (clouds_mid != null)clouds_mid.pauseAnimation();
if (clouds_front != null)clouds_front.pauseAnimation();
}
@Override
public void onResourcesLoaded() {
loaded = false;
setup.startCharacterSetup(this);
}
@Override
public void onSceneLoaded() {
synchronized (semaphore) {
if (progressDialog != null) progressDialog.dismiss();
loaded =true;
}
startActivity(new Intent(this, MainActivity.class));
this.finish();
}
@Override
public void onSceneLoadFailed(Savegames.LoadSavegameResult loadResult) {
synchronized (semaphore) {
if (progressDialog != null) progressDialog.dismiss();
loaded =true;
}
if (loadResult == Savegames.LoadSavegameResult.savegameIsFromAFutureVersion) {
showLoadingFailedDialog(R.string.dialog_loading_failed_incorrectversion);
} else if (loadResult == Savegames.LoadSavegameResult.cheatingDetected) {
showLoadingFailedDialog(R.string.dialog_loading_failed_cheat);
} else {
showLoadingFailedDialog(R.string.dialog_loading_failed_message);
}
}
private void showLoadingFailedDialog(int messageResourceID) {
final Dialog d = CustomDialogFactory.createDialog(this, getResources().getString(R.string.dialog_loading_failed_title), null, getResources().getString(messageResourceID), null, true);
CustomDialogFactory.addDismissButton(d, android.R.string.ok);
CustomDialogFactory.setDismissListener(d, new OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
LoadingActivity.this.finish();
}
});
CustomDialogFactory.show(d);
}
}
package com.gpl.rpg.AndorsTrail.activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.content.Intent;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
import android.widget.TextView;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.WorldSetup;
import com.gpl.rpg.AndorsTrail.WorldSetup.OnResourcesLoadedListener;
import com.gpl.rpg.AndorsTrail.WorldSetup.OnSceneLoadedListener;
import com.gpl.rpg.AndorsTrail.savegames.Savegames;
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
import com.gpl.rpg.AndorsTrail.view.CloudsAnimatorView;
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory;
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory.CustomDialog;
public final class LoadingActivity extends AndorsTrailBaseActivity implements OnResourcesLoadedListener, OnSceneLoadedListener {
private WorldSetup setup;
private CustomDialog progressDialog;
private CloudsAnimatorView clouds_back, clouds_mid, clouds_front;
boolean loaded = false;
private Object semaphore = new Object();
@Override
public void onCreate(Bundle savedInstanceState) {
setTheme(ThemeHelper.getBaseTheme());
super.onCreate(savedInstanceState);
AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this);
app.setWindowParameters(this);
setContentView(R.layout.startscreen);
TextView tv = (TextView) findViewById(R.id.startscreen_version);
tv.setVisibility(View.GONE);
clouds_back = (CloudsAnimatorView) findViewById(R.id.ts_clouds_animator_back);
if (clouds_back != null) clouds_back.setCloudsCountAndLayer(40, CloudsAnimatorView.Layer.below);
clouds_mid = (CloudsAnimatorView) findViewById(R.id.ts_clouds_animator_mid);
if (clouds_mid != null) clouds_mid.setCloudsCountAndLayer(15, CloudsAnimatorView.Layer.center);
clouds_front = (CloudsAnimatorView) findViewById(R.id.ts_clouds_animator_front);
if (clouds_front != null) clouds_front.setCloudsCountAndLayer(8, CloudsAnimatorView.Layer.above);
this.setup = app.getWorldSetup();
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
((AnimationDrawable)((ImageView)findViewById(R.id.title_logo)).getDrawable()).start();
ImageView iv = (ImageView) findViewById(R.id.ts_foreground);
int ivWidth = iv.getWidth();
int drawableWidth = iv.getDrawable().getIntrinsicWidth();
float ratio = ((float)ivWidth) / ((float)drawableWidth);
if (clouds_back != null) {
clouds_back.setScalingRatio(ratio);
}
if (clouds_mid != null) {
clouds_mid.setScalingRatio(ratio);
}
if (clouds_front != null) {
clouds_front.setScalingRatio(ratio);
}
if (progressDialog == null) {
progressDialog = CustomDialogFactory.createDialog(this, getResources().getString(R.string.dialog_loading_message),
getResources().getDrawable(R.drawable.loading_anim), null, null, false, false);
synchronized (semaphore) {
if (!loaded) {
progressDialog.setOwnerActivity(this);
CustomDialogFactory.show(progressDialog);
}
}
}
}
}
@Override
public void onResume() {
super.onResume();
setup.setOnResourcesLoadedListener(this);
final ImageView iv = (ImageView) findViewById(R.id.ts_foreground);
iv.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
float[] point = new float[]{0f,0.25f * iv.getDrawable().getIntrinsicHeight()};
iv.getImageMatrix().mapPoints(point);
int imgY = (int) (iv.getTop() + point[1]);
if (clouds_back != null) {
clouds_back.setYMax(imgY);
}
if (clouds_mid != null) {
clouds_mid.setYMax(imgY);
}
if (clouds_front != null) {
clouds_front.setYMax(imgY);
}
iv.getViewTreeObserver().removeOnPreDrawListener(this);
return true;
}
});
if (clouds_back != null)clouds_back.resumeAnimation();
if (clouds_mid != null)clouds_mid.resumeAnimation();
if (clouds_front != null)clouds_front.resumeAnimation();
}
@Override
public void onPause() {
super.onPause();
setup.setOnResourcesLoadedListener(null);
setup.removeOnSceneLoadedListener(this);
if (clouds_back != null)clouds_back.pauseAnimation();
if (clouds_mid != null)clouds_mid.pauseAnimation();
if (clouds_front != null)clouds_front.pauseAnimation();
}
@Override
public void onResourcesLoaded() {
loaded = false;
setup.startCharacterSetup(this);
}
@Override
public void onSceneLoaded() {
synchronized (semaphore) {
if (progressDialog != null) progressDialog.dismiss();
loaded =true;
}
startActivity(new Intent(this, MainActivity.class));
this.finish();
}
@Override
public void onSceneLoadFailed(Savegames.LoadSavegameResult loadResult) {
synchronized (semaphore) {
if (progressDialog != null) progressDialog.dismiss();
loaded =true;
}
if (loadResult == Savegames.LoadSavegameResult.savegameIsFromAFutureVersion) {
showLoadingFailedDialog(R.string.dialog_loading_failed_incorrectversion);
} else if (loadResult == Savegames.LoadSavegameResult.cheatingDetected) {
showLoadingFailedDialog(R.string.dialog_loading_failed_cheat);
} else {
showLoadingFailedDialog(R.string.dialog_loading_failed_message);
}
}
private void showLoadingFailedDialog(int messageResourceID) {
final CustomDialog d = CustomDialogFactory.createDialog(this, getResources().getString(R.string.dialog_loading_failed_title), null, getResources().getString(messageResourceID), null, true);
CustomDialogFactory.addDismissButton(d, android.R.string.ok);
CustomDialogFactory.setDismissListener(d, new OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
LoadingActivity.this.finish();
}
});
CustomDialogFactory.show(d);
}
}

View File

@@ -34,7 +34,6 @@ import com.gpl.rpg.AndorsTrail.controller.listeners.WorldEventListener;
import com.gpl.rpg.AndorsTrail.model.ability.ActorCondition;
import com.gpl.rpg.AndorsTrail.model.ability.ActorConditionEffect;
import com.gpl.rpg.AndorsTrail.model.actor.Monster;
import com.gpl.rpg.AndorsTrail.model.actor.Player;
import com.gpl.rpg.AndorsTrail.model.item.Loot;
import com.gpl.rpg.AndorsTrail.model.map.MapObject;
import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap;
@@ -44,6 +43,7 @@ import com.gpl.rpg.AndorsTrail.util.Coord;
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
import com.gpl.rpg.AndorsTrail.view.CombatView;
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory;
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory.CustomDialog;
import com.gpl.rpg.AndorsTrail.view.DisplayActiveActorConditionIcons;
import com.gpl.rpg.AndorsTrail.view.ItemContainerAdapter;
import com.gpl.rpg.AndorsTrail.view.MainView;
@@ -248,7 +248,7 @@ public final class MainActivity
final ItemContainerAdapter inventoryListAdapter = new QuickslotsItemContainerAdapter(lv.getContext(), world.tileManager, world.model.player.inventory.usableItems(), world.model.player, wornTiles);
lv.setAdapter(inventoryListAdapter);
final Dialog d = CustomDialogFactory.createDialog(v.getContext(),
final CustomDialog d = CustomDialogFactory.createDialog(v.getContext(),
v.getResources().getString(R.string.inventory_assign),
v.getResources().getDrawable(R.drawable.ui_icon_equipment),
v.getResources().getString(R.string.inventory_selectitem), view, false);

View File

@@ -1,6 +1,5 @@
package com.gpl.rpg.AndorsTrail.activity;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;

View File

@@ -1,6 +1,5 @@
package com.gpl.rpg.AndorsTrail.activity;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
@@ -31,6 +30,7 @@ public final class MonsterInfoActivity extends AndorsTrailBaseActivity {
private RangeBar hp;
private ViewGroup monsterinfo_container;
private TextView monsterinfo_max_ap;
private TextView monsterinfo_killcount;
@Override
@@ -48,6 +48,7 @@ public final class MonsterInfoActivity extends AndorsTrailBaseActivity {
monsterinfo_title = (TextView) findViewById(R.id.monsterinfo_title);
monsterinfo_difficulty = (TextView) findViewById(R.id.monsterinfo_difficulty);
monsterinfo_max_ap = (TextView) findViewById(R.id.monsterinfo_max_ap);
monsterinfo_killcount = (TextView) findViewById(R.id.monsterinfo_killcount);
Button b = (Button) findViewById(R.id.monsterinfo_close);
b.setOnClickListener(new OnClickListener() {
@@ -95,6 +96,7 @@ public final class MonsterInfoActivity extends AndorsTrailBaseActivity {
false);
hp.update(monster.getMaxHP(), monster.getCurrentHP());
monsterinfo_max_ap.setText(Integer.toString(monster.getMaxAP()));
monsterinfo_killcount.setText(Integer.toString(world.model.statistics.getNumberOfKillsForMonsterName(monster.getName()) ));
}
public static int getMonsterDifficultyResource(ControllerContext controllerContext, Monster monster) {

View File

@@ -1,36 +1,36 @@
package com.gpl.rpg.AndorsTrail.activity;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.view.Window;
import android.view.WindowManager;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
public final class Preferences extends PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(ThemeHelper.getBaseTheme());
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this);
if (app.getPreferences().fullscreen) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
} else {
getWindow().setFlags(0, WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
app.setLocale(this);
addPreferencesFromResource(R.xml.preferences);
}
@Override
protected void onResume() {
super.onResume();
AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this);
app.setLocale(this);
}
}
package com.gpl.rpg.AndorsTrail.activity;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.view.Window;
import android.view.WindowManager;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
public final class Preferences extends PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(ThemeHelper.getBaseTheme());
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this);
if (app.getPreferences().fullscreen) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
} else {
getWindow().setFlags(0, WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
app.setLocale(this);
addPreferencesFromResource(R.xml.preferences);
}
@Override
protected void onResume() {
super.onResume();
AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this);
app.setLocale(this);
}
}

View File

@@ -2,10 +2,8 @@ package com.gpl.rpg.AndorsTrail.activity;
import android.content.res.Resources;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTabHost;
import androidx.fragment.app.FragmentTabHost;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

View File

@@ -1,6 +1,5 @@
package com.gpl.rpg.AndorsTrail.activity;
import android.app.Activity;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;

View File

@@ -1,292 +1,288 @@
package com.gpl.rpg.AndorsTrail.activity;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.AndorsTrailPreferences;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.activity.fragment.StartScreenActivity_MainMenu;
import com.gpl.rpg.AndorsTrail.activity.fragment.StartScreenActivity_MainMenu.OnNewGameRequestedListener;
import com.gpl.rpg.AndorsTrail.activity.fragment.StartScreenActivity_NewGame;
import com.gpl.rpg.AndorsTrail.activity.fragment.StartScreenActivity_NewGame.GameCreationOverListener;
import com.gpl.rpg.AndorsTrail.resource.tiles.TileManager;
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
import com.gpl.rpg.AndorsTrail.view.CloudsAnimatorView;
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory;
import android.Manifest;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.drawable.AnimationDrawable;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager.OnBackStackChangedListener;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
public final class StartScreenActivity extends AndorsTrailBaseFragmentActivity implements OnNewGameRequestedListener, GameCreationOverListener, OnBackStackChangedListener {
private TextView tv;
private TextView development_version;
private CloudsAnimatorView clouds_back, clouds_mid, clouds_front;
private Fragment currentFragment;
//Means false by default, as a toggle is initiated in onCreate.
boolean ui_visible = true;
@Override
public void onCreate(Bundle savedInstanceState) {
initPreferences();
setTheme(ThemeHelper.getBaseTheme());
super.onCreate(savedInstanceState);
final AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this);
final Resources res = getResources();
TileManager tileManager = app.getWorld().tileManager;
tileManager.setDensity(res);
app.setWindowParameters(this);
setContentView(R.layout.startscreen);
if (findViewById(R.id.startscreen_fragment_container) != null) {
StartScreenActivity_MainMenu mainMenu = new StartScreenActivity_MainMenu();
getSupportFragmentManager().beginTransaction()
.replace(R.id.startscreen_fragment_container, mainMenu)
.commit();
currentFragment = mainMenu;
getSupportFragmentManager().addOnBackStackChangedListener(this);
}
tv = (TextView) findViewById(R.id.startscreen_version);
tv.setText('v' + AndorsTrailApplication.CURRENT_VERSION_DISPLAY);
development_version = (TextView) findViewById(R.id.startscreen_dev_version);
if (AndorsTrailApplication.DEVELOPMENT_INCOMPATIBLE_SAVEGAMES) {
development_version.setText(R.string.startscreen_incompatible_savegames);
development_version.setVisibility(View.VISIBLE);
} else if (!AndorsTrailApplication.IS_RELEASE_VERSION) {
development_version.setText(R.string.startscreen_non_release_version);
development_version.setVisibility(View.VISIBLE);
}
clouds_back = (CloudsAnimatorView) findViewById(R.id.ts_clouds_animator_back);
if (clouds_back != null) clouds_back.setCloudsCountAndLayer(40, CloudsAnimatorView.Layer.below);
clouds_mid = (CloudsAnimatorView) findViewById(R.id.ts_clouds_animator_mid);
if (clouds_mid != null) clouds_mid.setCloudsCountAndLayer(15, CloudsAnimatorView.Layer.center);
clouds_front = (CloudsAnimatorView) findViewById(R.id.ts_clouds_animator_front);
if (clouds_front != null) clouds_front.setCloudsCountAndLayer(8, CloudsAnimatorView.Layer.above);
View background = findViewById(R.id.title_bg);
if (background != null) {
background.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toggleUiVisibility();
}
});
}
if (development_version.getVisibility() == View.VISIBLE) {
development_version.setText(development_version.getText()
// +
// "\nMax Heap: " + Runtime.getRuntime().maxMemory() / (1024 * 1024) + "MB"+
// "\nUsed Heap: " + Runtime.getRuntime().totalMemory() / (1024 * 1024) + "MB"+
// "\nTile size: " + (int) (32 * res.getDisplayMetrics().density)
);
}
toggleUiVisibility();
app.getWorldSetup().startResourceLoader(res);
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (grantResults.length > 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) {
final Dialog d = CustomDialogFactory.createDialog(this,
getResources().getString(R.string.dialog_permission_information_title),
getResources().getDrawable(android.R.drawable.ic_dialog_info),
getResources().getString(R.string.dialog_permission_information),
null,
true);
final Activity activity = this;
CustomDialogFactory.addDismissButton(d, android.R.string.ok);
CustomDialogFactory.setDismissListener(d, new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
StartScreenActivity_MainMenu.checkAndRequestPermissions(activity);
}
});
CustomDialogFactory.show(d);
}
}
private void toggleUiVisibility() {
ui_visible = !ui_visible;
int visibility = ui_visible ? View.VISIBLE : View.GONE;
if (tv != null) tv.setVisibility(visibility);
if (!AndorsTrailApplication.IS_RELEASE_VERSION) {
if (development_version != null) development_version.setVisibility(visibility);
}
if (currentFragment != null) {
if (ui_visible) {
if (!AndorsTrailApplication.IS_RELEASE_VERSION) {
development_version.setText(
development_version.getText()
// +
// "\nMax Heap: " + Runtime.getRuntime().maxMemory() / (1024 * 1024) + "MB"+
// "\nUsed Heap: " + Runtime.getRuntime().totalMemory() / (1024 * 1024) + "MB"+
// "\nTile size: " + (int) (32 * getResources().getDisplayMetrics().density)
);
}
getSupportFragmentManager().beginTransaction()
.show(currentFragment)
.commit();
} else {
getSupportFragmentManager().beginTransaction()
.hide(currentFragment)
.commit();
}
}
}
private void initPreferences() {
AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this);
AndorsTrailPreferences preferences = app.getPreferences();
preferences.read(this);
ThemeHelper.changeTheme(preferences.selectedTheme);
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
((AnimationDrawable)((ImageView)findViewById(R.id.title_logo)).getDrawable()).start();
ImageView iv = (ImageView) findViewById(R.id.ts_foreground);
int ivWidth = iv.getWidth();
int drawableWidth = iv.getDrawable().getIntrinsicWidth();
float ratio = ((float)ivWidth) / ((float)drawableWidth);
if (clouds_back != null) {
clouds_back.setScalingRatio(ratio);
}
if (clouds_mid != null) {
clouds_mid.setScalingRatio(ratio);
}
if (clouds_front != null) {
clouds_front.setScalingRatio(ratio);
}
}
}
@Override
protected void onResume() {
super.onResume();
final ImageView iv = (ImageView) findViewById(R.id.ts_foreground);
iv.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
float[] point = new float[]{0f,0.25f * iv.getDrawable().getIntrinsicHeight()};
iv.getImageMatrix().mapPoints(point);
int imgY = (int) (iv.getTop() + point[1]);
int screenHeight = getResources().getDisplayMetrics().heightPixels;
if (clouds_back != null) {
clouds_back.setYMax(imgY);
}
if (clouds_mid != null) {
clouds_mid.setYMax(imgY);
}
if (clouds_front != null) {
clouds_front.setYMax(imgY);
}
iv.getViewTreeObserver().removeOnPreDrawListener(this);
return true;
}
});
if (clouds_back != null)clouds_back.resumeAnimation();
if (clouds_mid != null)clouds_mid.resumeAnimation();
if (clouds_front != null)clouds_front.resumeAnimation();
}
@Override
protected void onPause() {
super.onPause();
if (clouds_back != null)clouds_back.pauseAnimation();
if (clouds_mid != null)clouds_mid.pauseAnimation();
if (clouds_front != null)clouds_front.pauseAnimation();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
backPressed();
return true;
} else {
return super.onKeyDown(keyCode, event);
}
}
return super.onKeyDown(keyCode, event);
}
private void backPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStack();
currentFragment = getSupportFragmentManager().findFragmentById(R.id.startscreen_fragment_container);
}
}
public void onNewGameRequested() {
if (findViewById(R.id.startscreen_fragment_container) != null) {
StartScreenActivity_NewGame newGameFragment = new StartScreenActivity_NewGame();
getSupportFragmentManager().beginTransaction()
.replace(R.id.startscreen_fragment_container, newGameFragment)
.addToBackStack(null)
.commit();
currentFragment = newGameFragment;
}
}
@Override
public void onGameCreationCancelled() {
backPressed();
}
@Override
public void onBackStackChanged() {
currentFragment = getSupportFragmentManager().findFragmentById(R.id.startscreen_fragment_container);
}
}
package com.gpl.rpg.AndorsTrail.activity;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.AndorsTrailPreferences;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.activity.fragment.StartScreenActivity_MainMenu;
import com.gpl.rpg.AndorsTrail.activity.fragment.StartScreenActivity_MainMenu.OnNewGameRequestedListener;
import com.gpl.rpg.AndorsTrail.activity.fragment.StartScreenActivity_NewGame;
import com.gpl.rpg.AndorsTrail.activity.fragment.StartScreenActivity_NewGame.GameCreationOverListener;
import com.gpl.rpg.AndorsTrail.resource.tiles.TileManager;
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
import com.gpl.rpg.AndorsTrail.view.CloudsAnimatorView;
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory;
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory.CustomDialog;
import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager.OnBackStackChangedListener;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
import android.widget.TextView;
public final class StartScreenActivity extends AndorsTrailBaseFragmentActivity implements OnNewGameRequestedListener, GameCreationOverListener, OnBackStackChangedListener {
private TextView tv;
private TextView development_version;
private CloudsAnimatorView clouds_back, clouds_mid, clouds_front;
private Fragment currentFragment;
//Means false by default, as a toggle is initiated in onCreate.
boolean ui_visible = true;
@Override
public void onCreate(Bundle savedInstanceState) {
initPreferences();
setTheme(ThemeHelper.getBaseTheme());
super.onCreate(savedInstanceState);
final AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this);
final Resources res = getResources();
TileManager tileManager = app.getWorld().tileManager;
tileManager.setDensity(res);
app.setWindowParameters(this);
setContentView(R.layout.startscreen);
if (findViewById(R.id.startscreen_fragment_container) != null) {
StartScreenActivity_MainMenu mainMenu = new StartScreenActivity_MainMenu();
getSupportFragmentManager().beginTransaction()
.replace(R.id.startscreen_fragment_container, mainMenu)
.commit();
currentFragment = mainMenu;
getSupportFragmentManager().addOnBackStackChangedListener(this);
}
tv = (TextView) findViewById(R.id.startscreen_version);
tv.setText('v' + AndorsTrailApplication.CURRENT_VERSION_DISPLAY);
development_version = (TextView) findViewById(R.id.startscreen_dev_version);
if (AndorsTrailApplication.DEVELOPMENT_INCOMPATIBLE_SAVEGAMES) {
development_version.setText(R.string.startscreen_incompatible_savegames);
development_version.setVisibility(View.VISIBLE);
} else if (!AndorsTrailApplication.IS_RELEASE_VERSION) {
development_version.setText(R.string.startscreen_non_release_version);
development_version.setVisibility(View.VISIBLE);
}
clouds_back = (CloudsAnimatorView) findViewById(R.id.ts_clouds_animator_back);
if (clouds_back != null) clouds_back.setCloudsCountAndLayer(40, CloudsAnimatorView.Layer.below);
clouds_mid = (CloudsAnimatorView) findViewById(R.id.ts_clouds_animator_mid);
if (clouds_mid != null) clouds_mid.setCloudsCountAndLayer(15, CloudsAnimatorView.Layer.center);
clouds_front = (CloudsAnimatorView) findViewById(R.id.ts_clouds_animator_front);
if (clouds_front != null) clouds_front.setCloudsCountAndLayer(8, CloudsAnimatorView.Layer.above);
View background = findViewById(R.id.title_bg);
if (background != null) {
background.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toggleUiVisibility();
}
});
}
if (development_version.getVisibility() == View.VISIBLE) {
development_version.setText(development_version.getText()
// +
// "\nMax Heap: " + Runtime.getRuntime().maxMemory() / (1024 * 1024) + "MB"+
// "\nUsed Heap: " + Runtime.getRuntime().totalMemory() / (1024 * 1024) + "MB"+
// "\nTile size: " + (int) (32 * res.getDisplayMetrics().density)
);
}
toggleUiVisibility();
app.getWorldSetup().startResourceLoader(res);
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (grantResults.length > 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) {
final CustomDialog d = CustomDialogFactory.createDialog(this,
getResources().getString(R.string.dialog_permission_information_title),
getResources().getDrawable(android.R.drawable.ic_dialog_info),
getResources().getString(R.string.dialog_permission_information),
null,
true);
final Activity activity = this;
CustomDialogFactory.addDismissButton(d, android.R.string.ok);
CustomDialogFactory.setDismissListener(d, new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
StartScreenActivity_MainMenu.checkAndRequestPermissions(activity);
}
});
CustomDialogFactory.show(d);
}
}
private void toggleUiVisibility() {
ui_visible = !ui_visible;
int visibility = ui_visible ? View.VISIBLE : View.GONE;
if (tv != null) tv.setVisibility(visibility);
if (!AndorsTrailApplication.IS_RELEASE_VERSION) {
if (development_version != null) development_version.setVisibility(visibility);
}
if (currentFragment != null) {
if (ui_visible) {
if (!AndorsTrailApplication.IS_RELEASE_VERSION) {
development_version.setText(
development_version.getText()
// +
// "\nMax Heap: " + Runtime.getRuntime().maxMemory() / (1024 * 1024) + "MB"+
// "\nUsed Heap: " + Runtime.getRuntime().totalMemory() / (1024 * 1024) + "MB"+
// "\nTile size: " + (int) (32 * getResources().getDisplayMetrics().density)
);
}
getSupportFragmentManager().beginTransaction()
.show(currentFragment)
.commit();
} else {
getSupportFragmentManager().beginTransaction()
.hide(currentFragment)
.commit();
}
}
}
private void initPreferences() {
AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this);
AndorsTrailPreferences preferences = app.getPreferences();
preferences.read(this);
ThemeHelper.changeTheme(preferences.selectedTheme);
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
((AnimationDrawable)((ImageView)findViewById(R.id.title_logo)).getDrawable()).start();
ImageView iv = (ImageView) findViewById(R.id.ts_foreground);
int ivWidth = iv.getWidth();
int drawableWidth = iv.getDrawable().getIntrinsicWidth();
float ratio = ((float)ivWidth) / ((float)drawableWidth);
if (clouds_back != null) {
clouds_back.setScalingRatio(ratio);
}
if (clouds_mid != null) {
clouds_mid.setScalingRatio(ratio);
}
if (clouds_front != null) {
clouds_front.setScalingRatio(ratio);
}
}
}
@Override
protected void onResume() {
super.onResume();
final ImageView iv = (ImageView) findViewById(R.id.ts_foreground);
iv.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
float[] point = new float[]{0f,0.25f * iv.getDrawable().getIntrinsicHeight()};
iv.getImageMatrix().mapPoints(point);
int imgY = (int) (iv.getTop() + point[1]);
int screenHeight = getResources().getDisplayMetrics().heightPixels;
if (clouds_back != null) {
clouds_back.setYMax(imgY);
}
if (clouds_mid != null) {
clouds_mid.setYMax(imgY);
}
if (clouds_front != null) {
clouds_front.setYMax(imgY);
}
iv.getViewTreeObserver().removeOnPreDrawListener(this);
return true;
}
});
if (clouds_back != null)clouds_back.resumeAnimation();
if (clouds_mid != null)clouds_mid.resumeAnimation();
if (clouds_front != null)clouds_front.resumeAnimation();
}
@Override
protected void onPause() {
super.onPause();
if (clouds_back != null)clouds_back.pauseAnimation();
if (clouds_mid != null)clouds_mid.pauseAnimation();
if (clouds_front != null)clouds_front.pauseAnimation();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
backPressed();
return true;
} else {
return super.onKeyDown(keyCode, event);
}
}
return super.onKeyDown(keyCode, event);
}
private void backPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStack();
currentFragment = getSupportFragmentManager().findFragmentById(R.id.startscreen_fragment_container);
}
}
public void onNewGameRequested() {
if (findViewById(R.id.startscreen_fragment_container) != null) {
StartScreenActivity_NewGame newGameFragment = new StartScreenActivity_NewGame();
getSupportFragmentManager().beginTransaction()
.replace(R.id.startscreen_fragment_container, newGameFragment)
.addToBackStack(null)
.commit();
currentFragment = newGameFragment;
}
}
@Override
public void onGameCreationCancelled() {
backPressed();
}
@Override
public void onBackStackChanged() {
currentFragment = getSupportFragmentManager().findFragmentById(R.id.startscreen_fragment_container);
}
}

View File

@@ -1,490 +1,490 @@
package com.gpl.rpg.AndorsTrail.activity.fragment;
import java.util.Arrays;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.Dialogs;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.activity.ItemInfoActivity;
import com.gpl.rpg.AndorsTrail.context.ControllerContext;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.controller.ItemController;
import com.gpl.rpg.AndorsTrail.model.actor.HeroCollection;
import com.gpl.rpg.AndorsTrail.model.actor.Player;
import com.gpl.rpg.AndorsTrail.model.item.Inventory;
import com.gpl.rpg.AndorsTrail.model.item.ItemContainer;
import com.gpl.rpg.AndorsTrail.model.item.ItemType;
import com.gpl.rpg.AndorsTrail.resource.tiles.TileCollection;
import com.gpl.rpg.AndorsTrail.view.CustomMenuInflater;
import com.gpl.rpg.AndorsTrail.view.ItemContainerAdapter;
import com.gpl.rpg.AndorsTrail.view.SpinnerEmulator;
public final class HeroinfoActivity_Inventory extends Fragment implements CustomMenuInflater.MenuItemSelectedListener {
private static final int INTENTREQUEST_ITEMINFO = 3;
private static final int INTENTREQUEST_BULKSELECT_DROP = 11;
private WorldContext world;
private ControllerContext controllers;
private TileCollection wornTiles;
private Player player;
private ListView inventoryList;
private ItemContainerAdapter inventoryListAdapter;
private ItemContainerAdapter inventoryWeaponsListAdapter;
private ItemContainerAdapter inventoryArmorListAdapter;
private ItemContainerAdapter inventoryJewelryListAdapter;
private ItemContainerAdapter inventoryPotionListAdapter;
private ItemContainerAdapter inventoryFoodListAdapter;
private ItemContainerAdapter inventoryQuestListAdapter;
private ItemContainerAdapter inventoryOtherListAdapter;
private TextView heroinfo_stats_gold;
private TextView heroinfo_stats_attack;
private TextView heroinfo_stats_defense;
private ItemType lastSelectedItem; // Workaround android bug #7139
private final ImageView[] wornItemImage = new ImageView[Inventory.WearSlot.values().length];
private final int[] defaultWornItemImageResourceIDs = new int[Inventory.WearSlot.values().length];
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this.getActivity());
if (!app.isInitialized()) return;
this.world = app.getWorld();
this.controllers = app.getControllerContext();
this.player = world.model.player;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View v = inflater.inflate(R.layout.heroinfo_inventory, container, false);
AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this.getActivity());
if (!app.isInitialized()) return v;
inventoryList = (ListView) v.findViewById(R.id.inventorylist_root);
ImageView heroicon = (ImageView) v.findViewById(R.id.heroinfo_inventory_heroicon);
heroinfo_stats_gold = (TextView) v.findViewById(R.id.heroinfo_stats_gold);
heroinfo_stats_attack = (TextView) v.findViewById(R.id.heroinfo_stats_attack);
heroinfo_stats_defense = (TextView) v.findViewById(R.id.heroinfo_stats_defense);
registerForContextMenu(inventoryList);
inventoryList.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
// Move this code to separate function? -- Done
ItemType itemType = getSelectedItemType(position);
showInventoryItemInfo(itemType.id);
}
});
inventoryList.setOnItemLongClickListener(new OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
showContextMenuForItem(getSelectedItemType(position));
return true;
}
});
new SpinnerEmulator(v, R.id.inventorylist_category_filters_button, R.array.inventorylist_category_filters, R.string.heroinfo_inventory_categories) {
@Override
public void setValue(int value) {
world.model.uiSelections.selectedInventoryCategory = value;
}
@Override
public void selectionChanged(int value) {
reloadShownCategory(value);
}
@Override
public int getValue() {
return world.model.uiSelections.selectedInventoryCategory;
}
};
new SpinnerEmulator(v, R.id.inventorylist_sort_filters_button, R.array.inventorylist_sort_filters, R.string.heroinfo_inventory_sort) {
@Override
public void setValue(int value) {
world.model.uiSelections.selectedInventorySort = value;
}
@Override
public void selectionChanged(int value) {
reloadShownSort(player.inventory);
}
@Override
public int getValue() {
return world.model.uiSelections.selectedInventorySort;
}
};
ItemContainer inv = player.inventory;
wornTiles = world.tileManager.loadTilesFor(player.inventory, getResources());
inventoryListAdapter = new ItemContainerAdapter(getActivity(), world.tileManager, inv, player, wornTiles);
inventoryList.setAdapter(inventoryListAdapter);
heroicon.setImageResource(HeroCollection.getHeroLargeSprite(player.iconID));
setWearSlot(v, Inventory.WearSlot.weapon, R.id.heroinfo_worn_weapon, R.drawable.equip_weapon);
setWearSlot(v, Inventory.WearSlot.shield, R.id.heroinfo_worn_shield, R.drawable.equip_shield);
setWearSlot(v, Inventory.WearSlot.head, R.id.heroinfo_worn_head, R.drawable.equip_head);
setWearSlot(v, Inventory.WearSlot.body, R.id.heroinfo_worn_body, R.drawable.equip_body);
setWearSlot(v, Inventory.WearSlot.feet, R.id.heroinfo_worn_feet, R.drawable.equip_feet);
setWearSlot(v, Inventory.WearSlot.neck, R.id.heroinfo_worn_neck, R.drawable.equip_neck);
setWearSlot(v, Inventory.WearSlot.hand, R.id.heroinfo_worn_hand, R.drawable.equip_hand);
setWearSlot(v, Inventory.WearSlot.leftring, R.id.heroinfo_worn_ringleft, R.drawable.equip_ring);
setWearSlot(v, Inventory.WearSlot.rightring, R.id.heroinfo_worn_ringright, R.drawable.equip_ring);
return v;
}
@Override
public void onStart() {
super.onStart();
update();
}
private void setWearSlot(final View v, final Inventory.WearSlot inventorySlot, int viewId, int resourceId) {
final ImageView imageView = (ImageView) v.findViewById(viewId);
wornItemImage[inventorySlot.ordinal()] = imageView;
defaultWornItemImageResourceIDs[inventorySlot.ordinal()] = resourceId;
imageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (player.inventory.isEmptySlot(inventorySlot)) return;
imageView.setClickable(false); // Will be enabled again on update()
showEquippedItemInfo(player.inventory.getItemTypeInWearSlot(inventorySlot), inventorySlot);
}
});
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case INTENTREQUEST_ITEMINFO:
if (resultCode == ItemInfoActivity.RESULT_MORE_ACTIONS) {
showContextMenuForItem( world.itemTypes.getItemType(data.getExtras().getString("itemTypeID")));
break;
}
if (resultCode != Activity.RESULT_OK) break;
ItemType itemType = world.itemTypes.getItemType(data.getExtras().getString("itemTypeID"));
ItemInfoActivity.ItemInfoAction actionType = ItemInfoActivity.ItemInfoAction.valueOf(data.getExtras().getString("actionType"));
if (actionType == ItemInfoActivity.ItemInfoAction.unequip) {
Inventory.WearSlot slot = Inventory.WearSlot.valueOf(data.getExtras().getString("inventorySlot"));
controllers.itemController.unequipSlot(itemType, slot);
} else if (actionType == ItemInfoActivity.ItemInfoAction.equip) {
Inventory.WearSlot slot = suggestInventorySlot(itemType);
controllers.itemController.equipItem(itemType, slot);
} else if (actionType == ItemInfoActivity.ItemInfoAction.use) {
controllers.itemController.useItem(itemType);
}
break;
case INTENTREQUEST_BULKSELECT_DROP:
if (resultCode != Activity.RESULT_OK) break;
int quantity = data.getExtras().getInt("selectedAmount");
String itemTypeID = data.getExtras().getString("itemTypeID");
dropItem(itemTypeID, quantity);
break;
}
update();
}
private Inventory.WearSlot suggestInventorySlot(ItemType itemType) {
Inventory.WearSlot slot = itemType.category.inventorySlot;
if (player.inventory.isEmptySlot(slot)) return slot;
if (slot == Inventory.WearSlot.leftring) return Inventory.WearSlot.rightring;
if (itemType.isOffhandCapableWeapon()) {
ItemType mainWeapon = player.inventory.getItemTypeInWearSlot(Inventory.WearSlot.weapon);
if (mainWeapon != null && mainWeapon.isTwohandWeapon()) return slot;
else if (player.inventory.isEmptySlot(Inventory.WearSlot.shield)) return Inventory.WearSlot.shield;
}
return slot;
}
private void dropItem(String itemTypeID, int quantity) {
ItemType itemType = world.itemTypes.getItemType(itemTypeID);
controllers.itemController.dropItem(itemType, quantity);
}
private void update() {
updateTraits();
updateWorn();
updateItemList();
}
private void updateTraits() {
heroinfo_stats_gold.setText(getResources().getString(R.string.heroinfo_gold, player.inventory.gold));
StringBuilder sb = new StringBuilder(10);
ItemController.describeAttackEffect(
player.getAttackChance(),
player.getDamagePotential().current,
player.getDamagePotential().max,
player.getCriticalSkill(),
player.getCriticalMultiplier(),
sb);
heroinfo_stats_attack.setText(sb.toString());
sb = new StringBuilder(10);
ItemController.describeBlockEffect(player.getBlockChance(), player.getDamageResistance(), sb);
heroinfo_stats_defense.setText(sb.toString());
}
private void updateWorn() {
for(Inventory.WearSlot slot : Inventory.WearSlot.values()) {
updateWornImage(wornItemImage[slot.ordinal()], defaultWornItemImageResourceIDs[slot.ordinal()], player.inventory.getItemTypeInWearSlot(slot));
}
}
private void updateWornImage(ImageView imageView, int resourceIDEmptyImage, ItemType type) {
if (type != null) {
world.tileManager.setImageViewTile(getResources(), imageView, type, wornTiles);
} else {
imageView.setImageResource(resourceIDEmptyImage);
}
imageView.setClickable(true);
}
private void updateItemList() {
int currentScreen = world.model.uiSelections.selectedInventoryCategory;
if (currentScreen == 0)
inventoryListAdapter.notifyDataSetChanged();
else
reloadShownCategory(world.model.uiSelections.selectedInventoryCategory);
}
// @Override
// public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {}
// ItemType type = getSelectedItemType((AdapterContextMenuInfo) menuInfo);
public void showContextMenuForItem(ItemType type) {
MenuInflater inflater = getActivity().getMenuInflater();
Menu menu = CustomMenuInflater.newMenuInstance(getActivity());
inflater.inflate(R.menu.inventoryitem, menu);
if (type.isUsable()){
menu.findItem(R.id.inv_menu_use).setVisible(true);
menu.findItem(R.id.inv_menu_assign).setVisible(true);
}
if (type.isEquippable()) {
menu.findItem(R.id.inv_menu_equip).setVisible(true);
if (type.isOffhandCapableWeapon()) menu.findItem(R.id.inv_menu_equip_offhand).setVisible(true);
else if (type.category.inventorySlot == Inventory.WearSlot.leftring) menu.findItem(R.id.inv_menu_equip_offhand).setVisible(true);
}
lastSelectedItem = null;
CustomMenuInflater.showMenuInDialog(getActivity(), menu, world.tileManager.getDrawableForItem(getResources(), type.iconID, world.tileManager.loadTilesFor(Arrays.asList(new Integer[] { type.iconID}), getResources())), type.getName(player), type, this);
}
private ItemType getSelectedItemType(int position) {
int v = world.model.uiSelections.selectedInventoryCategory;
if (v == 0) { //All items
return inventoryListAdapter.getItem(position).itemType;
}else if (v == 1) { //Weapon items
return inventoryWeaponsListAdapter.getItem(position).itemType;
} else if (v == 2) { //Armor items
return inventoryArmorListAdapter.getItem(position).itemType;
} else if (v == 3) { //Jewelry items
return inventoryJewelryListAdapter.getItem(position).itemType;
} else if (v == 4) { //Potion items
return inventoryPotionListAdapter.getItem(position).itemType;
} else if (v == 5) { //Food items
return inventoryFoodListAdapter.getItem(position).itemType;
} else if (v == 6) { //Quest items
return inventoryQuestListAdapter.getItem(position).itemType;
} else if (v == 7) { //Other items
return inventoryOtherListAdapter.getItem(position).itemType;
}
// Better than crashing...
return inventoryListAdapter.getItem(position).itemType;
}
private ItemType getSelectedItemType(AdapterContextMenuInfo info) {
return getSelectedItemType(info.position);
}
@Override
public void onMenuItemSelected(MenuItem item, Object data) {
ItemType itemType = (ItemType) data;
switch (item.getItemId()) {
case R.id.inv_menu_info:
showInventoryItemInfo(itemType);
//context.mapController.itemInfo(this, getSelectedItemType(info));
break;
case R.id.inv_menu_drop:
String itemTypeID = itemType.id;
int quantity = player.inventory.getItemQuantity(itemTypeID);
if (quantity > 1) {
Intent intent = Dialogs.getIntentForBulkDroppingInterface(getActivity(), itemTypeID, quantity);
startActivityForResult(intent, INTENTREQUEST_BULKSELECT_DROP);
} else {
dropItem(itemTypeID, quantity);
}
break;
case R.id.inv_menu_equip:
controllers.itemController.equipItem(itemType, itemType.category.inventorySlot);
break;
case R.id.inv_menu_equip_offhand:
if (itemType.category.inventorySlot == Inventory.WearSlot.weapon) {
controllers.itemController.equipItem(itemType, Inventory.WearSlot.shield);
} else if (itemType.category.inventorySlot == Inventory.WearSlot.leftring) {
controllers.itemController.equipItem(itemType, Inventory.WearSlot.rightring);
}
break;
/*case R.id.inv_menu_unequip:
context.mapController.unequipItem(this, getSelectedItemType(info));
break;*/
case R.id.inv_menu_use:
controllers.itemController.useItem(itemType);
break;
case R.id.inv_menu_assign:
//lastSelectedItem = itemType;
break;
case R.id.inv_assign_slot1:
controllers.itemController.setQuickItem(itemType, 0);
break;
case R.id.inv_assign_slot2:
controllers.itemController.setQuickItem(itemType, 1);
break;
case R.id.inv_assign_slot3:
controllers.itemController.setQuickItem(itemType, 2);
break;
case R.id.inv_menu_movetop:
player.inventory.sortToTop(itemType.id);
break;
case R.id.inv_menu_movebottom:
player.inventory.sortToBottom(itemType.id);
break;
}
update();
}
private void showEquippedItemInfo(ItemType itemType, Inventory.WearSlot inventorySlot) {
String text;
boolean enabled = true;
if (world.model.uiSelections.isInCombat) {
int ap = world.model.player.getReequipCost();
text = getResources().getString(R.string.iteminfo_action_unequip_ap, ap);
if (ap > 0) {
enabled = world.model.player.hasAPs(ap);
}
} else {
text = getResources().getString(R.string.iteminfo_action_unequip);
}
Intent intent = Dialogs.getIntentForItemInfo(getActivity(), itemType.id, ItemInfoActivity.ItemInfoAction.unequip, text, enabled, inventorySlot);
startActivityForResult(intent, INTENTREQUEST_ITEMINFO);
}
private void showInventoryItemInfo(String itemTypeID) {
showInventoryItemInfo(world.itemTypes.getItemType(itemTypeID));
}
private void showInventoryItemInfo(ItemType itemType) {
String text = "";
int ap = 0;
boolean enabled = true;
ItemInfoActivity.ItemInfoAction action = ItemInfoActivity.ItemInfoAction.none;
final boolean isInCombat = world.model.uiSelections.isInCombat;
if (itemType.isEquippable()) {
if (isInCombat) {
ap = world.model.player.getReequipCost();
text = getResources().getString(R.string.iteminfo_action_equip_ap, ap);
} else {
text = getResources().getString(R.string.iteminfo_action_equip);
}
action = ItemInfoActivity.ItemInfoAction.equip;
} else if (itemType.isUsable()) {
if (isInCombat) {
ap = world.model.player.getUseItemCost();
text = getResources().getString(R.string.iteminfo_action_use_ap, ap);
} else {
text = getResources().getString(R.string.iteminfo_action_use);
}
action = ItemInfoActivity.ItemInfoAction.use;
}
if (isInCombat && ap > 0) {
enabled = world.model.player.hasAPs(ap);
}
Intent intent = Dialogs.getIntentForItemInfo(getActivity(), itemType.id, action, text, enabled, null);
startActivityForResult(intent, INTENTREQUEST_ITEMINFO);
}
private void reloadShownCategory(int v) { // Apologies about the code duplication,
// just didn't seem to make sense as an array, although I did create a nice array for skill category adapters.
// Decide which category to show
if (v == 0) { //All items
inventoryList.setAdapter(inventoryListAdapter);
inventoryListAdapter.notifyDataSetChanged();
} else if (v == 1) { //Weapon items
inventoryWeaponsListAdapter = new ItemContainerAdapter(getActivity(), world.tileManager, player.inventory.buildWeaponItems(), player, wornTiles);
inventoryList.setAdapter(inventoryWeaponsListAdapter);
inventoryWeaponsListAdapter.notifyDataSetChanged();
} else if (v == 2) { //Armor items
inventoryArmorListAdapter = new ItemContainerAdapter(getActivity(), world.tileManager, player.inventory.buildArmorItems(), player, wornTiles);
inventoryList.setAdapter(inventoryArmorListAdapter);
inventoryArmorListAdapter.notifyDataSetChanged();
} else if (v == 3) { //Jewelry items
inventoryJewelryListAdapter = new ItemContainerAdapter(getActivity(), world.tileManager, player.inventory.buildJewelryItems(), player, wornTiles);
inventoryList.setAdapter(inventoryJewelryListAdapter);
inventoryJewelryListAdapter.notifyDataSetChanged();
} else if (v == 4) { //Potion items
inventoryPotionListAdapter = new ItemContainerAdapter(getActivity(), world.tileManager, player.inventory.buildPotionItems(), player, wornTiles);
inventoryList.setAdapter(inventoryPotionListAdapter);
inventoryPotionListAdapter.notifyDataSetChanged();
} else if (v == 5) { //Food items
inventoryFoodListAdapter = new ItemContainerAdapter(getActivity(), world.tileManager, player.inventory.buildFoodItems(), player, wornTiles);
inventoryList.setAdapter(inventoryFoodListAdapter);
inventoryFoodListAdapter.notifyDataSetChanged();
} else if (v == 6) { //Quest items
inventoryQuestListAdapter = new ItemContainerAdapter(getActivity(), world.tileManager, player.inventory.buildQuestItems(), player, wornTiles);
inventoryList.setAdapter(inventoryQuestListAdapter);
inventoryQuestListAdapter.notifyDataSetChanged();
} else if (v == 7) { //Other items
inventoryOtherListAdapter = new ItemContainerAdapter(getActivity(), world.tileManager, player.inventory.buildOtherItems(), player, wornTiles);
inventoryList.setAdapter(inventoryOtherListAdapter);
inventoryOtherListAdapter.notifyDataSetChanged();
}
//updateItemList();
}
private void reloadShownSort(Inventory inv) {
int selected = world.model.uiSelections.selectedInventorySort;
inventoryListAdapter.reloadShownSort(selected, world.model.uiSelections.oldSortSelection, player.inventory, player);
// Currently not functional, perhaps because selection only updates when changed.
if (world.model.uiSelections.oldSortSelection == selected)
world.model.uiSelections.oldSortSelection = 0;
else world.model.uiSelections.oldSortSelection = selected;
updateItemList();
}
}
package com.gpl.rpg.AndorsTrail.activity.fragment;
import java.util.Arrays;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.Dialogs;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.activity.ItemInfoActivity;
import com.gpl.rpg.AndorsTrail.context.ControllerContext;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.controller.ItemController;
import com.gpl.rpg.AndorsTrail.model.actor.HeroCollection;
import com.gpl.rpg.AndorsTrail.model.actor.Player;
import com.gpl.rpg.AndorsTrail.model.item.Inventory;
import com.gpl.rpg.AndorsTrail.model.item.ItemContainer;
import com.gpl.rpg.AndorsTrail.model.item.ItemType;
import com.gpl.rpg.AndorsTrail.resource.tiles.TileCollection;
import com.gpl.rpg.AndorsTrail.view.CustomMenuInflater;
import com.gpl.rpg.AndorsTrail.view.ItemContainerAdapter;
import com.gpl.rpg.AndorsTrail.view.SpinnerEmulator;
public final class HeroinfoActivity_Inventory extends Fragment implements CustomMenuInflater.MenuItemSelectedListener {
private static final int INTENTREQUEST_ITEMINFO = 3;
private static final int INTENTREQUEST_BULKSELECT_DROP = 11;
private WorldContext world;
private ControllerContext controllers;
private TileCollection wornTiles;
private Player player;
private ListView inventoryList;
private ItemContainerAdapter inventoryListAdapter;
private ItemContainerAdapter inventoryWeaponsListAdapter;
private ItemContainerAdapter inventoryArmorListAdapter;
private ItemContainerAdapter inventoryJewelryListAdapter;
private ItemContainerAdapter inventoryPotionListAdapter;
private ItemContainerAdapter inventoryFoodListAdapter;
private ItemContainerAdapter inventoryQuestListAdapter;
private ItemContainerAdapter inventoryOtherListAdapter;
private TextView heroinfo_stats_gold;
private TextView heroinfo_stats_attack;
private TextView heroinfo_stats_defense;
private ItemType lastSelectedItem; // Workaround android bug #7139
private final ImageView[] wornItemImage = new ImageView[Inventory.WearSlot.values().length];
private final int[] defaultWornItemImageResourceIDs = new int[Inventory.WearSlot.values().length];
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this.getActivity());
if (!app.isInitialized()) return;
this.world = app.getWorld();
this.controllers = app.getControllerContext();
this.player = world.model.player;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View v = inflater.inflate(R.layout.heroinfo_inventory, container, false);
AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this.getActivity());
if (!app.isInitialized()) return v;
inventoryList = (ListView) v.findViewById(R.id.inventorylist_root);
ImageView heroicon = (ImageView) v.findViewById(R.id.heroinfo_inventory_heroicon);
heroinfo_stats_gold = (TextView) v.findViewById(R.id.heroinfo_stats_gold);
heroinfo_stats_attack = (TextView) v.findViewById(R.id.heroinfo_stats_attack);
heroinfo_stats_defense = (TextView) v.findViewById(R.id.heroinfo_stats_defense);
registerForContextMenu(inventoryList);
inventoryList.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
// Move this code to separate function? -- Done
ItemType itemType = getSelectedItemType(position);
showInventoryItemInfo(itemType.id);
}
});
inventoryList.setOnItemLongClickListener(new OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
showContextMenuForItem(getSelectedItemType(position));
return true;
}
});
new SpinnerEmulator(v, R.id.inventorylist_category_filters_button, R.array.inventorylist_category_filters, R.string.heroinfo_inventory_categories) {
@Override
public void setValue(int value) {
world.model.uiSelections.selectedInventoryCategory = value;
}
@Override
public void selectionChanged(int value) {
reloadShownCategory(value);
}
@Override
public int getValue() {
return world.model.uiSelections.selectedInventoryCategory;
}
};
new SpinnerEmulator(v, R.id.inventorylist_sort_filters_button, R.array.inventorylist_sort_filters, R.string.heroinfo_inventory_sort) {
@Override
public void setValue(int value) {
world.model.uiSelections.selectedInventorySort = value;
}
@Override
public void selectionChanged(int value) {
reloadShownSort(player.inventory);
}
@Override
public int getValue() {
return world.model.uiSelections.selectedInventorySort;
}
};
ItemContainer inv = player.inventory;
wornTiles = world.tileManager.loadTilesFor(player.inventory, getResources());
inventoryListAdapter = new ItemContainerAdapter(getActivity(), world.tileManager, inv, player, wornTiles);
inventoryList.setAdapter(inventoryListAdapter);
heroicon.setImageResource(HeroCollection.getHeroLargeSprite(player.iconID));
setWearSlot(v, Inventory.WearSlot.weapon, R.id.heroinfo_worn_weapon, R.drawable.equip_weapon);
setWearSlot(v, Inventory.WearSlot.shield, R.id.heroinfo_worn_shield, R.drawable.equip_shield);
setWearSlot(v, Inventory.WearSlot.head, R.id.heroinfo_worn_head, R.drawable.equip_head);
setWearSlot(v, Inventory.WearSlot.body, R.id.heroinfo_worn_body, R.drawable.equip_body);
setWearSlot(v, Inventory.WearSlot.feet, R.id.heroinfo_worn_feet, R.drawable.equip_feet);
setWearSlot(v, Inventory.WearSlot.neck, R.id.heroinfo_worn_neck, R.drawable.equip_neck);
setWearSlot(v, Inventory.WearSlot.hand, R.id.heroinfo_worn_hand, R.drawable.equip_hand);
setWearSlot(v, Inventory.WearSlot.leftring, R.id.heroinfo_worn_ringleft, R.drawable.equip_ring);
setWearSlot(v, Inventory.WearSlot.rightring, R.id.heroinfo_worn_ringright, R.drawable.equip_ring);
return v;
}
@Override
public void onStart() {
super.onStart();
update();
}
private void setWearSlot(final View v, final Inventory.WearSlot inventorySlot, int viewId, int resourceId) {
final ImageView imageView = (ImageView) v.findViewById(viewId);
wornItemImage[inventorySlot.ordinal()] = imageView;
defaultWornItemImageResourceIDs[inventorySlot.ordinal()] = resourceId;
imageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (player.inventory.isEmptySlot(inventorySlot)) return;
imageView.setClickable(false); // Will be enabled again on update()
showEquippedItemInfo(player.inventory.getItemTypeInWearSlot(inventorySlot), inventorySlot);
}
});
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case INTENTREQUEST_ITEMINFO:
if (resultCode == ItemInfoActivity.RESULT_MORE_ACTIONS) {
showContextMenuForItem( world.itemTypes.getItemType(data.getExtras().getString("itemTypeID")));
break;
}
if (resultCode != Activity.RESULT_OK) break;
ItemType itemType = world.itemTypes.getItemType(data.getExtras().getString("itemTypeID"));
ItemInfoActivity.ItemInfoAction actionType = ItemInfoActivity.ItemInfoAction.valueOf(data.getExtras().getString("actionType"));
if (actionType == ItemInfoActivity.ItemInfoAction.unequip) {
Inventory.WearSlot slot = Inventory.WearSlot.valueOf(data.getExtras().getString("inventorySlot"));
controllers.itemController.unequipSlot(itemType, slot);
} else if (actionType == ItemInfoActivity.ItemInfoAction.equip) {
Inventory.WearSlot slot = suggestInventorySlot(itemType);
controllers.itemController.equipItem(itemType, slot);
} else if (actionType == ItemInfoActivity.ItemInfoAction.use) {
controllers.itemController.useItem(itemType);
}
break;
case INTENTREQUEST_BULKSELECT_DROP:
if (resultCode != Activity.RESULT_OK) break;
int quantity = data.getExtras().getInt("selectedAmount");
String itemTypeID = data.getExtras().getString("itemTypeID");
dropItem(itemTypeID, quantity);
break;
}
update();
}
private Inventory.WearSlot suggestInventorySlot(ItemType itemType) {
Inventory.WearSlot slot = itemType.category.inventorySlot;
if (player.inventory.isEmptySlot(slot)) return slot;
if (slot == Inventory.WearSlot.leftring) return Inventory.WearSlot.rightring;
if (itemType.isOffhandCapableWeapon()) {
ItemType mainWeapon = player.inventory.getItemTypeInWearSlot(Inventory.WearSlot.weapon);
if (mainWeapon != null && mainWeapon.isTwohandWeapon()) return slot;
else if (player.inventory.isEmptySlot(Inventory.WearSlot.shield)) return Inventory.WearSlot.shield;
}
return slot;
}
private void dropItem(String itemTypeID, int quantity) {
ItemType itemType = world.itemTypes.getItemType(itemTypeID);
controllers.itemController.dropItem(itemType, quantity);
}
private void update() {
updateTraits();
updateWorn();
updateItemList();
}
private void updateTraits() {
heroinfo_stats_gold.setText(getResources().getString(R.string.heroinfo_gold, player.inventory.gold));
StringBuilder sb = new StringBuilder(10);
ItemController.describeAttackEffect(
player.getAttackChance(),
player.getDamagePotential().current,
player.getDamagePotential().max,
player.getCriticalSkill(),
player.getCriticalMultiplier(),
sb);
heroinfo_stats_attack.setText(sb.toString());
sb = new StringBuilder(10);
ItemController.describeBlockEffect(player.getBlockChance(), player.getDamageResistance(), sb);
heroinfo_stats_defense.setText(sb.toString());
}
private void updateWorn() {
for(Inventory.WearSlot slot : Inventory.WearSlot.values()) {
updateWornImage(wornItemImage[slot.ordinal()], defaultWornItemImageResourceIDs[slot.ordinal()], player.inventory.getItemTypeInWearSlot(slot));
}
}
private void updateWornImage(ImageView imageView, int resourceIDEmptyImage, ItemType type) {
if (type != null) {
world.tileManager.setImageViewTile(getResources(), imageView, type, wornTiles);
} else {
imageView.setImageResource(resourceIDEmptyImage);
}
imageView.setClickable(true);
}
private void updateItemList() {
int currentScreen = world.model.uiSelections.selectedInventoryCategory;
if (currentScreen == 0)
inventoryListAdapter.notifyDataSetChanged();
else
reloadShownCategory(world.model.uiSelections.selectedInventoryCategory);
}
// @Override
// public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {}
// ItemType type = getSelectedItemType((AdapterContextMenuInfo) menuInfo);
public void showContextMenuForItem(ItemType type) {
MenuInflater inflater = getActivity().getMenuInflater();
Menu menu = CustomMenuInflater.newMenuInstance(getActivity());
inflater.inflate(R.menu.inventoryitem, menu);
if (type.isUsable()){
menu.findItem(R.id.inv_menu_use).setVisible(true);
menu.findItem(R.id.inv_menu_assign).setVisible(true);
}
if (type.isEquippable()) {
menu.findItem(R.id.inv_menu_equip).setVisible(true);
if (type.isOffhandCapableWeapon()) menu.findItem(R.id.inv_menu_equip_offhand).setVisible(true);
else if (type.category.inventorySlot == Inventory.WearSlot.leftring) menu.findItem(R.id.inv_menu_equip_offhand).setVisible(true);
}
lastSelectedItem = null;
CustomMenuInflater.showMenuInDialog(getActivity(), menu, world.tileManager.getDrawableForItem(getResources(), type.iconID, world.tileManager.loadTilesFor(Arrays.asList(new Integer[] { type.iconID}), getResources())), type.getName(player), type, this);
}
private ItemType getSelectedItemType(int position) {
int v = world.model.uiSelections.selectedInventoryCategory;
if (v == 0) { //All items
return inventoryListAdapter.getItem(position).itemType;
}else if (v == 1) { //Weapon items
return inventoryWeaponsListAdapter.getItem(position).itemType;
} else if (v == 2) { //Armor items
return inventoryArmorListAdapter.getItem(position).itemType;
} else if (v == 3) { //Jewelry items
return inventoryJewelryListAdapter.getItem(position).itemType;
} else if (v == 4) { //Potion items
return inventoryPotionListAdapter.getItem(position).itemType;
} else if (v == 5) { //Food items
return inventoryFoodListAdapter.getItem(position).itemType;
} else if (v == 6) { //Quest items
return inventoryQuestListAdapter.getItem(position).itemType;
} else if (v == 7) { //Other items
return inventoryOtherListAdapter.getItem(position).itemType;
}
// Better than crashing...
return inventoryListAdapter.getItem(position).itemType;
}
private ItemType getSelectedItemType(AdapterContextMenuInfo info) {
return getSelectedItemType(info.position);
}
@Override
public void onMenuItemSelected(MenuItem item, Object data) {
ItemType itemType = (ItemType) data;
switch (item.getItemId()) {
case R.id.inv_menu_info:
showInventoryItemInfo(itemType);
//context.mapController.itemInfo(this, getSelectedItemType(info));
break;
case R.id.inv_menu_drop:
String itemTypeID = itemType.id;
int quantity = player.inventory.getItemQuantity(itemTypeID);
if (quantity > 1) {
Intent intent = Dialogs.getIntentForBulkDroppingInterface(getActivity(), itemTypeID, quantity);
startActivityForResult(intent, INTENTREQUEST_BULKSELECT_DROP);
} else {
dropItem(itemTypeID, quantity);
}
break;
case R.id.inv_menu_equip:
controllers.itemController.equipItem(itemType, itemType.category.inventorySlot);
break;
case R.id.inv_menu_equip_offhand:
if (itemType.category.inventorySlot == Inventory.WearSlot.weapon) {
controllers.itemController.equipItem(itemType, Inventory.WearSlot.shield);
} else if (itemType.category.inventorySlot == Inventory.WearSlot.leftring) {
controllers.itemController.equipItem(itemType, Inventory.WearSlot.rightring);
}
break;
/*case R.id.inv_menu_unequip:
context.mapController.unequipItem(this, getSelectedItemType(info));
break;*/
case R.id.inv_menu_use:
controllers.itemController.useItem(itemType);
break;
case R.id.inv_menu_assign:
//lastSelectedItem = itemType;
break;
case R.id.inv_assign_slot1:
controllers.itemController.setQuickItem(itemType, 0);
break;
case R.id.inv_assign_slot2:
controllers.itemController.setQuickItem(itemType, 1);
break;
case R.id.inv_assign_slot3:
controllers.itemController.setQuickItem(itemType, 2);
break;
case R.id.inv_menu_movetop:
player.inventory.sortToTop(itemType.id);
break;
case R.id.inv_menu_movebottom:
player.inventory.sortToBottom(itemType.id);
break;
}
update();
}
private void showEquippedItemInfo(ItemType itemType, Inventory.WearSlot inventorySlot) {
String text;
boolean enabled = true;
if (world.model.uiSelections.isInCombat) {
int ap = world.model.player.getReequipCost();
text = getResources().getString(R.string.iteminfo_action_unequip_ap, ap);
if (ap > 0) {
enabled = world.model.player.hasAPs(ap);
}
} else {
text = getResources().getString(R.string.iteminfo_action_unequip);
}
Intent intent = Dialogs.getIntentForItemInfo(getActivity(), itemType.id, ItemInfoActivity.ItemInfoAction.unequip, text, enabled, inventorySlot);
startActivityForResult(intent, INTENTREQUEST_ITEMINFO);
}
private void showInventoryItemInfo(String itemTypeID) {
showInventoryItemInfo(world.itemTypes.getItemType(itemTypeID));
}
private void showInventoryItemInfo(ItemType itemType) {
String text = "";
int ap = 0;
boolean enabled = true;
ItemInfoActivity.ItemInfoAction action = ItemInfoActivity.ItemInfoAction.none;
final boolean isInCombat = world.model.uiSelections.isInCombat;
if (itemType.isEquippable()) {
if (isInCombat) {
ap = world.model.player.getReequipCost();
text = getResources().getString(R.string.iteminfo_action_equip_ap, ap);
} else {
text = getResources().getString(R.string.iteminfo_action_equip);
}
action = ItemInfoActivity.ItemInfoAction.equip;
} else if (itemType.isUsable()) {
if (isInCombat) {
ap = world.model.player.getUseItemCost();
text = getResources().getString(R.string.iteminfo_action_use_ap, ap);
} else {
text = getResources().getString(R.string.iteminfo_action_use);
}
action = ItemInfoActivity.ItemInfoAction.use;
}
if (isInCombat && ap > 0) {
enabled = world.model.player.hasAPs(ap);
}
Intent intent = Dialogs.getIntentForItemInfo(getActivity(), itemType.id, action, text, enabled, null);
startActivityForResult(intent, INTENTREQUEST_ITEMINFO);
}
private void reloadShownCategory(int v) { // Apologies about the code duplication,
// just didn't seem to make sense as an array, although I did create a nice array for skill category adapters.
// Decide which category to show
if (v == 0) { //All items
inventoryList.setAdapter(inventoryListAdapter);
inventoryListAdapter.notifyDataSetChanged();
} else if (v == 1) { //Weapon items
inventoryWeaponsListAdapter = new ItemContainerAdapter(getActivity(), world.tileManager, player.inventory.buildWeaponItems(), player, wornTiles);
inventoryList.setAdapter(inventoryWeaponsListAdapter);
inventoryWeaponsListAdapter.notifyDataSetChanged();
} else if (v == 2) { //Armor items
inventoryArmorListAdapter = new ItemContainerAdapter(getActivity(), world.tileManager, player.inventory.buildArmorItems(), player, wornTiles);
inventoryList.setAdapter(inventoryArmorListAdapter);
inventoryArmorListAdapter.notifyDataSetChanged();
} else if (v == 3) { //Jewelry items
inventoryJewelryListAdapter = new ItemContainerAdapter(getActivity(), world.tileManager, player.inventory.buildJewelryItems(), player, wornTiles);
inventoryList.setAdapter(inventoryJewelryListAdapter);
inventoryJewelryListAdapter.notifyDataSetChanged();
} else if (v == 4) { //Potion items
inventoryPotionListAdapter = new ItemContainerAdapter(getActivity(), world.tileManager, player.inventory.buildPotionItems(), player, wornTiles);
inventoryList.setAdapter(inventoryPotionListAdapter);
inventoryPotionListAdapter.notifyDataSetChanged();
} else if (v == 5) { //Food items
inventoryFoodListAdapter = new ItemContainerAdapter(getActivity(), world.tileManager, player.inventory.buildFoodItems(), player, wornTiles);
inventoryList.setAdapter(inventoryFoodListAdapter);
inventoryFoodListAdapter.notifyDataSetChanged();
} else if (v == 6) { //Quest items
inventoryQuestListAdapter = new ItemContainerAdapter(getActivity(), world.tileManager, player.inventory.buildQuestItems(), player, wornTiles);
inventoryList.setAdapter(inventoryQuestListAdapter);
inventoryQuestListAdapter.notifyDataSetChanged();
} else if (v == 7) { //Other items
inventoryOtherListAdapter = new ItemContainerAdapter(getActivity(), world.tileManager, player.inventory.buildOtherItems(), player, wornTiles);
inventoryList.setAdapter(inventoryOtherListAdapter);
inventoryOtherListAdapter.notifyDataSetChanged();
}
//updateItemList();
}
private void reloadShownSort(Inventory inv) {
int selected = world.model.uiSelections.selectedInventorySort;
inventoryListAdapter.reloadShownSort(selected, world.model.uiSelections.oldSortSelection, player.inventory, player);
// Currently not functional, perhaps because selection only updates when changed.
if (world.model.uiSelections.oldSortSelection == selected)
world.model.uiSelections.oldSortSelection = 0;
else world.model.uiSelections.oldSortSelection = selected;
updateItemList();
}
}

View File

@@ -2,14 +2,13 @@ package com.gpl.rpg.AndorsTrail.activity.fragment;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -22,7 +21,6 @@ import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.model.actor.Player;
import com.gpl.rpg.AndorsTrail.model.quest.Quest;
import com.gpl.rpg.AndorsTrail.model.quest.QuestLogEntry;
import com.gpl.rpg.AndorsTrail.model.quest.QuestProgress;
import com.gpl.rpg.AndorsTrail.view.SpinnerEmulator;
public final class HeroinfoActivity_Quests extends Fragment {

View File

@@ -5,7 +5,7 @@ import java.util.ArrayList;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

View File

@@ -5,11 +5,7 @@ import java.util.ArrayList;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.RelativeSizeSpan;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;

View File

@@ -1,131 +1,128 @@
package com.gpl.rpg.AndorsTrail.activity.fragment;
import java.util.HashSet;
import android.content.res.Resources;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.Dialogs;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.model.actor.Monster;
import com.gpl.rpg.AndorsTrail.model.actor.Player;
import com.gpl.rpg.AndorsTrail.model.item.ItemContainer;
import com.gpl.rpg.AndorsTrail.resource.tiles.TileCollection;
import com.gpl.rpg.AndorsTrail.view.ShopItemContainerAdapter;
import com.gpl.rpg.AndorsTrail.view.SpinnerEmulator;
import com.gpl.rpg.AndorsTrail.view.ShopItemContainerAdapter.OnContainerItemClickedListener;
public abstract class ShopActivityFragment extends Fragment implements OnContainerItemClickedListener {
protected static final int INTENTREQUEST_ITEMINFO = 3;
protected static final int INTENTREQUEST_BULKSELECT = 9;
protected WorldContext world;
protected Player player;
protected ItemContainer shopInventory;
private TextView shop_gc;
private ShopItemContainerAdapter listAdapter;
private Button shoplist_sort;
protected abstract boolean isSellingInterface();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(getActivity());
if (!app.isInitialized()) return;
this.world = app.getWorld();
this.player = world.model.player;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.shoplist, container, false);
final Monster npc = Dialogs.getMonsterFromIntent(getActivity().getIntent(), world);
final Resources res = getResources();
shop_gc = (TextView) v.findViewById(R.id.shop_gc);
ListView shoplist = (ListView) v.findViewById(R.id.shop_list);
shopInventory = npc.getShopItems(player);
HashSet<Integer> iconIDs = world.tileManager.getTileIDsFor(shopInventory);
iconIDs.addAll(world.tileManager.getTileIDsFor(player.inventory));
TileCollection tiles = world.tileManager.loadTilesFor(iconIDs, res);
final boolean isSelling = isSellingInterface();
listAdapter = new ShopItemContainerAdapter(getActivity(), tiles, world.tileManager, player, isSelling ? player.inventory : shopInventory, this, isSelling);
shoplist.setAdapter(listAdapter);
//Initiating drop-down list for category filters
shoplist_sort = (Button) v.findViewById(R.id.shoplist_sort_filters);
new SpinnerEmulator(v, R.id.shoplist_sort_filters, R.array.shoplist_sort_filters, R.string.shop_item_sort) {
@Override
public void setValue(int value) {
world.model.uiSelections.selectedShopSort = value;
}
@Override
public void selectionChanged(int value) {
reloadShownSort(isSelling ? player.inventory : shopInventory);
}
@Override
public int getValue() {
return world.model.uiSelections.selectedShopSort;
}
};
return v;
}
private void reloadShownSort(ItemContainer itemContainer) {
listAdapter.reloadShownSort(world.model.uiSelections.selectedShopSort, itemContainer, player);
listAdapter.notifyDataSetChanged();
}
@Override
public void onStart() {
super.onStart();
update();
}
private Toast lastToast = null;
protected void displayStoreAction(final String msg) {
if (lastToast != null) {
lastToast.setText(msg);
} else {
lastToast = Toast.makeText(getActivity(), msg, Toast.LENGTH_SHORT);
}
lastToast.show();
update();
}
@Override
public void onPause() {
super.onPause();
lastToast = null;
}
protected void update() {
listAdapter.notifyDataSetChanged();
String gc = getResources().getString(R.string.shop_yourgold, player.getGold());
shop_gc.setText(gc);
}
}
package com.gpl.rpg.AndorsTrail.activity.fragment;
import java.util.HashSet;
import android.content.res.Resources;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.Dialogs;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.model.actor.Monster;
import com.gpl.rpg.AndorsTrail.model.actor.Player;
import com.gpl.rpg.AndorsTrail.model.item.ItemContainer;
import com.gpl.rpg.AndorsTrail.resource.tiles.TileCollection;
import com.gpl.rpg.AndorsTrail.view.ShopItemContainerAdapter;
import com.gpl.rpg.AndorsTrail.view.SpinnerEmulator;
import com.gpl.rpg.AndorsTrail.view.ShopItemContainerAdapter.OnContainerItemClickedListener;
public abstract class ShopActivityFragment extends Fragment implements OnContainerItemClickedListener {
protected static final int INTENTREQUEST_ITEMINFO = 3;
protected static final int INTENTREQUEST_BULKSELECT = 9;
protected WorldContext world;
protected Player player;
protected ItemContainer shopInventory;
private TextView shop_gc;
private ShopItemContainerAdapter listAdapter;
private Button shoplist_sort;
protected abstract boolean isSellingInterface();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(getActivity());
if (!app.isInitialized()) return;
this.world = app.getWorld();
this.player = world.model.player;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.shoplist, container, false);
final Monster npc = Dialogs.getMonsterFromIntent(getActivity().getIntent(), world);
final Resources res = getResources();
shop_gc = (TextView) v.findViewById(R.id.shop_gc);
ListView shoplist = (ListView) v.findViewById(R.id.shop_list);
shopInventory = npc.getShopItems(player);
HashSet<Integer> iconIDs = world.tileManager.getTileIDsFor(shopInventory);
iconIDs.addAll(world.tileManager.getTileIDsFor(player.inventory));
TileCollection tiles = world.tileManager.loadTilesFor(iconIDs, res);
final boolean isSelling = isSellingInterface();
listAdapter = new ShopItemContainerAdapter(getActivity(), tiles, world.tileManager, player, isSelling ? player.inventory : shopInventory, this, isSelling);
shoplist.setAdapter(listAdapter);
//Initiating drop-down list for category filters
shoplist_sort = (Button) v.findViewById(R.id.shoplist_sort_filters);
new SpinnerEmulator(v, R.id.shoplist_sort_filters, R.array.shoplist_sort_filters, R.string.shop_item_sort) {
@Override
public void setValue(int value) {
world.model.uiSelections.selectedShopSort = value;
}
@Override
public void selectionChanged(int value) {
reloadShownSort(isSelling ? player.inventory : shopInventory);
}
@Override
public int getValue() {
return world.model.uiSelections.selectedShopSort;
}
};
return v;
}
private void reloadShownSort(ItemContainer itemContainer) {
listAdapter.reloadShownSort(world.model.uiSelections.selectedShopSort, itemContainer, player);
listAdapter.notifyDataSetChanged();
}
@Override
public void onStart() {
super.onStart();
update();
}
private Toast lastToast = null;
protected void displayStoreAction(final String msg) {
if (lastToast != null) {
lastToast.setText(msg);
} else {
lastToast = Toast.makeText(getActivity(), msg, Toast.LENGTH_SHORT);
}
lastToast.show();
update();
}
@Override
public void onPause() {
super.onPause();
lastToast = null;
}
protected void update() {
listAdapter.notifyDataSetChanged();
String gc = getResources().getString(R.string.shop_yourgold, player.getGold());
shop_gc.setText(gc);
}
}

View File

@@ -1,400 +1,416 @@
package com.gpl.rpg.AndorsTrail.activity.fragment;
import android.Manifest;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.AndorsTrailPreferences;
import com.gpl.rpg.AndorsTrail.Dialogs;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.WorldSetup;
import com.gpl.rpg.AndorsTrail.activity.AboutActivity;
import com.gpl.rpg.AndorsTrail.activity.LoadingActivity;
import com.gpl.rpg.AndorsTrail.activity.Preferences;
import com.gpl.rpg.AndorsTrail.controller.Constants;
import com.gpl.rpg.AndorsTrail.resource.tiles.TileManager;
import com.gpl.rpg.AndorsTrail.savegames.Savegames;
import com.gpl.rpg.AndorsTrail.savegames.Savegames.FileHeader;
import com.gpl.rpg.AndorsTrail.util.AndroidStorage;
import com.gpl.rpg.AndorsTrail.util.L;
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory;
public class StartScreenActivity_MainMenu extends Fragment {
private static final int INTENTREQUEST_PREFERENCES = 7;
public static final int INTENTREQUEST_LOADGAME = 9;
private boolean hasExistingGame = false;
private Button startscreen_continue;
private Button startscreen_newgame;
private Button startscreen_load;
private ViewGroup save_preview_holder;
private ImageView save_preview_hero_icon;
private TextView save_preview_hero_desc;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
updatePreferences(false);
super.onCreateView(inflater, container, savedInstanceState);
if (container != null) {
container.removeAllViews();
}
View root = inflater.inflate(R.layout.startscreen_mainmenu, container, false);
save_preview_holder = (ViewGroup) root.findViewById(R.id.save_preview_holder);
save_preview_hero_icon = (ImageView) root.findViewById(R.id.save_preview_hero_icon);
save_preview_hero_desc = (TextView) root.findViewById(R.id.save_preview_hero_desc);
startscreen_continue = (Button) root.findViewById(R.id.startscreen_continue);
startscreen_continue.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
continueGame(false, Savegames.SLOT_QUICKSAVE, null);
}
});
startscreen_newgame = (Button) root.findViewById(R.id.startscreen_newgame);
startscreen_newgame.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
if (hasExistingGame) {
comfirmNewGame();
} else {
createNewGame();
}
}
});
Button b = (Button) root.findViewById(R.id.startscreen_about);
b.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
startActivity(new Intent(getActivity(), AboutActivity.class));
}
});
b = (Button) root.findViewById(R.id.startscreen_preferences);
b.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Intent intent = new Intent(getActivity(), Preferences.class);
StartScreenActivity_MainMenu.this.startActivityForResult(intent, INTENTREQUEST_PREFERENCES);
}
});
startscreen_load = (Button) root.findViewById(R.id.startscreen_load);
startscreen_load.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(getActivity());
if (hasExistingGame && app != null && app.getWorld() != null && app.getWorld().model != null
&& app.getWorld().model.statistics != null && !app.getWorld().model.statistics.hasUnlimitedSaves()) {
final Dialog d = CustomDialogFactory.createDialog(getActivity(),
getString(R.string.startscreen_load_game),
getResources().getDrawable(android.R.drawable.ic_delete),
getString(R.string.startscreen_load_game_confirm),
null,
true);
CustomDialogFactory.addButton(d, android.R.string.ok, new View.OnClickListener() {
@Override
public void onClick(View v) {
Dialogs.showLoad(StartScreenActivity_MainMenu.this);
}
});
CustomDialogFactory.addDismissButton(d, android.R.string.cancel);
CustomDialogFactory.show(d);
} else {
Dialogs.showLoad(StartScreenActivity_MainMenu.this);
}
}
});
if (AndorsTrailApplication.DEVELOPMENT_FORCE_STARTNEWGAME) {
if (AndorsTrailApplication.DEVELOPMENT_DEBUGRESOURCES) {
continueGame(true, 0, "Debug player");
} else {
continueGame(true, 0, "Player");
}
} else if (AndorsTrailApplication.DEVELOPMENT_FORCE_CONTINUEGAME) {
continueGame(false, Savegames.SLOT_QUICKSAVE, null);
}
// if it is a new version we first fire a welcome screen in onResume
// and afterwards check the permissions
if (!isNewVersion()) {
checkAndRequestPermissions(getActivity());
migrateDataOnDemand(getActivity());
}
return root;
}
@Override
public void onResume() {
super.onResume();
String playerName;
String displayInfo = null;
int iconID = TileManager.CHAR_HERO;
boolean isDead = false;
FileHeader header = Savegames.quickload(getActivity(), Savegames.SLOT_QUICKSAVE);
if (header != null && header.playerName != null) {
playerName = header.playerName;
displayInfo = header.displayInfo;
iconID = header.iconID;
isDead = header.isDead;
} else {
// Before fileversion 14 (v0.6.7), quicksave was stored in Shared preferences
SharedPreferences p = getActivity().getSharedPreferences("quicksave", Activity.MODE_PRIVATE);
playerName = p.getString("playername", null);
if (playerName != null) {
displayInfo = "level " + p.getInt("level", -1);
}
}
hasExistingGame = (playerName != null);
setButtonState(playerName, displayInfo, iconID, isDead);
if (isNewVersion()) {
Dialogs.showNewVersion(getActivity(), new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface arg0) {
setCurrentVersionForVersionCheck();
checkAndRequestPermissions(getActivity());
migrateDataOnDemand(getActivity());
boolean hasSavegames = !Savegames.getUsedSavegameSlots(getActivity()).isEmpty();
startscreen_load.setEnabled(hasSavegames);
}
});
}
boolean hasSavegames = !Savegames.getUsedSavegameSlots(getActivity()).isEmpty();
startscreen_load.setEnabled(hasSavegames);
}
@TargetApi(29)
public void migrateDataOnDemand(final Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (activity.getApplicationContext().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
if (AndroidStorage.shouldMigrateToInternalStorage(activity.getApplicationContext())) {
final Dialog d = CustomDialogFactory.createDialog(activity,
getString(R.string.startscreen_migration_title),
activity.getResources().getDrawable(android.R.drawable.ic_dialog_alert),
getString(R.string.startscreen_migration_text),
null,
true);
CustomDialogFactory.addDismissButton(d, android.R.string.ok);
d.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface arg0) {
boolean hasSavegames = !Savegames.getUsedSavegameSlots(getActivity()).isEmpty();
startscreen_load.setEnabled(hasSavegames);
}
});
CustomDialogFactory.show(d);
if (!AndroidStorage.migrateToInternalStorage(activity.getApplicationContext())) {
final Dialog errorDlg = CustomDialogFactory.createDialog(activity,
getString(R.string.startscreen_migration_title),
activity.getResources().getDrawable(android.R.drawable.ic_dialog_alert),
getString(R.string.startscreen_migration_failure),
null,
true);
CustomDialogFactory.addDismissButton(errorDlg, android.R.string.ok);
d.cancel();
CustomDialogFactory.show(errorDlg);
}
} else {
L.log("INFO: No external files or destination folder ist not empty. No data migration.");
}
} else {
L.log("INFO: No read permission on external folder. No data migration.");
}
}
}
private static final int READ_EXTERNAL_STORAGE_REQUEST=1;
private static final int WRITE_EXTERNAL_STORAGE_REQUEST=2;
@TargetApi(23)
public static void checkAndRequestPermissions(final Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
if (activity.getApplicationContext().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
activity.requestPermissions(new String[] {Manifest.permission.READ_EXTERNAL_STORAGE}, READ_EXTERNAL_STORAGE_REQUEST);
}
if (activity.getApplicationContext().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
activity.requestPermissions(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE_REQUEST);
}
}
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
listener = (OnNewGameRequestedListener) activity;
}
@Override
public void onDetach() {
super.onDetach();
listener = null;
}
private void setButtonState(final String playerName, final String displayInfo, int iconID, boolean isDead) {
startscreen_continue.setEnabled(hasExistingGame && !isDead);
startscreen_newgame.setEnabled(true);
if (hasExistingGame) {
TileManager tm = AndorsTrailApplication.getApplicationFromActivity(getActivity()).getWorld().tileManager;
tm.setImageViewTileForPlayer(getResources(), save_preview_hero_icon, iconID);
save_preview_hero_desc.setText((isDead ? getString(R.string.rip_startscreen) : "") + playerName + ", " + displayInfo);
save_preview_holder.setVisibility(View.VISIBLE);
} else {
save_preview_holder.setVisibility(View.GONE);
}
}
private void continueGame(boolean createNewCharacter, int loadFromSlot, String name) {
final WorldSetup setup = AndorsTrailApplication.getApplicationFromActivity(getActivity()).getWorldSetup();
setup.createNewCharacter = createNewCharacter;
setup.loadFromSlot = loadFromSlot;
setup.newHeroName = name;
startActivity(new Intent(getActivity(), LoadingActivity.class));
}
private void comfirmNewGame() {
// new AlertDialog.Builder(new ContextThemeWrapper(getActivity(), R.style.AndorsTrailStyle_Dialog))
// .setTitle(R.string.startscreen_newgame)
// .setMessage(R.string.startscreen_newgame_confirm)
// .setIcon(android.R.drawable.ic_delete)
// .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
// @Override
// public void onClick(DialogInterface dialog, int which) {
// //continueGame(true);
//// hasExistingGame = false;
//// setButtonState(null, null, 0);
// createNewGame();
// }
// })
// .setNegativeButton(android.R.string.cancel, null)
// .create().show();
//
//
final Dialog d = CustomDialogFactory.createDialog(getActivity(),
getString(R.string.startscreen_newgame),
getResources().getDrawable(android.R.drawable.ic_delete),
getResources().getString(R.string.startscreen_newgame_confirm),
null,
true);
CustomDialogFactory.addButton(d, android.R.string.ok, new View.OnClickListener() {
@Override
public void onClick(View v) {
createNewGame();
}
});
CustomDialogFactory.addDismissButton(d, android.R.string.cancel);
CustomDialogFactory.show(d);
}
private static final String versionCheck = "lastversion";
private boolean isNewVersion() {
SharedPreferences s = getActivity().getSharedPreferences(Constants.PREFERENCE_MODEL_LASTRUNVERSION, Activity.MODE_PRIVATE);
int lastversion = s.getInt(versionCheck, 0);
if (lastversion >= AndorsTrailApplication.CURRENT_VERSION) return false;
return true;
}
private void setCurrentVersionForVersionCheck() {
SharedPreferences s = getActivity().getSharedPreferences(Constants.PREFERENCE_MODEL_LASTRUNVERSION, Activity.MODE_PRIVATE);
Editor e = s.edit();
e.putInt(versionCheck, AndorsTrailApplication.CURRENT_VERSION);
e.commit();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case INTENTREQUEST_LOADGAME:
if (resultCode != Activity.RESULT_OK) break;
final int slot = data.getIntExtra("slot", 1);
continueGame(false, slot, null);
break;
case INTENTREQUEST_PREFERENCES:
updatePreferences(true);
break;
}
}
private void updatePreferences(boolean alreadyStartedLoadingResources) {
AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(getActivity());
AndorsTrailPreferences preferences = app.getPreferences();
preferences.read(getActivity());
if (app.setLocale(getActivity())) {
if (alreadyStartedLoadingResources) {
// Changing the locale after having loaded the game requires resources to
// be re-loaded. Therefore, we just exit here.
Toast.makeText(getActivity(), R.string.change_locale_requires_restart, Toast.LENGTH_LONG).show();
doFinish();
return;
}
}
if (ThemeHelper.changeTheme(preferences.selectedTheme)) {
// Changing the theme requires a restart to re-create all activities.
Toast.makeText(getActivity(), R.string.change_theme_requires_restart, Toast.LENGTH_LONG).show();
doFinish();
return;
}
app.getWorld().tileManager.updatePreferences(preferences);
}
@SuppressLint("NewApi")
private void doFinish() {
//For Lollipop and above
((AndorsTrailApplication)getActivity().getApplication()).discardWorld();
getActivity().finish();
}
public interface OnNewGameRequestedListener {
public void onNewGameRequested();
}
private OnNewGameRequestedListener listener = null;
private void createNewGame() {
if (listener != null) {
listener.onNewGameRequested();
}
}
}
package com.gpl.rpg.AndorsTrail.activity.fragment;
import android.Manifest;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.AndorsTrailPreferences;
import com.gpl.rpg.AndorsTrail.Dialogs;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.WorldSetup;
import com.gpl.rpg.AndorsTrail.activity.AboutActivity;
import com.gpl.rpg.AndorsTrail.activity.LoadingActivity;
import com.gpl.rpg.AndorsTrail.activity.Preferences;
import com.gpl.rpg.AndorsTrail.controller.Constants;
import com.gpl.rpg.AndorsTrail.resource.tiles.TileManager;
import com.gpl.rpg.AndorsTrail.savegames.Savegames;
import com.gpl.rpg.AndorsTrail.savegames.Savegames.FileHeader;
import com.gpl.rpg.AndorsTrail.util.AndroidStorage;
import com.gpl.rpg.AndorsTrail.util.L;
import com.gpl.rpg.AndorsTrail.util.ThemeHelper;
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory;
import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory.CustomDialog;
public class StartScreenActivity_MainMenu extends Fragment {
private static final int INTENTREQUEST_PREFERENCES = 7;
public static final int INTENTREQUEST_LOADGAME = 9;
private boolean hasExistingGame = false;
private Button startscreen_continue;
private Button startscreen_newgame;
private Button startscreen_load;
private ViewGroup save_preview_holder;
private ImageView save_preview_hero_icon;
private TextView save_preview_hero_desc;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
updatePreferences(false);
super.onCreateView(inflater, container, savedInstanceState);
if (container != null) {
container.removeAllViews();
}
View root = inflater.inflate(R.layout.startscreen_mainmenu, container, false);
save_preview_holder = (ViewGroup) root.findViewById(R.id.save_preview_holder);
save_preview_hero_icon = (ImageView) root.findViewById(R.id.save_preview_hero_icon);
save_preview_hero_desc = (TextView) root.findViewById(R.id.save_preview_hero_desc);
startscreen_continue = (Button) root.findViewById(R.id.startscreen_continue);
startscreen_continue.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
continueGame(false, Savegames.SLOT_QUICKSAVE, null);
}
});
startscreen_newgame = (Button) root.findViewById(R.id.startscreen_newgame);
startscreen_newgame.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
if (hasExistingGame) {
comfirmNewGame();
} else {
createNewGame();
}
}
});
Button b = (Button) root.findViewById(R.id.startscreen_about);
b.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
startActivity(new Intent(getActivity(), AboutActivity.class));
}
});
b = (Button) root.findViewById(R.id.startscreen_preferences);
b.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Intent intent = new Intent(getActivity(), Preferences.class);
StartScreenActivity_MainMenu.this.startActivityForResult(intent, INTENTREQUEST_PREFERENCES);
}
});
startscreen_load = (Button) root.findViewById(R.id.startscreen_load);
startscreen_load.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(getActivity());
if (hasExistingGame && app != null && app.getWorld() != null && app.getWorld().model != null
&& app.getWorld().model.statistics != null && !app.getWorld().model.statistics.hasUnlimitedSaves()) {
final CustomDialog d = CustomDialogFactory.createDialog(getActivity(),
getString(R.string.startscreen_load_game),
getResources().getDrawable(android.R.drawable.ic_delete),
getString(R.string.startscreen_load_game_confirm),
null,
true);
CustomDialogFactory.addButton(d, android.R.string.ok, new View.OnClickListener() {
@Override
public void onClick(View v) {
Dialogs.showLoad(StartScreenActivity_MainMenu.this);
}
});
CustomDialogFactory.addDismissButton(d, android.R.string.cancel);
CustomDialogFactory.show(d);
} else {
Dialogs.showLoad(StartScreenActivity_MainMenu.this);
}
}
});
if (AndorsTrailApplication.DEVELOPMENT_FORCE_STARTNEWGAME) {
if (AndorsTrailApplication.DEVELOPMENT_DEBUGRESOURCES) {
continueGame(true, 0, "Debug player");
} else {
continueGame(true, 0, "Player");
}
} else if (AndorsTrailApplication.DEVELOPMENT_FORCE_CONTINUEGAME) {
continueGame(false, Savegames.SLOT_QUICKSAVE, null);
}
// if it is a new version we first fire a welcome screen in onResume
// and afterwards check the permissions
if (!isNewVersion()) {
checkAndRequestPermissions(getActivity());
migrateDataOnDemand(getActivity());
}
return root;
}
@Override
public void onResume() {
super.onResume();
String playerName;
String displayInfo = null;
int iconID = TileManager.CHAR_HERO;
boolean isDead = false;
FileHeader header = Savegames.quickload(getActivity(), Savegames.SLOT_QUICKSAVE);
if (header != null && header.playerName != null) {
playerName = header.playerName;
displayInfo = header.displayInfo;
iconID = header.iconID;
isDead = header.isDead;
} else {
// Before fileversion 14 (v0.6.7), quicksave was stored in Shared preferences
SharedPreferences p = getActivity().getSharedPreferences("quicksave", Activity.MODE_PRIVATE);
playerName = p.getString("playername", null);
if (playerName != null) {
displayInfo = "level " + p.getInt("level", -1);
}
}
hasExistingGame = (playerName != null);
setButtonState(playerName, displayInfo, iconID, isDead);
if (isNewVersion()) {
Dialogs.showNewVersion(getActivity(), new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface arg0) {
setCurrentVersionForVersionCheck();
checkAndRequestPermissions(getActivity());
migrateDataOnDemand(getActivity());
}
});
}
}
@TargetApi(29)
public void migrateDataOnDemand(final Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (activity.getApplicationContext().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
if (AndroidStorage.shouldMigrateToInternalStorage(activity.getApplicationContext())) {
final CustomDialog d = CustomDialogFactory.createDialog(activity,
getString(R.string.startscreen_migration_title),
activity.getResources().getDrawable(android.R.drawable.ic_dialog_alert),
getString(R.string.startscreen_migration_text),
null,
true);
CustomDialogFactory.addDismissButton(d, android.R.string.ok);
CustomDialogFactory.show(d);
if (!AndroidStorage.migrateToInternalStorage(activity.getApplicationContext())) {
final CustomDialog errorDlg = CustomDialogFactory.createDialog(activity,
getString(R.string.startscreen_migration_title),
activity.getResources().getDrawable(android.R.drawable.ic_dialog_alert),
getString(R.string.startscreen_migration_failure),
null,
true);
CustomDialogFactory.addDismissButton(errorDlg, android.R.string.ok);
d.cancel();
CustomDialogFactory.show(errorDlg);
}
} else {
L.log("INFO: No external files or destination folder ist not empty. No data migration.");
}
} else {
L.log("INFO: No read permission on external folder. No data migration.");
}
}
}
private static final int READ_EXTERNAL_STORAGE_REQUEST=1;
private static final int WRITE_EXTERNAL_STORAGE_REQUEST=2;
@TargetApi(23)
public static void checkAndRequestPermissions(final Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
if (activity.getApplicationContext().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
activity.requestPermissions(new String[] {Manifest.permission.READ_EXTERNAL_STORAGE}, READ_EXTERNAL_STORAGE_REQUEST);
}
if (activity.getApplicationContext().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
activity.requestPermissions(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE_REQUEST);
}
}
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
listener = (OnNewGameRequestedListener) activity;
}
@Override
public void onDetach() {
super.onDetach();
listener = null;
}
private void setButtonState(final String playerName, final String displayInfo, int iconID, boolean isDead) {
startscreen_continue.setEnabled(hasExistingGame && !isDead);
startscreen_newgame.setEnabled(true);
if (hasExistingGame) {
TileManager tm = AndorsTrailApplication.getApplicationFromActivity(getActivity()).getWorld().tileManager;
tm.setImageViewTileForPlayer(getResources(), save_preview_hero_icon, iconID);
save_preview_hero_desc.setText((isDead ? getString(R.string.rip_startscreen) : "") + playerName + ", " + displayInfo);
save_preview_holder.setVisibility(View.VISIBLE);
} else {
save_preview_holder.setVisibility(View.GONE);
}
}
private void continueGame(boolean createNewCharacter, int loadFromSlot, String name) {
final WorldSetup setup = AndorsTrailApplication.getApplicationFromActivity(getActivity()).getWorldSetup();
setup.createNewCharacter = createNewCharacter;
setup.loadFromSlot = loadFromSlot;
setup.newHeroName = name;
startActivity(new Intent(getActivity(), LoadingActivity.class));
}
private void comfirmNewGame() {
// new AlertDialog.Builder(new ContextThemeWrapper(getActivity(), R.style.AndorsTrailStyle_Dialog))
// .setTitle(R.string.startscreen_newgame)
// .setMessage(R.string.startscreen_newgame_confirm)
// .setIcon(android.R.drawable.ic_delete)
// .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
// @Override
// public void onClick(DialogInterface dialog, int which) {
// //continueGame(true);
//// hasExistingGame = false;
//// setButtonState(null, null, 0);
// createNewGame();
// }
// })
// .setNegativeButton(android.R.string.cancel, null)
// .create().show();
//
//
final CustomDialog d = CustomDialogFactory.createDialog(getActivity(),
getString(R.string.startscreen_newgame),
getResources().getDrawable(android.R.drawable.ic_delete),
getResources().getString(R.string.startscreen_newgame_confirm),
null,
true);
CustomDialogFactory.addButton(d, android.R.string.ok, new View.OnClickListener() {
@Override
public void onClick(View v) {
createNewGame();
}
});
CustomDialogFactory.addDismissButton(d, android.R.string.cancel);
CustomDialogFactory.show(d);
}
private static final String versionCheck = "lastversion";
private boolean isNewVersion() {
SharedPreferences s = getActivity().getSharedPreferences(Constants.PREFERENCE_MODEL_LASTRUNVERSION, Activity.MODE_PRIVATE);
int lastversion = s.getInt(versionCheck, 0);
if (lastversion >= AndorsTrailApplication.CURRENT_VERSION) return false;
return true;
}
private void setCurrentVersionForVersionCheck() {
SharedPreferences s = getActivity().getSharedPreferences(Constants.PREFERENCE_MODEL_LASTRUNVERSION, Activity.MODE_PRIVATE);
Editor e = s.edit();
e.putInt(versionCheck, AndorsTrailApplication.CURRENT_VERSION);
e.commit();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case INTENTREQUEST_LOADGAME:
boolean unsuccessful = resultCode != Activity.RESULT_OK;
if(data == null) break;
final boolean wasImportOrExport = data.getBooleanExtra("import_export", false);
if (wasImportOrExport) {
String message = getImportExportMessage(!unsuccessful, data);
Toast.makeText(getActivity(), message, Toast.LENGTH_LONG).show();
break;
}
if (unsuccessful) break;
final int slot = data.getIntExtra("slot", 1);
continueGame(false, slot, null);
break;
case INTENTREQUEST_PREFERENCES:
updatePreferences(true);
break;
}
}
private String getImportExportMessage(boolean successful, Intent data) {
String message = "";
boolean isImportWorldmap = data.getBooleanExtra("import_worldmap", false);
boolean isImportSaves = data.getBooleanExtra("import_savegames", false);
boolean isExport = data.getBooleanExtra("export", false);
if(isImportWorldmap) {
message = getString(successful ? R.string.loadsave_import_worldmap_successfull : R.string.loadsave_import_worldmap_unsuccessfull);
} else if(isImportSaves) {
message = getString(successful ? R.string.loadsave_import_save_successfull : R.string.loadsave_import_save_unsuccessfull);
} else if(isExport) {
message = getString(successful ? R.string.loadsave_export_successfull : R.string.loadsave_export_unsuccessfull);
}
return message;
}
private void updatePreferences(boolean alreadyStartedLoadingResources) {
AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(getActivity());
AndorsTrailPreferences preferences = app.getPreferences();
preferences.read(getActivity());
if (app.setLocale(getActivity())) {
if (alreadyStartedLoadingResources) {
// Changing the locale after having loaded the game requires resources to
// be re-loaded. Therefore, we just exit here.
Toast.makeText(getActivity(), R.string.change_locale_requires_restart, Toast.LENGTH_LONG).show();
doFinish();
return;
}
}
if (ThemeHelper.changeTheme(preferences.selectedTheme)) {
// Changing the theme requires a restart to re-create all activities.
Toast.makeText(getActivity(), R.string.change_theme_requires_restart, Toast.LENGTH_LONG).show();
doFinish();
return;
}
app.getWorld().tileManager.updatePreferences(preferences);
}
@SuppressLint("NewApi")
private void doFinish() {
//For Lollipop and above
((AndorsTrailApplication) getActivity().getApplication()).discardWorld();
getActivity().finish();
}
public interface OnNewGameRequestedListener {
public void onNewGameRequested();
}
private OnNewGameRequestedListener listener = null;
private void createNewGame() {
if (listener != null) {
listener.onNewGameRequested();
}
}
}

View File

@@ -3,7 +3,7 @@ package com.gpl.rpg.AndorsTrail.activity.fragment;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;

View File

@@ -238,7 +238,7 @@ public final class CombatController implements VisualEffectCompletedCallback {
controllers.actorStatsController.addActorAP(player, player.getSkillLevel(SkillCollection.SkillID.cleave) * SkillCollection.PER_SKILLPOINT_INCREASE_CLEAVE_AP);
controllers.actorStatsController.addActorHealth(player, player.getSkillLevel(SkillCollection.SkillID.eater) * SkillCollection.PER_SKILLPOINT_INCREASE_EATER_HEALTH);
world.model.statistics.addMonsterKill(killedMonster.getMonsterTypeID());
world.model.statistics.addMonsterKill(killedMonster.monsterType);
controllers.actorStatsController.addExperience(loot.exp);
world.model.combatLog.append(controllers.getResources().getString(R.string.dialog_monsterloot_gainedexp, loot.exp));
@@ -579,6 +579,13 @@ public final class CombatController implements VisualEffectCompletedCallback {
private static final int n = 50;
private static final int F = 40;
private static final float two_divided_by_PI = (float) (2f / Math.PI);
/**
* @implNote
* formula: 50 * (1 + (2 / pi) * atan((attackChance - blockChance - n) / F))
* <br/>
* n = {@value n}; F = {@value F}
* @return [0..100] . 100 == always hit.
*/
private static int getAttackHitChance(final Actor attacker, final Actor target) {
final int c = attacker.getAttackChance() - target.getBlockChance();
// (2/pi)*atan(..) will vary from -1 to +1 .

View File

@@ -7,7 +7,7 @@ import com.gpl.rpg.AndorsTrail.util.ConstRange;
import com.gpl.rpg.AndorsTrail.util.Range;
public final class Constants {
public static final int PERCENT_EXP_LOST_WHEN_DIED = 30;
public static final int PERCENT_EXP_LOST_WHEN_DIED = 20;
public static final int LEVELUP_EFFECT_HEALTH = 5;
public static final int LEVELUP_EFFECT_ATK_CH = 5;
public static final int LEVELUP_EFFECT_ATK_DMG = 1;
@@ -23,8 +23,8 @@ public final class Constants {
public static final long MINIMUM_INPUT_INTERVAL_STD = 200;
//TODO restore final modifier before release
public static long MINIMUM_INPUT_INTERVAL = AndorsTrailApplication.DEVELOPMENT_FASTSPEED ? MINIMUM_INPUT_INTERVAL_FAST : MINIMUM_INPUT_INTERVAL_STD;
public static final int MAX_MAP_WIDTH = 33;
public static final int MAX_MAP_HEIGHT = 33;
public static final int MAX_MAP_WIDTH = 46;
public static final int MAX_MAP_HEIGHT = 46;
public static final int MONSTER_MOVEMENT_TURN_DURATION_MS = 1200;
public static final int MONSTER_IMMOBILE_MOVE_COST = 999;
@@ -51,6 +51,10 @@ public final class Constants {
public static final String CHEAT_DETECTION_FOLDER = "dEAGyGE3YojqXjI3x4x7";
public static final String PASSIVE_ACHIEVEMENT_CHECK_PHRASE = "passive_achievement_check";
public static final String SAVEGAME_FILE_MIME_TYPE = "application/octet-stream";
public static final String WORLDMAP_FILE_MIME_TYPE = "image/png";
public static final String NO_FILE_EXTENSION_MIME_TYPE = "application/no_file_extension_mime_type";
public static final Random rnd = new Random();
public static int rollValue(final ConstRange r) { return rollValue(r.max, r.current); }
public static int rollValue(final ConstRange r, int bias) { return rollValue((r.max + 1) * 100 -1, r.current * 100 + bias)/100; }

View File

@@ -22,6 +22,7 @@ import com.gpl.rpg.AndorsTrail.model.conversation.Reply;
import com.gpl.rpg.AndorsTrail.model.item.ItemTypeCollection;
import com.gpl.rpg.AndorsTrail.model.item.Loot;
import com.gpl.rpg.AndorsTrail.model.map.LayeredTileMap;
import com.gpl.rpg.AndorsTrail.model.map.MapObject;
import com.gpl.rpg.AndorsTrail.model.map.MonsterSpawnArea;
import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap;
import com.gpl.rpg.AndorsTrail.model.quest.QuestLogEntry;
@@ -124,6 +125,9 @@ public final class ConversationController {
case changeMapFilter:
changeMapFilter(res, effect.mapName, effect.effectID);
break;
case mapchange:
mapchange(effect.mapName, effect.effectID);
break;
}
}
@@ -172,6 +176,13 @@ public final class ConversationController {
}
}
private void mapchange(String mapName, String place) {
PredefinedMap map = findMapForScriptEffect(mapName);
// controllers.mapController.activateMapObjectGroup(map, mapObjectGroupID);
// controllerContext.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, effect.mapName, effect.effectID, 0, 0); //cbcbcb check
controllers.movementController.placePlayerAsyncAt(MapObject.MapObjectType.newmap, mapName, place, 0, 0);
}
private void addAlignmentReward(Player player, String faction, int delta) {
player.addAlignment(faction, delta);
MovementController.refreshMonsterAggressiveness(world.model.currentMaps.map, world.model.player);
@@ -311,6 +322,18 @@ public final class ConversationController {
case factionScoreEquals:
result = player.getAlignment(requirement.requireID) == requirement.value;
break;
case date:
result = world.model.worldData.getDate(requirement.requireID) >= requirement.value;
break;
case dateEquals:
result = world.model.worldData.getDate(requirement.requireID) == requirement.value;
break;
case time:
result = world.model.worldData.getTime(requirement.requireID) >= requirement.value;
break;
case timeEquals:
result = world.model.worldData.getTime(requirement.requireID) == requirement.value;
break;
default:
result = true;
}

View File

@@ -0,0 +1,342 @@
package com.gpl.rpg.AndorsTrail.controller;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.util.SparseIntArray;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import com.gpl.rpg.AndorsTrail.activity.HeroinfoActivity;
import com.gpl.rpg.AndorsTrail.context.ControllerContext;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.util.Coord;
import com.gpl.rpg.AndorsTrail.util.L;
public final class InputController implements OnClickListener, OnLongClickListener{
private final ControllerContext controllers;
private final WorldContext world;
private final Coord lastTouchPosition_tileCoords = new Coord();
private int lastTouchPosition_dx = 0;
private int lastTouchPosition_dy = 0;
private long lastTouchEventTime = 0;
private boolean isDpadActive = false;
private int keyState_dx = 0;
private int keyState_dy = 0;
private boolean keyState_attack = false;
private boolean keyState_flee = false;
private boolean keyState_endturn = false;
final private int KEY_UNHANDLED = 0; // Default, for unhandled keycodes
final private int KEY_MOVE_UP = 1;
final private int KEY_MOVE_DOWN = 2;
final private int KEY_MOVE_LEFT = 3;
final private int KEY_MOVE_RIGHT = 4;
final private int KEY_MOVE_UP_LEFT = 5;
final private int KEY_MOVE_UP_RIGHT = 6;
final private int KEY_MOVE_DOWN_LEFT = 7;
final private int KEY_MOVE_DOWN_RIGHT = 8;
final private int KEY_ATTACK = 9;
final private int KEY_FLEE = 10;
final private int KEY_END_TURN = 11;
final private int KEY_HERO_INFO = 12;
final private int KEY_TOOLBOX = 13;
private SparseIntArray keyMap = new SparseIntArray(); // Android keycode to internal key event mapping. TODO: Configure via preferences
public InputController(ControllerContext controllers, WorldContext world) {
this.controllers = controllers;
this.world = world;
initializeKeyMap();
}
/* New keyboard handler. Both Key Down and Key Up events handled here to allow conditional behaviours.
On 4-way dpad controllers, cursor keys, and WASD, diagonals are generated by chording two keys.
Single-key diagonals are supported on numeric keypad and 8-way dpads (not seen/tested in the wild).
Because two-key combos initially generate a ordinal movement (one key comes in first), which can
be dangerous in tight spaces, modifiers are provided to "lock" the input until both keys are down.
TODO: Use delay timer to enable chorded diagonals on first move without locking kludge?
*/
// Map key codes to spectic internal actions
// TODO: Move mapping out of code to JSON/XML file, or maybe player prefs
private void initializeKeyMap() {
int key;
// Keys mapping to UP
key = KEY_MOVE_UP;
keyMap.put(KeyEvent.KEYCODE_DPAD_UP, key);
keyMap.put(KeyEvent.KEYCODE_NUMPAD_8, key);
keyMap.put(KeyEvent.KEYCODE_8, key);
keyMap.put(KeyEvent.KEYCODE_W, key);
// Keys mapping to DOWN
key = KEY_MOVE_DOWN;
keyMap.put(KeyEvent.KEYCODE_DPAD_DOWN, key);
keyMap.put(KeyEvent.KEYCODE_NUMPAD_2, key);
keyMap.put(KeyEvent.KEYCODE_2, key);
keyMap.put(KeyEvent.KEYCODE_S, key);
// Keys mapping to LEFT
key = KEY_MOVE_LEFT;
keyMap.put(KeyEvent.KEYCODE_DPAD_LEFT, key);
keyMap.put(KeyEvent.KEYCODE_NUMPAD_4, key);
keyMap.put(KeyEvent.KEYCODE_4, key);
keyMap.put(KeyEvent.KEYCODE_A, key);
// Keys mapping to RIGHT
key = KEY_MOVE_RIGHT;
keyMap.put(KeyEvent.KEYCODE_DPAD_RIGHT, key);
keyMap.put(KeyEvent.KEYCODE_NUMPAD_6, key);
keyMap.put(KeyEvent.KEYCODE_6, key);
keyMap.put(KeyEvent.KEYCODE_D, key);
// Keys mapping to UP_LEFT
key = KEY_MOVE_UP_LEFT;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
keyMap.put(KeyEvent.KEYCODE_DPAD_UP_LEFT, key);
}
keyMap.put(KeyEvent.KEYCODE_NUMPAD_7, key);
keyMap.put(KeyEvent.KEYCODE_7, key);
keyMap.put(KeyEvent.KEYCODE_MOVE_HOME, key);
// Keys mapping to UP_RIGHT
key = KEY_MOVE_UP_RIGHT;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
keyMap.put(KeyEvent.KEYCODE_DPAD_UP_RIGHT, key);
}
keyMap.put(KeyEvent.KEYCODE_NUMPAD_9, key);
keyMap.put(KeyEvent.KEYCODE_9, key);
keyMap.put(KeyEvent.KEYCODE_PAGE_UP, key);
// Keys mapping to DOWN_LEFT
key = KEY_MOVE_DOWN_LEFT;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
keyMap.put(KeyEvent.KEYCODE_DPAD_DOWN_LEFT, key);
}
keyMap.put(KeyEvent.KEYCODE_NUMPAD_1, key);
keyMap.put(KeyEvent.KEYCODE_1, key);
keyMap.put(KeyEvent.KEYCODE_MOVE_END, key);
// Keys mapping to DOWN_RIGHT
key = KEY_MOVE_DOWN_RIGHT;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
keyMap.put(KeyEvent.KEYCODE_DPAD_DOWN_RIGHT, key);
}
keyMap.put(KeyEvent.KEYCODE_NUMPAD_3, key);
keyMap.put(KeyEvent.KEYCODE_3, key);
keyMap.put(KeyEvent.KEYCODE_PAGE_DOWN, key);
// Keys mapping to ATTACK
key = KEY_ATTACK;
keyMap.put(KeyEvent.KEYCODE_DPAD_CENTER, key);
keyMap.put(KeyEvent.KEYCODE_BUTTON_A, key);
keyMap.put(KeyEvent.KEYCODE_SPACE, key);
keyMap.put(KeyEvent.KEYCODE_NUMPAD_5, key);
// Keys mapping to FLEE
key = KEY_FLEE;
keyMap.put(KeyEvent.KEYCODE_BUTTON_X, key);
keyMap.put(KeyEvent.KEYCODE_F, key);
keyMap.put(KeyEvent.KEYCODE_NUMPAD_ENTER, key);
keyMap.put(KeyEvent.KEYCODE_ENTER, key);
// Keys mapping to END_TURN
key = KEY_END_TURN;
keyMap.put(KeyEvent.KEYCODE_BUTTON_Y, key);
keyMap.put(KeyEvent.KEYCODE_E, key);
keyMap.put(KeyEvent.KEYCODE_FORWARD_DEL, key);
keyMap.put(KeyEvent.KEYCODE_NUMPAD_DOT, key);
// Keys mapping to HERO_INFO
key = KEY_HERO_INFO;
//keyMap.put(KeyEvent.KEYCODE_BUTTON_SELECT, key);
keyMap.put(KeyEvent.KEYCODE_BUTTON_L1, key);
keyMap.put(KeyEvent.KEYCODE_NUM_LOCK, key);
keyMap.put(KeyEvent.KEYCODE_C, key);
// Keys mapping to TOOLBOX
key = KEY_TOOLBOX;
keyMap.put(KeyEvent.KEYCODE_BUTTON_R1, key);
keyMap.put(KeyEvent.KEYCODE_NUMPAD_DIVIDE, key);
keyMap.put(KeyEvent.KEYCODE_B, key);
}
// Generate game actions based on mapped keys
public boolean onKeyboardAction(Context context, KeyEvent event, boolean acceptInput) {
//L.log("onKeyboardAction(): Processing action " + event.getAction() + " for keyCode " + event.getKeyCode());
if (event.getAction() != KeyEvent.ACTION_DOWN && event.getAction() != KeyEvent.ACTION_UP) return false; // don't handle other actions
boolean keydown = (event.getAction() == KeyEvent.ACTION_DOWN);
boolean inihbit = (keyState_attack || keyState_flee); // used to inhibit movement if an action key is held down
switch (keyMap.get(event.getKeyCode())) {
// Ordinal directional keys - only modify one direction register; registers are combined when
// keys used simultaneously to create synthetic diagonals
case KEY_MOVE_UP:
keyState_dy = keydown ? -1 : 0;
if (acceptInput && !inihbit) onRelativeMovement(keyState_dx, keyState_dy);
break;
case KEY_MOVE_DOWN:
keyState_dy = keydown ? 1 : 0;
if (acceptInput && !inihbit) onRelativeMovement(keyState_dx, keyState_dy);
break;
case KEY_MOVE_LEFT:
keyState_dx = keydown ? -1 : 0;
if (acceptInput && !inihbit) onRelativeMovement(keyState_dx, keyState_dy);
break;
case KEY_MOVE_RIGHT:
keyState_dx = keydown ? 1 : 0;
if (acceptInput && !inihbit) onRelativeMovement(keyState_dx, keyState_dy);
break;
// Diagonal directional keys. Modify both direction registers, can't be combined
// TODO: store individual key position to allow combinations. May not be worth the trouble.
case KEY_MOVE_UP_LEFT:
keyState_dx = keydown ? -1 : 0;
keyState_dy = keydown ? -1 : 0;
if (acceptInput && !inihbit) onRelativeMovement(keyState_dx, keyState_dy);
break;
case KEY_MOVE_UP_RIGHT:
keyState_dx = keydown ? 1 : 0;
keyState_dy = keydown ? -1 : 0;
if (acceptInput && !inihbit) onRelativeMovement(keyState_dx, keyState_dy);
break;
case KEY_MOVE_DOWN_LEFT:
keyState_dx = keydown ? -1 : 0;
keyState_dy = keydown ? 1 : 0;
if (acceptInput && !inihbit) onRelativeMovement(keyState_dx, keyState_dy);
break;
case KEY_MOVE_DOWN_RIGHT:
keyState_dx = keydown ? 1 : 0;
keyState_dy = keydown ? 1 : 0;
if (acceptInput && !inihbit) onRelativeMovement(keyState_dx, keyState_dy);
break;
// Special key handling below - some combat/movement stuff done here because it's too
// specific for logic in onRelativeMovement
// "Attack" shortcut - freeze movement to allow chorded direction when key is released.
// if in combat, executes an attack on key release
case KEY_ATTACK:
if (keydown && !keyState_attack) { // key pressed - pause any movement
if(!world.model.uiSelections.isInCombat) controllers.movementController.stopMovement();
} else if (!keydown && keyState_attack) { // key released - execute attack / move in direction
if (acceptInput) onRelativeMovement(keyState_dx, keyState_dy);
}
keyState_attack = keydown;
break;
// "Flee" shortcut. Intitiates flee when pressed. If a direction is held, moves in chosen direction when released
case KEY_FLEE:
if (world.model.uiSelections.isInCombat) {
if (keydown && !keyState_flee) { // button pressed - set flee; movement locked while pressed
if(acceptInput) controllers.combatController.startFlee();
} else if (!keydown && keyState_flee) { // button released - move flee direction, if held
// We need to do a special call because the movement key may already be down, and if the device
// doesn't generate repeat keystrokes, this handler won't get another event
if ((keyState_dx != 0 || keyState_dy != 0) && allowInputInterval()) {
if(acceptInput) controllers.combatController.executeMoveAttack(keyState_dx, keyState_dy);
}
}
}
keyState_flee = keydown;
break;
// "End Turn" shortcut. Flag prevents repeated end turn if key is held down.
case KEY_END_TURN:
if (acceptInput && keydown && !keyState_endturn) {
if (world.model.uiSelections.isInCombat) controllers.combatController.endPlayerTurn();
}
keyState_endturn = keydown;
break;
// "Hero Info" screen shortcut. New activity takes focus, so we don't need to worry about repeats.
case KEY_HERO_INFO:
if (acceptInput && keydown) context.startActivity(new Intent(context, HeroinfoActivity.class));
break;
case KEY_TOOLBOX:
// ??? ToolboxView toolboxview = context.getApplicationContext(). findViewById(R.id.main_toolboxview);
break;
case KEY_UNHANDLED: // Unhandled keycode
return false;
default: // unhandled keymap code entry (should not happen)
L.log("onKeyboardAction(): Unhandled keyMap code constant " + keyMap.get(event.getKeyCode()) + " for keyCode " + event.getKeyCode());
return false;
}
return true;
}
public void onRelativeMovement(int dx, int dy) {
//L.log("onRelativeMovement(): dx=" + dx + " dy=" + dy + " combat: " + world.model.uiSelections.isInCombat);
if (world.model.uiSelections.isInCombat) {
if (allowInputInterval()) controllers.combatController.executeMoveAttack(dx, dy);
} else if (dx == 0 && dy == 0) {
controllers.movementController.stopMovement();
} else {
controllers.movementController.startMovement(dx, dy, null);
}
}
public void onKeyboardCancel() {
controllers.movementController.stopMovement();
}
@Override
public void onClick(View arg0) {
if (!world.model.uiSelections.isInCombat) return;
onRelativeMovement(lastTouchPosition_dx, lastTouchPosition_dy);
}
@Override
public boolean onLongClick(View arg0) {
if (world.model.uiSelections.isInCombat) {
//TODO: Should be able to mark positions far away (mapwalk / ranged combat)
if (lastTouchPosition_dx == 0 && lastTouchPosition_dy == 0) return false;
if (Math.abs(lastTouchPosition_dx) > 1) return false;
if (Math.abs(lastTouchPosition_dy) > 1) return false;
controllers.combatController.setCombatSelection(lastTouchPosition_tileCoords);
return true;
}
return false;
}
private boolean allowInputInterval() {
final long now = System.currentTimeMillis();
if ((now - lastTouchEventTime) < Constants.MINIMUM_INPUT_INTERVAL) return false;
lastTouchEventTime = now;
return true;
}
public void setDpadActive(boolean isDpadActive) {
this.isDpadActive = isDpadActive;
}
public void onTouchCancel() {
controllers.movementController.stopMovement();
}
public boolean onTouchedTile(int tile_x, int tile_y) {
lastTouchPosition_tileCoords.set(tile_x, tile_y);
lastTouchPosition_dx = tile_x - world.model.player.position.x;
lastTouchPosition_dy = tile_y - world.model.player.position.y;
if (world.model.uiSelections.isInCombat || isDpadActive) return false;
controllers.movementController.startMovement(lastTouchPosition_dx, lastTouchPosition_dy, lastTouchPosition_tileCoords);
return true;
}
}

View File

@@ -1,446 +1,446 @@
package com.gpl.rpg.AndorsTrail.controller;
import java.util.ArrayList;
import java.util.Collection;
import com.gpl.rpg.AndorsTrail.AndorsTrailPreferences;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.context.ControllerContext;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.controller.listeners.QuickSlotListeners;
import com.gpl.rpg.AndorsTrail.model.ModelContainer;
import com.gpl.rpg.AndorsTrail.model.ability.SkillCollection;
import com.gpl.rpg.AndorsTrail.model.ability.traits.AbilityModifierTraits;
import com.gpl.rpg.AndorsTrail.model.actor.Player;
import com.gpl.rpg.AndorsTrail.model.item.Inventory;
import com.gpl.rpg.AndorsTrail.model.item.ItemContainer;
import com.gpl.rpg.AndorsTrail.model.item.ItemContainer.ItemEntry;
import com.gpl.rpg.AndorsTrail.model.item.ItemTraits_OnHitReceived;
import com.gpl.rpg.AndorsTrail.model.item.ItemTraits_OnUse;
import com.gpl.rpg.AndorsTrail.model.item.ItemType;
import com.gpl.rpg.AndorsTrail.model.item.Loot;
import static java.lang.Math.min;
public final class ItemController {
private final ControllerContext controllers;
private final WorldContext world;
public final QuickSlotListeners quickSlotListeners = new QuickSlotListeners();
public ItemController(ControllerContext controllers, WorldContext world) {
this.controllers = controllers;
this.world = world;
}
public void dropItem(ItemType type, int quantity) {
if (world.model.player.inventory.getItemQuantity(type.id) < quantity) return;
world.model.player.inventory.removeItem(type.id, quantity);
world.model.currentMaps.map.itemDropped(type, quantity, world.model.player.position);
}
public void equipItem(ItemType type, Inventory.WearSlot slot) {
if (!type.isEquippable()) return;
final Player player = world.model.player;
if (world.model.uiSelections.isInCombat) {
boolean changed = controllers.actorStatsController.useAPs(player, player.getReequipCost());
if (!changed) return;
}
if (!player.inventory.removeItem(type.id, 1)) return;
unequipSlot(player, slot);
if (type.isTwohandWeapon()) unequipSlot(player, Inventory.WearSlot.shield);
else if (slot == Inventory.WearSlot.shield) {
ItemType currentWeapon = player.inventory.getItemTypeInWearSlot(Inventory.WearSlot.weapon);
if (currentWeapon != null && currentWeapon.isTwohandWeapon()) unequipSlot(player, Inventory.WearSlot.weapon);
}
player.inventory.setItemTypeInWearSlot(slot, type);
controllers.actorStatsController.addConditionsFromEquippedItem(player, type);
controllers.actorStatsController.recalculatePlayerStats(player);
if (world.model.uiSelections.isInCombat && !controllers.combatController.playerHasApLeft()) {
controllers.combatController.endPlayerTurn();
}
}
public void unequipSlot(ItemType type, Inventory.WearSlot slot) {
if (!type.isEquippable()) return;
final Player player = world.model.player;
if (player.inventory.isEmptySlot(slot)) return;
if (world.model.uiSelections.isInCombat) {
boolean changed = controllers.actorStatsController.useAPs(player, player.getReequipCost());
if (!changed) return;
}
unequipSlot(player, slot);
controllers.actorStatsController.recalculatePlayerStats(player);
if (world.model.uiSelections.isInCombat && !controllers.combatController.playerHasApLeft()) {
controllers.combatController.endPlayerTurn();
}
}
private void unequipSlot(Player player, Inventory.WearSlot slot) {
ItemType removedItemType = player.inventory.getItemTypeInWearSlot(slot);
if (removedItemType == null) return;
player.inventory.addItem(removedItemType);
player.inventory.setItemTypeInWearSlot(slot, null);
controllers.actorStatsController.removeConditionsFromUnequippedItem(player, removedItemType);
}
public void useItem(ItemType type) {
if (!type.isUsable()) return;
final Player player = world.model.player;
if (world.model.uiSelections.isInCombat) {
boolean changed = controllers.actorStatsController.useAPs(player, player.getUseItemCost());
if (!changed) return;
}
if (!player.inventory.removeItem(type.id, 1)) return;
world.model.combatLog.append(controllers.getResources().getString(R.string.inventory_item_used, type.getName(player)));
controllers.actorStatsController.applyUseEffect(player, null, type.effects_use);
world.model.statistics.addItemUsage(type);
if (world.model.uiSelections.isInCombat && !controllers.combatController.playerHasApLeft()) {
controllers.combatController.endPlayerTurn();
}
}
public void playerSteppedOnLootBag(Loot loot) {
if (pickupLootBagWithoutConfirmation(loot)) {
controllers.mapController.worldEventListeners.onPlayerPickedUpGroundLoot(loot);
pickupAll(loot);
removeLootBagIfEmpty(loot);
} else {
controllers.mapController.worldEventListeners.onPlayerSteppedOnGroundLoot(loot);
consumeNonItemLoot(loot);
}
}
public void lootMonsterBags(Collection<Loot> killedMonsterBags, int totalExpThisFight) {
if (pickupLootBagsWithoutConfirmation(killedMonsterBags)) {
controllers.mapController.worldEventListeners.onPlayerPickedUpMonsterLoot(killedMonsterBags, totalExpThisFight);
pickupAll(killedMonsterBags);
removeLootBagIfEmpty(killedMonsterBags);
controllers.gameRoundController.resume();
} else {
controllers.mapController.worldEventListeners.onPlayerFoundMonsterLoot(killedMonsterBags, totalExpThisFight);
consumeNonItemLoot(killedMonsterBags);
}
}
private boolean pickupLootBagWithoutConfirmation(Loot bag) {
if (bag.isContainer()) return false;
switch (controllers.preferences.displayLoot) {
case AndorsTrailPreferences.DISPLAYLOOT_DIALOG_ALWAYS:
return false;
case AndorsTrailPreferences.DISPLAYLOOT_DIALOG_FOR_ITEMS:
case AndorsTrailPreferences.DISPLAYLOOT_DIALOG_FOR_ITEMS_ELSE_TOAST:
if (bag.hasItems()) return false;
}
return true;
}
private boolean pickupLootBagsWithoutConfirmation(Collection<Loot> bags) {
if (controllers.preferences.displayLoot == AndorsTrailPreferences.DISPLAYLOOT_DIALOG_ALWAYS) return false;
for (Loot bag : bags) {
if (!pickupLootBagWithoutConfirmation(bag)) return false;
}
return true;
}
public void applyInventoryEffects(Player player) {
ItemType weapon = getMainWeapon(player);
if (weapon != null) {
player.attackCost = 0;
player.criticalMultiplier = weapon.effects_equip.stats.setCriticalMultiplier;
}
applyInventoryEffects(player, Inventory.WearSlot.weapon);
applyInventoryEffects(player, Inventory.WearSlot.shield);
SkillController.applySkillEffectsFromFightingStyles(player);
applyInventoryEffects(player, Inventory.WearSlot.head);
applyInventoryEffects(player, Inventory.WearSlot.body);
applyInventoryEffects(player, Inventory.WearSlot.hand);
applyInventoryEffects(player, Inventory.WearSlot.feet);
applyInventoryEffects(player, Inventory.WearSlot.neck);
applyInventoryEffects(player, Inventory.WearSlot.leftring);
applyInventoryEffects(player, Inventory.WearSlot.rightring);
SkillController.applySkillEffectsFromItemProficiencies(player);
}
public static ItemType getMainWeapon(Player player) {
ItemType itemType = player.inventory.getItemTypeInWearSlot(Inventory.WearSlot.weapon);
if (itemType != null) return itemType;
itemType = player.inventory.getItemTypeInWearSlot(Inventory.WearSlot.shield);
if (itemType != null && itemType.isWeapon()) return itemType;
return null;
}
private void applyInventoryEffects(Player player, Inventory.WearSlot slot) {
ItemType type = player.inventory.getItemTypeInWearSlot(slot);
if (type == null) return;
if (slot == Inventory.WearSlot.shield) {
ItemType mainHandItem = player.inventory.getItemTypeInWearSlot(Inventory.WearSlot.weapon);
// The stats for off-hand weapons will be added later in SkillController.applySkillEffectsFromFightingStyles
if (SkillController.isDualWielding(mainHandItem, type)) return;
}
if (type.effects_equip != null && type.effects_equip.stats != null) {
controllers.actorStatsController.applyAbilityEffects(player, type.effects_equip.stats, 1);
if (type.isWeapon()) {
controllers.actorStatsController.addPlayerWeaponDamage(player, type.effects_equip.stats.increaseMinDamage, type.effects_equip.stats.increaseMaxDamage);
}
}
}
public static void recalculateHitEffectsFromWornItems(Player player) {
ArrayList<ItemTraits_OnUse> effects_onHit = null;
ArrayList<ItemTraits_OnHitReceived> effects_onHitReceived = null;
for (Inventory.WearSlot slot : Inventory.WearSlot.values()) {
ItemType type = player.inventory.getItemTypeInWearSlot(slot);
if (type == null) continue;
ItemTraits_OnUse eh = type.effects_hit;
ItemTraits_OnHitReceived ehr = type.effects_hitReceived;
if (eh == null && ehr == null) continue;
if (effects_onHit == null) effects_onHit = new ArrayList<ItemTraits_OnUse>();
if (eh != null) effects_onHit.add(eh);
if (effects_onHitReceived == null) effects_onHitReceived = new ArrayList<ItemTraits_OnHitReceived>();
if (ehr != null) effects_onHitReceived.add(ehr);
}
if (effects_onHit != null) {
ItemTraits_OnUse[] effects_ = new ItemTraits_OnUse[effects_onHit.size()];
effects_ = effects_onHit.toArray(effects_);
player.onHitEffects = effects_;
} else {
player.onHitEffects = null;
}
if (effects_onHitReceived != null) {
ItemTraits_OnHitReceived[] effects_ = new ItemTraits_OnHitReceived[effects_onHitReceived.size()];
effects_ = effects_onHitReceived.toArray(effects_);
player.onHitReceivedEffects = effects_;
} else {
player.onHitReceivedEffects = null;
}
}
public void consumeNonItemLoot(Loot loot) {
// Experience will be given as soon as the monster is killed.
world.model.player.inventory.gold += loot.gold;
loot.gold = 0;
removeLootBagIfEmpty(loot);
}
public void consumeNonItemLoot(Iterable<Loot> lootBags) {
for(Loot l : lootBags) {
consumeNonItemLoot(l);
}
}
public void pickupAll(Loot loot) {
world.model.player.inventory.add(loot.items);
consumeNonItemLoot(loot);
checkQuickslotItemLooted(loot.items);
loot.clear();
}
public void pickupAll(Iterable<Loot> lootBags) {
for(Loot l : lootBags) {
pickupAll(l);
}
}
public boolean removeLootBagIfEmpty(final Loot loot) {
if (loot.hasItemsOrGold()) return false;
world.model.currentMaps.map.removeGroundLoot(loot);
controllers.mapController.mapLayoutListeners.onLootBagRemoved(world.model.currentMaps.map, loot.position);
return true; // The bag was removed.
}
public boolean removeLootBagIfEmpty(final Iterable<Loot> lootBags) {
boolean isEmpty = true;
for (Loot l : lootBags) {
if (!removeLootBagIfEmpty(l)) isEmpty = false;
}
return isEmpty;
}
private static int getMarketPriceFactor(Player player) {
return Constants.MARKET_PRICEFACTOR_PERCENT
- player.getSkillLevel(SkillCollection.SkillID.barter) * SkillCollection.PER_SKILLPOINT_INCREASE_BARTER_PRICEFACTOR_PERCENTAGE;
}
public static int getBuyingPrice(Player player, ItemType itemType) {
return itemType.baseMarketCost + itemType.baseMarketCost * getMarketPriceFactor(player) / 100;
}
public static int getSellingPrice(Player player, ItemType itemType) {
return itemType.baseMarketCost - itemType.baseMarketCost * getMarketPriceFactor(player) / 100;
}
public static boolean canAfford(Player player, ItemType itemType) {
return player.inventory.gold >= getBuyingPrice(player, itemType);
}
public static boolean canAfford(Player player, int price) {
return player.inventory.gold >= price;
}
public static boolean maySellItem(Player player, ItemType itemType) {
if (!itemType.isSellable()) return false;
return true;
}
public static boolean sell(Player player, ItemType itemType, ItemContainer merchant, int quantity) {
int price = getSellingPrice(player, itemType) * quantity;
if (!maySellItem(player, itemType)) return false;
if (!player.inventory.removeItem(itemType.id, quantity)) return false;
player.inventory.gold += price;
merchant.addItem(itemType, quantity);
return true;
}
public static boolean buy(ModelContainer model, Player player, ItemType itemType, ItemContainer merchant, int quantity) {
int price = getBuyingPrice(player, itemType) * quantity;
if (!canAfford(player, price)) return false;
if (!merchant.removeItem(itemType.id, quantity)) return false;
player.inventory.gold -= price;
player.inventory.addItem(itemType, quantity);
model.statistics.addGoldSpent(price);
return true;
}
public static String describeItemForListView(ItemEntry item, Player player) {
StringBuilder sb = new StringBuilder(item.itemType.getName(player));
if (item.quantity > 1) {
sb.append(" (");
sb.append(item.quantity);
sb.append(')');
}
if (item.itemType.effects_equip != null) {
AbilityModifierTraits t = item.itemType.effects_equip.stats;
if (t != null) {
if (t.increaseAttackChance != 0
|| t.increaseMinDamage != 0
|| t.increaseMaxDamage != 0
|| t.increaseCriticalSkill != 0
|| t.setCriticalMultiplier != 0) {
sb.append(" [");
describeAttackEffect(t.increaseAttackChance, t.increaseMinDamage, t.increaseMaxDamage, t.increaseCriticalSkill, t.setCriticalMultiplier, sb);
sb.append(']');
}
if (t.increaseBlockChance != 0
|| t.increaseDamageResistance != 0) {
sb.append(" [");
describeBlockEffect(t.increaseBlockChance, t.increaseDamageResistance, sb);
sb.append(']');
}
}
}
return sb.toString();
}
public static void describeAttackEffect(int attackChance, int minDamage, int maxDamage, int criticalSkill, float criticalMultiplier, StringBuilder sb) {
boolean addSpace = false;
if (attackChance != 0) {
sb.append(attackChance);
addSpace = true;
}
if (minDamage != 0 || maxDamage != 0) {
if (addSpace) sb.append(' ');
sb.append(minDamage);
if (minDamage != maxDamage) {
sb.append('-');
sb.append(maxDamage);
}
addSpace = true;
}
if (criticalSkill != 0) {
if (addSpace) sb.append(' ');
if (criticalSkill >= 0) {
sb.append('+');
}
sb.append(criticalSkill);
}
if (criticalMultiplier != 0 && criticalMultiplier != 1) {
sb.append('x');
sb.append(criticalMultiplier);
}
}
public static void describeBlockEffect(int blockChance, int damageResistance, StringBuilder sb) {
if (blockChance != 0) {
sb.append(blockChance);
}
if (damageResistance != 0) {
sb.append('/');
sb.append(damageResistance);
}
}
public void quickitemUse(int quickSlotId) {
useItem(world.model.player.inventory.quickitem[quickSlotId]);
quickSlotListeners.onQuickSlotUsed(quickSlotId);
}
public void setQuickItem(ItemType itemType, int quickSlotId) {
world.model.player.inventory.quickitem[quickSlotId] = itemType;
quickSlotListeners.onQuickSlotChanged(quickSlotId);
}
private void checkQuickslotItemLooted(ItemContainer items) {
for (ItemEntry item : items.items) {
if (item.itemType.isUsable()) {
for (int i = 0; i < world.model.player.inventory.quickitem.length; i++) {
if (item.itemType == world.model.player.inventory.quickitem[i]) {
quickSlotListeners.onQuickSlotChanged(i);
}
}
}
}
}
public int removeEquippedItem(String itemTypeID, int count) {
int removed = 0;
final Player player = world.model.player;
for (Inventory.WearSlot slot : Inventory.WearSlot.values()) {
ItemType type = player.inventory.getItemTypeInWearSlot(slot);
if (type != null && type.id.equals(itemTypeID)) {
player.inventory.setItemTypeInWearSlot(slot, null);
controllers.actorStatsController.removeConditionsFromUnequippedItem(player, type);
controllers.actorStatsController.recalculatePlayerStats(player);
removed++;
if (removed >= count) {
break;
}
}
}
return removed;
}
public static void applyDamageModifier(Player player) {
ItemType itemType = player.inventory.getItemTypeInWearSlot(Inventory.WearSlot.weapon);
int modifier1 = -1;
int modifier2 = -1;
if (itemType != null) modifier1 = itemType.effects_equip.stats.setNonWeaponDamageModifier;
itemType = player.inventory.getItemTypeInWearSlot(Inventory.WearSlot.shield);
if (itemType != null && itemType.isWeapon()) modifier2 = itemType.effects_equip.stats.setNonWeaponDamageModifier;
int modifier = 100;
if (modifier1 >= 0 && modifier2 >= 0) {
int skillLevelFightStyle = player.getSkillLevel(SkillCollection.SkillID.fightstyleDualWield);
if (skillLevelFightStyle == 2) {
modifier = Math.max(modifier1, modifier2);
} else if (skillLevelFightStyle == 1) {
modifier = (modifier1 + modifier2) / 2;
} else {
modifier = Math.min(modifier1, modifier2);
}
}
else if (modifier1 <= 0 && modifier2 >= 0) modifier = modifier2;
else if (modifier2 <= 0 && modifier1 >= 0) modifier = modifier1;
if (modifier != 100) {
final int minBaseDamage = player.damagePotential.current - player.weaponDamage.current;
final int maxBaseDamage = player.damagePotential.max - player.weaponDamage.max;
player.damagePotential.add(Math.round(minBaseDamage * ((modifier - 100)/100f)), true);
player.damagePotential.addToMax(Math.round(maxBaseDamage * ((modifier - 100)/100f)));
}
}
}
package com.gpl.rpg.AndorsTrail.controller;
import java.util.ArrayList;
import java.util.Collection;
import com.gpl.rpg.AndorsTrail.AndorsTrailPreferences;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.context.ControllerContext;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.controller.listeners.QuickSlotListeners;
import com.gpl.rpg.AndorsTrail.model.ModelContainer;
import com.gpl.rpg.AndorsTrail.model.ability.SkillCollection;
import com.gpl.rpg.AndorsTrail.model.ability.traits.AbilityModifierTraits;
import com.gpl.rpg.AndorsTrail.model.actor.Player;
import com.gpl.rpg.AndorsTrail.model.item.Inventory;
import com.gpl.rpg.AndorsTrail.model.item.ItemContainer;
import com.gpl.rpg.AndorsTrail.model.item.ItemContainer.ItemEntry;
import com.gpl.rpg.AndorsTrail.model.item.ItemTraits_OnHitReceived;
import com.gpl.rpg.AndorsTrail.model.item.ItemTraits_OnUse;
import com.gpl.rpg.AndorsTrail.model.item.ItemType;
import com.gpl.rpg.AndorsTrail.model.item.Loot;
import static java.lang.Math.min;
public final class ItemController {
private final ControllerContext controllers;
private final WorldContext world;
public final QuickSlotListeners quickSlotListeners = new QuickSlotListeners();
public ItemController(ControllerContext controllers, WorldContext world) {
this.controllers = controllers;
this.world = world;
}
public void dropItem(ItemType type, int quantity) {
if (world.model.player.inventory.getItemQuantity(type.id) < quantity) return;
world.model.player.inventory.removeItem(type.id, quantity);
world.model.currentMaps.map.itemDropped(type, quantity, world.model.player.position);
}
public void equipItem(ItemType type, Inventory.WearSlot slot) {
if (!type.isEquippable()) return;
final Player player = world.model.player;
if (world.model.uiSelections.isInCombat) {
boolean changed = controllers.actorStatsController.useAPs(player, player.getReequipCost());
if (!changed) return;
}
if (!player.inventory.removeItem(type.id, 1)) return;
unequipSlot(player, slot);
if (type.isTwohandWeapon()) unequipSlot(player, Inventory.WearSlot.shield);
else if (slot == Inventory.WearSlot.shield) {
ItemType currentWeapon = player.inventory.getItemTypeInWearSlot(Inventory.WearSlot.weapon);
if (currentWeapon != null && currentWeapon.isTwohandWeapon()) unequipSlot(player, Inventory.WearSlot.weapon);
}
player.inventory.setItemTypeInWearSlot(slot, type);
controllers.actorStatsController.addConditionsFromEquippedItem(player, type);
controllers.actorStatsController.recalculatePlayerStats(player);
if (world.model.uiSelections.isInCombat && !controllers.combatController.playerHasApLeft()) {
controllers.combatController.endPlayerTurn();
}
}
public void unequipSlot(ItemType type, Inventory.WearSlot slot) {
if (!type.isEquippable()) return;
final Player player = world.model.player;
if (player.inventory.isEmptySlot(slot)) return;
if (world.model.uiSelections.isInCombat) {
boolean changed = controllers.actorStatsController.useAPs(player, player.getReequipCost());
if (!changed) return;
}
unequipSlot(player, slot);
controllers.actorStatsController.recalculatePlayerStats(player);
if (world.model.uiSelections.isInCombat && !controllers.combatController.playerHasApLeft()) {
controllers.combatController.endPlayerTurn();
}
}
private void unequipSlot(Player player, Inventory.WearSlot slot) {
ItemType removedItemType = player.inventory.getItemTypeInWearSlot(slot);
if (removedItemType == null) return;
player.inventory.addItem(removedItemType);
player.inventory.setItemTypeInWearSlot(slot, null);
controllers.actorStatsController.removeConditionsFromUnequippedItem(player, removedItemType);
}
public void useItem(ItemType type) {
if (!type.isUsable()) return;
final Player player = world.model.player;
if (world.model.uiSelections.isInCombat) {
boolean changed = controllers.actorStatsController.useAPs(player, player.getUseItemCost());
if (!changed) return;
}
if (!player.inventory.removeItem(type.id, 1)) return;
world.model.combatLog.append(controllers.getResources().getString(R.string.inventory_item_used, type.getName(player)));
controllers.actorStatsController.applyUseEffect(player, null, type.effects_use);
world.model.statistics.addItemUsage(type);
if (world.model.uiSelections.isInCombat && !controllers.combatController.playerHasApLeft()) {
controllers.combatController.endPlayerTurn();
}
}
public void playerSteppedOnLootBag(Loot loot) {
if (pickupLootBagWithoutConfirmation(loot)) {
controllers.mapController.worldEventListeners.onPlayerPickedUpGroundLoot(loot);
pickupAll(loot);
removeLootBagIfEmpty(loot);
} else {
controllers.mapController.worldEventListeners.onPlayerSteppedOnGroundLoot(loot);
consumeNonItemLoot(loot);
}
}
public void lootMonsterBags(Collection<Loot> killedMonsterBags, int totalExpThisFight) {
if (pickupLootBagsWithoutConfirmation(killedMonsterBags)) {
controllers.mapController.worldEventListeners.onPlayerPickedUpMonsterLoot(killedMonsterBags, totalExpThisFight);
pickupAll(killedMonsterBags);
removeLootBagIfEmpty(killedMonsterBags);
controllers.gameRoundController.resume();
} else {
controllers.mapController.worldEventListeners.onPlayerFoundMonsterLoot(killedMonsterBags, totalExpThisFight);
consumeNonItemLoot(killedMonsterBags);
}
}
private boolean pickupLootBagWithoutConfirmation(Loot bag) {
if (bag.isContainer()) return false;
switch (controllers.preferences.displayLoot) {
case AndorsTrailPreferences.DISPLAYLOOT_DIALOG_ALWAYS:
return false;
case AndorsTrailPreferences.DISPLAYLOOT_DIALOG_FOR_ITEMS:
case AndorsTrailPreferences.DISPLAYLOOT_DIALOG_FOR_ITEMS_ELSE_TOAST:
if (bag.hasItems()) return false;
}
return true;
}
private boolean pickupLootBagsWithoutConfirmation(Collection<Loot> bags) {
if (controllers.preferences.displayLoot == AndorsTrailPreferences.DISPLAYLOOT_DIALOG_ALWAYS) return false;
for (Loot bag : bags) {
if (!pickupLootBagWithoutConfirmation(bag)) return false;
}
return true;
}
public void applyInventoryEffects(Player player) {
ItemType weapon = getMainWeapon(player);
if (weapon != null) {
player.attackCost = 0;
player.criticalMultiplier = weapon.effects_equip.stats.setCriticalMultiplier;
}
applyInventoryEffects(player, Inventory.WearSlot.weapon);
applyInventoryEffects(player, Inventory.WearSlot.shield);
SkillController.applySkillEffectsFromFightingStyles(player);
applyInventoryEffects(player, Inventory.WearSlot.head);
applyInventoryEffects(player, Inventory.WearSlot.body);
applyInventoryEffects(player, Inventory.WearSlot.hand);
applyInventoryEffects(player, Inventory.WearSlot.feet);
applyInventoryEffects(player, Inventory.WearSlot.neck);
applyInventoryEffects(player, Inventory.WearSlot.leftring);
applyInventoryEffects(player, Inventory.WearSlot.rightring);
SkillController.applySkillEffectsFromItemProficiencies(player);
}
public static ItemType getMainWeapon(Player player) {
ItemType itemType = player.inventory.getItemTypeInWearSlot(Inventory.WearSlot.weapon);
if (itemType != null) return itemType;
itemType = player.inventory.getItemTypeInWearSlot(Inventory.WearSlot.shield);
if (itemType != null && itemType.isWeapon()) return itemType;
return null;
}
private void applyInventoryEffects(Player player, Inventory.WearSlot slot) {
ItemType type = player.inventory.getItemTypeInWearSlot(slot);
if (type == null) return;
if (slot == Inventory.WearSlot.shield) {
ItemType mainHandItem = player.inventory.getItemTypeInWearSlot(Inventory.WearSlot.weapon);
// The stats for off-hand weapons will be added later in SkillController.applySkillEffectsFromFightingStyles
if (SkillController.isDualWielding(mainHandItem, type)) return;
}
if (type.effects_equip != null && type.effects_equip.stats != null) {
controllers.actorStatsController.applyAbilityEffects(player, type.effects_equip.stats, 1);
if (type.isWeapon()) {
controllers.actorStatsController.addPlayerWeaponDamage(player, type.effects_equip.stats.increaseMinDamage, type.effects_equip.stats.increaseMaxDamage);
}
}
}
public static void recalculateHitEffectsFromWornItems(Player player) {
ArrayList<ItemTraits_OnUse> effects_onHit = null;
ArrayList<ItemTraits_OnHitReceived> effects_onHitReceived = null;
for (Inventory.WearSlot slot : Inventory.WearSlot.values()) {
ItemType type = player.inventory.getItemTypeInWearSlot(slot);
if (type == null) continue;
ItemTraits_OnUse eh = type.effects_hit;
ItemTraits_OnHitReceived ehr = type.effects_hitReceived;
if (eh == null && ehr == null) continue;
if (effects_onHit == null) effects_onHit = new ArrayList<ItemTraits_OnUse>();
if (eh != null) effects_onHit.add(eh);
if (effects_onHitReceived == null) effects_onHitReceived = new ArrayList<ItemTraits_OnHitReceived>();
if (ehr != null) effects_onHitReceived.add(ehr);
}
if (effects_onHit != null) {
ItemTraits_OnUse[] effects_ = new ItemTraits_OnUse[effects_onHit.size()];
effects_ = effects_onHit.toArray(effects_);
player.onHitEffects = effects_;
} else {
player.onHitEffects = null;
}
if (effects_onHitReceived != null) {
ItemTraits_OnHitReceived[] effects_ = new ItemTraits_OnHitReceived[effects_onHitReceived.size()];
effects_ = effects_onHitReceived.toArray(effects_);
player.onHitReceivedEffects = effects_;
} else {
player.onHitReceivedEffects = null;
}
}
public void consumeNonItemLoot(Loot loot) {
// Experience will be given as soon as the monster is killed.
world.model.player.inventory.gold += loot.gold;
loot.gold = 0;
removeLootBagIfEmpty(loot);
}
public void consumeNonItemLoot(Iterable<Loot> lootBags) {
for(Loot l : lootBags) {
consumeNonItemLoot(l);
}
}
public void pickupAll(Loot loot) {
world.model.player.inventory.add(loot.items);
consumeNonItemLoot(loot);
checkQuickslotItemLooted(loot.items);
loot.clear();
}
public void pickupAll(Iterable<Loot> lootBags) {
for(Loot l : lootBags) {
pickupAll(l);
}
}
public boolean removeLootBagIfEmpty(final Loot loot) {
if (loot.hasItemsOrGold()) return false;
world.model.currentMaps.map.removeGroundLoot(loot);
controllers.mapController.mapLayoutListeners.onLootBagRemoved(world.model.currentMaps.map, loot.position);
return true; // The bag was removed.
}
public boolean removeLootBagIfEmpty(final Iterable<Loot> lootBags) {
boolean isEmpty = true;
for (Loot l : lootBags) {
if (!removeLootBagIfEmpty(l)) isEmpty = false;
}
return isEmpty;
}
private static int getMarketPriceFactor(Player player) {
return Constants.MARKET_PRICEFACTOR_PERCENT
- player.getSkillLevel(SkillCollection.SkillID.barter) * SkillCollection.PER_SKILLPOINT_INCREASE_BARTER_PRICEFACTOR_PERCENTAGE;
}
public static int getBuyingPrice(Player player, ItemType itemType) {
return itemType.baseMarketCost + itemType.baseMarketCost * getMarketPriceFactor(player) / 100;
}
public static int getSellingPrice(Player player, ItemType itemType) {
return itemType.baseMarketCost - itemType.baseMarketCost * getMarketPriceFactor(player) / 100;
}
public static boolean canAfford(Player player, ItemType itemType) {
return player.inventory.gold >= getBuyingPrice(player, itemType);
}
public static boolean canAfford(Player player, int price) {
return player.inventory.gold >= price;
}
public static boolean maySellItem(Player player, ItemType itemType) {
if (!itemType.isSellable()) return false;
return true;
}
public static boolean sell(Player player, ItemType itemType, ItemContainer merchant, int quantity) {
int price = getSellingPrice(player, itemType) * quantity;
if (!maySellItem(player, itemType)) return false;
if (!player.inventory.removeItem(itemType.id, quantity)) return false;
player.inventory.gold += price;
merchant.addItem(itemType, quantity);
return true;
}
public static boolean buy(ModelContainer model, Player player, ItemType itemType, ItemContainer merchant, int quantity) {
int price = getBuyingPrice(player, itemType) * quantity;
if (!canAfford(player, price)) return false;
if (!merchant.removeItem(itemType.id, quantity)) return false;
player.inventory.gold -= price;
player.inventory.addItem(itemType, quantity);
model.statistics.addGoldSpent(price);
return true;
}
public static String describeItemForListView(ItemEntry item, Player player) {
StringBuilder sb = new StringBuilder(item.itemType.getName(player));
if (item.quantity > 1) {
sb.append(" (");
sb.append(item.quantity);
sb.append(')');
}
if (item.itemType.effects_equip != null) {
AbilityModifierTraits t = item.itemType.effects_equip.stats;
if (t != null) {
if (t.increaseAttackChance != 0
|| t.increaseMinDamage != 0
|| t.increaseMaxDamage != 0
|| t.increaseCriticalSkill != 0
|| t.setCriticalMultiplier != 0) {
sb.append(" [");
describeAttackEffect(t.increaseAttackChance, t.increaseMinDamage, t.increaseMaxDamage, t.increaseCriticalSkill, t.setCriticalMultiplier, sb);
sb.append(']');
}
if (t.increaseBlockChance != 0
|| t.increaseDamageResistance != 0) {
sb.append(" [");
describeBlockEffect(t.increaseBlockChance, t.increaseDamageResistance, sb);
sb.append(']');
}
}
}
return sb.toString();
}
public static void describeAttackEffect(int attackChance, int minDamage, int maxDamage, int criticalSkill, float criticalMultiplier, StringBuilder sb) {
boolean addSpace = false;
if (attackChance != 0) {
sb.append(attackChance);
addSpace = true;
}
if (minDamage != 0 || maxDamage != 0) {
if (addSpace) sb.append(' ');
sb.append(minDamage);
if (minDamage != maxDamage) {
sb.append('-');
sb.append(maxDamage);
}
addSpace = true;
}
if (criticalSkill != 0) {
if (addSpace) sb.append(' ');
if (criticalSkill >= 0) {
sb.append('+');
}
sb.append(criticalSkill);
}
if (criticalMultiplier != 0 && criticalMultiplier != 1) {
sb.append('x');
sb.append(criticalMultiplier);
}
}
public static void describeBlockEffect(int blockChance, int damageResistance, StringBuilder sb) {
if (blockChance != 0) {
sb.append(blockChance);
}
if (damageResistance != 0) {
sb.append('/');
sb.append(damageResistance);
}
}
public void quickitemUse(int quickSlotId) {
useItem(world.model.player.inventory.quickitem[quickSlotId]);
quickSlotListeners.onQuickSlotUsed(quickSlotId);
}
public void setQuickItem(ItemType itemType, int quickSlotId) {
world.model.player.inventory.quickitem[quickSlotId] = itemType;
quickSlotListeners.onQuickSlotChanged(quickSlotId);
}
private void checkQuickslotItemLooted(ItemContainer items) {
for (ItemEntry item : items.items) {
if (item.itemType.isUsable()) {
for (int i = 0; i < world.model.player.inventory.quickitem.length; i++) {
if (item.itemType == world.model.player.inventory.quickitem[i]) {
quickSlotListeners.onQuickSlotChanged(i);
}
}
}
}
}
public int removeEquippedItem(String itemTypeID, int count) {
int removed = 0;
final Player player = world.model.player;
for (Inventory.WearSlot slot : Inventory.WearSlot.values()) {
ItemType type = player.inventory.getItemTypeInWearSlot(slot);
if (type != null && type.id.equals(itemTypeID)) {
player.inventory.setItemTypeInWearSlot(slot, null);
controllers.actorStatsController.removeConditionsFromUnequippedItem(player, type);
controllers.actorStatsController.recalculatePlayerStats(player);
removed++;
if (removed >= count) {
break;
}
}
}
return removed;
}
public static void applyDamageModifier(Player player) {
ItemType itemType = player.inventory.getItemTypeInWearSlot(Inventory.WearSlot.weapon);
int modifier1 = -1;
int modifier2 = -1;
if (itemType != null) modifier1 = itemType.effects_equip.stats.setNonWeaponDamageModifier;
itemType = player.inventory.getItemTypeInWearSlot(Inventory.WearSlot.shield);
if (itemType != null && itemType.isWeapon()) modifier2 = itemType.effects_equip.stats.setNonWeaponDamageModifier;
int modifier = 100;
if (modifier1 >= 0 && modifier2 >= 0) {
int skillLevelFightStyle = player.getSkillLevel(SkillCollection.SkillID.fightstyleDualWield);
if (skillLevelFightStyle == 2) {
modifier = Math.max(modifier1, modifier2);
} else if (skillLevelFightStyle == 1) {
modifier = (modifier1 + modifier2) / 2;
} else {
modifier = Math.min(modifier1, modifier2);
}
}
else if (modifier1 <= 0 && modifier2 >= 0) modifier = modifier2;
else if (modifier2 <= 0 && modifier1 >= 0) modifier = modifier1;
if (modifier != 100) {
final int minBaseDamage = player.damagePotential.current - player.weaponDamage.current;
final int maxBaseDamage = player.damagePotential.max - player.weaponDamage.max;
player.damagePotential.add(Math.round(minBaseDamage * ((modifier - 100)/100f)), true);
player.damagePotential.addToMax(Math.round(maxBaseDamage * ((modifier - 100)/100f)));
}
}
}

View File

@@ -1,5 +1,6 @@
package com.gpl.rpg.AndorsTrail.controller;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.context.ControllerContext;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.controller.listeners.CombatActionListeners;
@@ -17,6 +18,7 @@ import com.gpl.rpg.AndorsTrail.model.item.ItemCategory;
import com.gpl.rpg.AndorsTrail.model.item.ItemType;
import com.gpl.rpg.AndorsTrail.model.item.ItemTypeCollection;
import com.gpl.rpg.AndorsTrail.util.ConstRange;
import com.gpl.rpg.AndorsTrail.util.L;
public final class SkillController {
private final ControllerContext controllers;
@@ -58,6 +60,9 @@ public final class SkillController {
public static int getDropChanceRollBias(DropItem item, Player player) {
if (player == null) return 0;
if(item.itemType == null && AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES){
L.log("Item type missing: " + item + " " + player.id);
}
if (ItemTypeCollection.isGoldItemType(item.itemType.id)) {
return getRollBias(item, player, SkillID.coinfinder, SkillCollection.PER_SKILLPOINT_INCREASE_COINFINDER_CHANCE_PERCENT);

View File

@@ -1,317 +1,317 @@
package com.gpl.rpg.AndorsTrail.controller;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.AsyncTask;
import android.widget.Toast;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.activity.DisplayWorldMapActivity;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.model.map.LayeredTileMap;
import com.gpl.rpg.AndorsTrail.model.map.MapLayer;
import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap;
import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment;
import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment.NamedWorldMapArea;
import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment.WorldMapSegmentMap;
import com.gpl.rpg.AndorsTrail.resource.tiles.TileCollection;
import com.gpl.rpg.AndorsTrail.util.AndroidStorage;
import com.gpl.rpg.AndorsTrail.util.Coord;
import com.gpl.rpg.AndorsTrail.util.CoordRect;
import com.gpl.rpg.AndorsTrail.util.L;
import com.gpl.rpg.AndorsTrail.util.Size;
public final class WorldMapController {
private static final int WORLDMAP_SCREENSHOT_TILESIZE = 8;
public static final int WORLDMAP_DISPLAY_TILESIZE = WORLDMAP_SCREENSHOT_TILESIZE;
public static void updateWorldMap(Context context, final WorldContext world, final Resources res) {
updateWorldMap(context, world, world.model.currentMaps.map, world.model.currentMaps.tileMap, world.model.currentMaps.tiles, res);
}
private static void updateWorldMap(
Context context, final WorldContext world,
final PredefinedMap map,
final LayeredTileMap mapTiles,
final TileCollection cachedTiles,
final Resources res) {
final String worldMapSegmentName = world.maps.getWorldMapSegmentNameForMap(map.name);
if (worldMapSegmentName == null) return;
if (!shouldUpdateWorldMap(context, map, worldMapSegmentName, world.maps.worldMapRequiresUpdate)) return;
(new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... arg0) {
final MapRenderer renderer = new MapRenderer(world, map, mapTiles, cachedTiles);
try {
updateCachedBitmap(context, map, renderer);
updateWorldMapSegment(context, res, world, worldMapSegmentName);
world.maps.worldMapRequiresUpdate = false;
if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) {
L.log("WorldMapController: Updated worldmap segment " + worldMapSegmentName + " for map " + map.name);
}
} catch (IOException e) {
L.log("Error creating worldmap file for map " + map.name + " : " + e.toString());
}
return null;
}
}).execute();
}
private static boolean shouldUpdateWorldMap(Context context, PredefinedMap map, String worldMapSegmentName, boolean forceUpdate) {
if (forceUpdate) return true;
if (!map.visited) return true;
File file = getFileForMap(context, map, false);
if (!file.exists()) return true;
file = getCombinedWorldMapFile(context, worldMapSegmentName);
if (!file.exists()) return true;
return false;
}
private static void updateCachedBitmap(Context context, PredefinedMap map, MapRenderer renderer) throws IOException {
ensureWorldmapDirectoryExists(context);
File file = getFileForMap(context, map, false);
if (file.exists()) return;
Bitmap image = renderer.drawMap();
FileOutputStream fos = new FileOutputStream(file);
image.compress(Bitmap.CompressFormat.PNG, 70, fos);
fos.flush();
fos.close();
image.recycle();
L.log("WorldMapController: Wrote " + file.getAbsolutePath());
}
private static final class MapRenderer {
private final PredefinedMap map;
private final LayeredTileMap mapTiles;
private final TileCollection cachedTiles;
private final int tileSize;
private final float scale;
private final Paint mPaint = new Paint();
public MapRenderer(final WorldContext world, final PredefinedMap map, final LayeredTileMap mapTiles, final TileCollection cachedTiles) {
this.map = map;
this.mapTiles = mapTiles;
this.cachedTiles = cachedTiles;
this.tileSize = world.tileManager.tileSize;
this.scale = (float) WORLDMAP_SCREENSHOT_TILESIZE / world.tileManager.tileSize;
mapTiles.setColorFilter(mPaint, null, true);
}
public Bitmap drawMap() {
Bitmap image = Bitmap.createBitmap(map.size.width * WORLDMAP_SCREENSHOT_TILESIZE, map.size.height * WORLDMAP_SCREENSHOT_TILESIZE, Config.RGB_565);
image.setDensity(Bitmap.DENSITY_NONE);
Canvas canvas = new Canvas(image);
canvas.scale(scale, scale);
synchronized (cachedTiles) {
tryDrawMapLayer(canvas, mapTiles.currentLayout.layerBase);
tryDrawMapLayer(canvas, mapTiles.currentLayout.layerGround);
tryDrawMapLayer(canvas, mapTiles.currentLayout.layerObjects);
tryDrawMapLayer(canvas, mapTiles.currentLayout.layerAbove);
tryDrawMapLayer(canvas, mapTiles.currentLayout.layerTop);
}
return image;
}
private void tryDrawMapLayer(Canvas canvas, final MapLayer layer) {
if (layer != null) drawMapLayer(canvas, layer);
}
private void drawMapLayer(Canvas canvas, final MapLayer layer) {
int py = 0;
for (int y = 0; y < map.size.height; ++y, py += tileSize) {
int px = 0;
for (int x = 0; x < map.size.width; ++x, px += tileSize) {
final int tile = layer.tiles[x][y];
if (tile == 0) continue;
cachedTiles.drawTile(canvas, tile, px, py, mPaint);
}
}
}
}
private static void ensureWorldmapDirectoryExists(Context context) throws IOException {
File dir = AndroidStorage.getStorageDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY);
if (!dir.exists()) dir.mkdir();
dir = new File(dir, Constants.FILENAME_WORLDMAP_DIRECTORY);
if (!dir.exists()) dir.mkdir();
File noMediaFile = new File(dir, ".nomedia");
if (!noMediaFile.exists()) noMediaFile.createNewFile();
}
public static boolean fileForMapExists(Context context, PredefinedMap map) {
if (map.lastSeenLayoutHash.length() > 0) {
return getPngFile(context, map.name + '.' + map.lastSeenLayoutHash).exists();
}
return getPngFile(context, map.name).exists();
}
private static File getFileForMap(Context context, PredefinedMap map, boolean verifyFileExists) {
if (map.lastSeenLayoutHash.length() > 0) {
File fileWithHash = getPngFile(context, map.name + '.' + map.lastSeenLayoutHash);
if (!verifyFileExists) return fileWithHash;
else if (fileWithHash.exists()) return fileWithHash;
}
return getPngFile(context, map.name);
}
private static File getPngFile(Context context, String fileName) {
return new File(getWorldmapDirectory(context), fileName + ".png");
}
private static File getWorldmapDirectory(Context context) {
File dir = AndroidStorage.getStorageDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY);
return new File(dir, Constants.FILENAME_WORLDMAP_DIRECTORY);
}
public static File getCombinedWorldMapFile(Context context, String segmentName) {
return new File(getWorldmapDirectory(context), Constants.FILENAME_WORLDMAP_HTMLFILE_PREFIX + segmentName + Constants.FILENAME_WORLDMAP_HTMLFILE_SUFFIX);
}
private static String getWorldMapSegmentAsHtml(Context context, Resources res, WorldContext world, String segmentName) {
WorldMapSegment segment = world.maps.worldMapSegments.get(segmentName);
Map<String, File> displayedMapFilenamesPerMapName = new HashMap<String, File>(segment.maps.size());
Coord offsetWorldmapTo = new Coord(999999, 999999);
for (WorldMapSegmentMap map : segment.maps.values()) {
PredefinedMap predefinedMap = world.maps.findPredefinedMap(map.mapName);
if (predefinedMap == null) continue;
if (!predefinedMap.visited) continue;
File f = WorldMapController.getFileForMap(context, predefinedMap, true);
if (!f.exists()) continue;
displayedMapFilenamesPerMapName.put(map.mapName, f);
offsetWorldmapTo.x = Math.min(offsetWorldmapTo.x, map.worldPosition.x);
offsetWorldmapTo.y = Math.min(offsetWorldmapTo.y, map.worldPosition.y);
}
Coord bottomRight = new Coord(0, 0);
StringBuilder mapsAsHtml = new StringBuilder(1000);
for (WorldMapSegmentMap segmentMap : segment.maps.values()) {
File f = displayedMapFilenamesPerMapName.get(segmentMap.mapName);
if (f == null) continue;
Size size = getMapSize(segmentMap, world);
mapsAsHtml
.append("<img src=\"")
.append(f.getName())
.append("\" id=\"")
.append(segmentMap.mapName)
.append("\" style=\"width:")
.append(size.width * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
.append("px; height:")
.append(size.height * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
.append("px; left:")
.append((segmentMap.worldPosition.x - offsetWorldmapTo.x) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
.append("px; top:")
.append((segmentMap.worldPosition.y - offsetWorldmapTo.y) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
.append("px;\" />");
if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) mapsAsHtml.append('\n');
bottomRight.x = Math.max(bottomRight.x, segmentMap.worldPosition.x + size.width);
bottomRight.y = Math.max(bottomRight.y, segmentMap.worldPosition.y + size.height);
}
Size worldmapSegmentSize = new Size(
(bottomRight.x - offsetWorldmapTo.x) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE
,(bottomRight.y - offsetWorldmapTo.y) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE
);
StringBuilder namedAreasAsHtml = new StringBuilder(500);
for (NamedWorldMapArea area : segment.namedAreas.values()) {
CoordRect r = determineNamedAreaBoundary(area, segment, world, displayedMapFilenamesPerMapName.keySet());
if (r == null) continue;
namedAreasAsHtml
.append("<div class=\"namedarea ")
.append(area.type)
.append("\" style=\"width:")
.append(r.size.width * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
.append("px; line-height:")
.append(r.size.height * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
.append("px; left:")
.append((r.topLeft.x - offsetWorldmapTo.x) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
.append("px; top:")
.append((r.topLeft.y - offsetWorldmapTo.y) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
.append("px;\"><span>")
.append(area.name)
.append("</span></div>");
if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) namedAreasAsHtml.append('\n');
}
return res.getString(R.string.worldmap_template)
.replace("{{maps}}", mapsAsHtml.toString())
.replace("{{areas}}", namedAreasAsHtml.toString())
.replace("{{sizex}}", Integer.toString(worldmapSegmentSize.width))
.replace("{{sizey}}", Integer.toString(worldmapSegmentSize.height))
.replace("{{offsetx}}", Integer.toString(offsetWorldmapTo.x * WorldMapController.WORLDMAP_DISPLAY_TILESIZE))
.replace("{{offsety}}", Integer.toString(offsetWorldmapTo.y * WorldMapController.WORLDMAP_DISPLAY_TILESIZE));
}
private static Size getMapSize(WorldMapSegmentMap map, WorldContext world) {
return world.maps.findPredefinedMap(map.mapName).size;
}
private static CoordRect determineNamedAreaBoundary(NamedWorldMapArea area, WorldMapSegment segment, WorldContext world, Set<String> displayedMapNames) {
Coord topLeft = null;
Coord bottomRight = null;
for (String mapName : area.mapNames) {
if (!displayedMapNames.contains(mapName)) continue;
WorldMapSegmentMap map = segment.maps.get(mapName);
Size size = getMapSize(map, world);
if (topLeft == null) {
topLeft = new Coord(map.worldPosition);
} else {
topLeft.x = Math.min(topLeft.x, map.worldPosition.x);
topLeft.y = Math.min(topLeft.y, map.worldPosition.y);
}
if (bottomRight == null) {
bottomRight = new Coord(map.worldPosition.x + size.width, map.worldPosition.y + size.height);
} else {
bottomRight.x = Math.max(bottomRight.x, map.worldPosition.x + size.width);
bottomRight.y = Math.max(bottomRight.y, map.worldPosition.y + size.height);
}
}
if (topLeft == null) return null;
return new CoordRect(topLeft, new Size(bottomRight.x - topLeft.x, bottomRight.y - topLeft.y));
}
public static void updateWorldMapSegment(Context context, Resources res, WorldContext world, String segmentName) throws IOException {
String mapAsHtml = getWorldMapSegmentAsHtml(context, res, world, segmentName);
File outputFile = getCombinedWorldMapFile(context, segmentName);
PrintWriter pw = new PrintWriter(outputFile);
pw.write(mapAsHtml);
pw.close();
}
public static boolean displayWorldMap(Context context, WorldContext world) {
String worldMapSegmentName = world.maps.getWorldMapSegmentNameForMap(world.model.currentMaps.map.name);
if (worldMapSegmentName == null) {
Toast.makeText(context, context.getResources().getString(R.string.display_worldmap_not_available), Toast.LENGTH_LONG).show();
return false;
}
Intent intent = new Intent(context, DisplayWorldMapActivity.class);
intent.putExtra("worldMapSegmentName", worldMapSegmentName);
context.startActivity(intent);
return true;
}
}
package com.gpl.rpg.AndorsTrail.controller;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.AsyncTask;
import android.widget.Toast;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.R;
import com.gpl.rpg.AndorsTrail.activity.DisplayWorldMapActivity;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.model.map.LayeredTileMap;
import com.gpl.rpg.AndorsTrail.model.map.MapLayer;
import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap;
import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment;
import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment.NamedWorldMapArea;
import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment.WorldMapSegmentMap;
import com.gpl.rpg.AndorsTrail.resource.tiles.TileCollection;
import com.gpl.rpg.AndorsTrail.util.AndroidStorage;
import com.gpl.rpg.AndorsTrail.util.Coord;
import com.gpl.rpg.AndorsTrail.util.CoordRect;
import com.gpl.rpg.AndorsTrail.util.L;
import com.gpl.rpg.AndorsTrail.util.Size;
public final class WorldMapController {
private static final int WORLDMAP_SCREENSHOT_TILESIZE = 8;
public static final int WORLDMAP_DISPLAY_TILESIZE = WORLDMAP_SCREENSHOT_TILESIZE;
public static void updateWorldMap(Context context, final WorldContext world, final Resources res) {
updateWorldMap(context, world, world.model.currentMaps.map, world.model.currentMaps.tileMap, world.model.currentMaps.tiles, res);
}
private static void updateWorldMap(
Context context, final WorldContext world,
final PredefinedMap map,
final LayeredTileMap mapTiles,
final TileCollection cachedTiles,
final Resources res) {
final String worldMapSegmentName = world.maps.getWorldMapSegmentNameForMap(map.name);
if (worldMapSegmentName == null) return;
if (!shouldUpdateWorldMap(context, map, worldMapSegmentName, world.maps.worldMapRequiresUpdate)) return;
(new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... arg0) {
final MapRenderer renderer = new MapRenderer(world, map, mapTiles, cachedTiles);
try {
updateCachedBitmap(context, map, renderer);
updateWorldMapSegment(context, res, world, worldMapSegmentName);
world.maps.worldMapRequiresUpdate = false;
if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) {
L.log("WorldMapController: Updated worldmap segment " + worldMapSegmentName + " for map " + map.name);
}
} catch (IOException e) {
L.log("Error creating worldmap file for map " + map.name + " : " + e.toString());
}
return null;
}
}).execute();
}
private static boolean shouldUpdateWorldMap(Context context, PredefinedMap map, String worldMapSegmentName, boolean forceUpdate) {
if (forceUpdate) return true;
if (!map.visited) return true;
File file = getFileForMap(context, map, false);
if (!file.exists()) return true;
file = getCombinedWorldMapFile(context, worldMapSegmentName);
if (!file.exists()) return true;
return false;
}
private static void updateCachedBitmap(Context context, PredefinedMap map, MapRenderer renderer) throws IOException {
ensureWorldmapDirectoryExists(context);
File file = getFileForMap(context, map, false);
if (file.exists()) return;
Bitmap image = renderer.drawMap();
FileOutputStream fos = new FileOutputStream(file);
image.compress(Bitmap.CompressFormat.PNG, 70, fos);
fos.flush();
fos.close();
image.recycle();
L.log("WorldMapController: Wrote " + file.getAbsolutePath());
}
private static final class MapRenderer {
private final PredefinedMap map;
private final LayeredTileMap mapTiles;
private final TileCollection cachedTiles;
private final int tileSize;
private final float scale;
private final Paint mPaint = new Paint();
public MapRenderer(final WorldContext world, final PredefinedMap map, final LayeredTileMap mapTiles, final TileCollection cachedTiles) {
this.map = map;
this.mapTiles = mapTiles;
this.cachedTiles = cachedTiles;
this.tileSize = world.tileManager.tileSize;
this.scale = (float) WORLDMAP_SCREENSHOT_TILESIZE / world.tileManager.tileSize;
mapTiles.setColorFilter(mPaint, null, true);
}
public Bitmap drawMap() {
Bitmap image = Bitmap.createBitmap(map.size.width * WORLDMAP_SCREENSHOT_TILESIZE, map.size.height * WORLDMAP_SCREENSHOT_TILESIZE, Config.RGB_565);
image.setDensity(Bitmap.DENSITY_NONE);
Canvas canvas = new Canvas(image);
canvas.scale(scale, scale);
synchronized (cachedTiles) {
tryDrawMapLayer(canvas, mapTiles.currentLayout.layerBase);
tryDrawMapLayer(canvas, mapTiles.currentLayout.layerGround);
tryDrawMapLayer(canvas, mapTiles.currentLayout.layerObjects);
tryDrawMapLayer(canvas, mapTiles.currentLayout.layerAbove);
tryDrawMapLayer(canvas, mapTiles.currentLayout.layerTop);
}
return image;
}
private void tryDrawMapLayer(Canvas canvas, final MapLayer layer) {
if (layer != null) drawMapLayer(canvas, layer);
}
private void drawMapLayer(Canvas canvas, final MapLayer layer) {
int py = 0;
for (int y = 0; y < map.size.height; ++y, py += tileSize) {
int px = 0;
for (int x = 0; x < map.size.width; ++x, px += tileSize) {
final int tile = layer.tiles[x][y];
if (tile == 0) continue;
cachedTiles.drawTile(canvas, tile, px, py, mPaint);
}
}
}
}
private static void ensureWorldmapDirectoryExists(Context context) throws IOException {
File dir = AndroidStorage.getStorageDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY);
if (!dir.exists()) dir.mkdir();
dir = new File(dir, Constants.FILENAME_WORLDMAP_DIRECTORY);
if (!dir.exists()) dir.mkdir();
File noMediaFile = new File(dir, ".nomedia");
if (!noMediaFile.exists()) noMediaFile.createNewFile();
}
public static boolean fileForMapExists(Context context, PredefinedMap map) {
if (map.lastSeenLayoutHash.length() > 0) {
return getPngFile(context, map.name + '.' + map.lastSeenLayoutHash).exists();
}
return getPngFile(context, map.name).exists();
}
private static File getFileForMap(Context context, PredefinedMap map, boolean verifyFileExists) {
if (map.lastSeenLayoutHash.length() > 0) {
File fileWithHash = getPngFile(context, map.name + '.' + map.lastSeenLayoutHash);
if (!verifyFileExists) return fileWithHash;
else if (fileWithHash.exists()) return fileWithHash;
}
return getPngFile(context, map.name);
}
private static File getPngFile(Context context, String fileName) {
return new File(getWorldmapDirectory(context), fileName + ".png");
}
private static File getWorldmapDirectory(Context context) {
File dir = AndroidStorage.getStorageDirectory(context, Constants.FILENAME_SAVEGAME_DIRECTORY);
return new File(dir, Constants.FILENAME_WORLDMAP_DIRECTORY);
}
public static File getCombinedWorldMapFile(Context context, String segmentName) {
return new File(getWorldmapDirectory(context), Constants.FILENAME_WORLDMAP_HTMLFILE_PREFIX + segmentName + Constants.FILENAME_WORLDMAP_HTMLFILE_SUFFIX);
}
private static String getWorldMapSegmentAsHtml(Context context, Resources res, WorldContext world, String segmentName) {
WorldMapSegment segment = world.maps.worldMapSegments.get(segmentName);
Map<String, File> displayedMapFilenamesPerMapName = new HashMap<String, File>(segment.maps.size());
Coord offsetWorldmapTo = new Coord(999999, 999999);
for (WorldMapSegmentMap map : segment.maps.values()) {
PredefinedMap predefinedMap = world.maps.findPredefinedMap(map.mapName);
if (predefinedMap == null) continue;
if (!predefinedMap.visited) continue;
File f = WorldMapController.getFileForMap(context, predefinedMap, true);
if (!f.exists()) continue;
displayedMapFilenamesPerMapName.put(map.mapName, f);
offsetWorldmapTo.x = Math.min(offsetWorldmapTo.x, map.worldPosition.x);
offsetWorldmapTo.y = Math.min(offsetWorldmapTo.y, map.worldPosition.y);
}
Coord bottomRight = new Coord(0, 0);
StringBuilder mapsAsHtml = new StringBuilder(1000);
for (WorldMapSegmentMap segmentMap : segment.maps.values()) {
File f = displayedMapFilenamesPerMapName.get(segmentMap.mapName);
if (f == null) continue;
Size size = getMapSize(segmentMap, world);
mapsAsHtml
.append("<img src=\"")
.append(f.getName())
.append("\" id=\"")
.append(segmentMap.mapName)
.append("\" style=\"width:")
.append(size.width * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
.append("px; height:")
.append(size.height * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
.append("px; left:")
.append((segmentMap.worldPosition.x - offsetWorldmapTo.x) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
.append("px; top:")
.append((segmentMap.worldPosition.y - offsetWorldmapTo.y) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
.append("px;\" />");
if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) mapsAsHtml.append('\n');
bottomRight.x = Math.max(bottomRight.x, segmentMap.worldPosition.x + size.width);
bottomRight.y = Math.max(bottomRight.y, segmentMap.worldPosition.y + size.height);
}
Size worldmapSegmentSize = new Size(
(bottomRight.x - offsetWorldmapTo.x) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE
,(bottomRight.y - offsetWorldmapTo.y) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE
);
StringBuilder namedAreasAsHtml = new StringBuilder(500);
for (NamedWorldMapArea area : segment.namedAreas.values()) {
CoordRect r = determineNamedAreaBoundary(area, segment, world, displayedMapFilenamesPerMapName.keySet());
if (r == null) continue;
namedAreasAsHtml
.append("<div class=\"namedarea ")
.append(area.type)
.append("\" style=\"width:")
.append(r.size.width * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
.append("px; line-height:")
.append(r.size.height * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
.append("px; left:")
.append((r.topLeft.x - offsetWorldmapTo.x) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
.append("px; top:")
.append((r.topLeft.y - offsetWorldmapTo.y) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
.append("px;\"><span>")
.append(area.name)
.append("</span></div>");
if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) namedAreasAsHtml.append('\n');
}
return res.getString(R.string.worldmap_template)
.replace("{{maps}}", mapsAsHtml.toString())
.replace("{{areas}}", namedAreasAsHtml.toString())
.replace("{{sizex}}", Integer.toString(worldmapSegmentSize.width))
.replace("{{sizey}}", Integer.toString(worldmapSegmentSize.height))
.replace("{{offsetx}}", Integer.toString(offsetWorldmapTo.x * WorldMapController.WORLDMAP_DISPLAY_TILESIZE))
.replace("{{offsety}}", Integer.toString(offsetWorldmapTo.y * WorldMapController.WORLDMAP_DISPLAY_TILESIZE));
}
private static Size getMapSize(WorldMapSegmentMap map, WorldContext world) {
return world.maps.findPredefinedMap(map.mapName).size;
}
private static CoordRect determineNamedAreaBoundary(NamedWorldMapArea area, WorldMapSegment segment, WorldContext world, Set<String> displayedMapNames) {
Coord topLeft = null;
Coord bottomRight = null;
for (String mapName : area.mapNames) {
if (!displayedMapNames.contains(mapName)) continue;
WorldMapSegmentMap map = segment.maps.get(mapName);
Size size = getMapSize(map, world);
if (topLeft == null) {
topLeft = new Coord(map.worldPosition);
} else {
topLeft.x = Math.min(topLeft.x, map.worldPosition.x);
topLeft.y = Math.min(topLeft.y, map.worldPosition.y);
}
if (bottomRight == null) {
bottomRight = new Coord(map.worldPosition.x + size.width, map.worldPosition.y + size.height);
} else {
bottomRight.x = Math.max(bottomRight.x, map.worldPosition.x + size.width);
bottomRight.y = Math.max(bottomRight.y, map.worldPosition.y + size.height);
}
}
if (topLeft == null) return null;
return new CoordRect(topLeft, new Size(bottomRight.x - topLeft.x, bottomRight.y - topLeft.y));
}
public static void updateWorldMapSegment(Context context, Resources res, WorldContext world, String segmentName) throws IOException {
String mapAsHtml = getWorldMapSegmentAsHtml(context, res, world, segmentName);
File outputFile = getCombinedWorldMapFile(context, segmentName);
PrintWriter pw = new PrintWriter(outputFile);
pw.write(mapAsHtml);
pw.close();
}
public static boolean displayWorldMap(Context context, WorldContext world) {
String worldMapSegmentName = world.maps.getWorldMapSegmentNameForMap(world.model.currentMaps.map.name);
if (worldMapSegmentName == null) {
Toast.makeText(context, context.getResources().getString(R.string.display_worldmap_not_available), Toast.LENGTH_LONG).show();
return false;
}
Intent intent = new Intent(context, DisplayWorldMapActivity.class);
intent.putExtra("worldMapSegmentName", worldMapSegmentName);
context.startActivity(intent);
return true;
}
}

View File

@@ -19,10 +19,12 @@ import com.gpl.rpg.AndorsTrail.model.actor.MonsterType;
import com.gpl.rpg.AndorsTrail.model.item.ItemType;
import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap;
import com.gpl.rpg.AndorsTrail.model.quest.Quest;
import com.gpl.rpg.AndorsTrail.util.HashMapHelper;
public final class GameStatistics {
private int deaths = 0;
private final HashMap<String, Integer> killedMonsters = new HashMap<String, Integer>();
private final HashMap<String, Integer> killedMonstersByTypeID = new HashMap<String, Integer>();
private final HashMap<String, Integer> killedMonstersByName = new HashMap<String, Integer>();
private final HashMap<String, Integer> usedItems = new HashMap<String, Integer>();
private int spentGold = 0;
private boolean unlimitedSaves = true;
@@ -33,10 +35,14 @@ public final class GameStatistics {
this.startLives = startLives;
}
public void addMonsterKill(String monsterTypeID) {
if (!killedMonsters.containsKey(monsterTypeID)) killedMonsters.put(monsterTypeID, 1);
else killedMonsters.put(monsterTypeID, killedMonsters.get(monsterTypeID) + 1);
public void addMonsterKill(MonsterType monsterType) {
// Track monster kills by type ID, for savegame file
killedMonstersByTypeID.put(monsterType.id, getNumberOfKillsForMonsterType(monsterType.id) + 1);
// Also track by name, for statistics display (multiple IDs w/same name don't matter to player)
killedMonstersByName.put(monsterType.name, getNumberOfKillsForMonsterName(monsterType.name) + 1);
}
public void addPlayerDeath(int lostExp) {
++deaths;
}
@@ -45,8 +51,7 @@ public final class GameStatistics {
}
public void addItemUsage(ItemType type) {
final String n = type.id;
if (!usedItems.containsKey(n)) usedItems.put(n, 1);
else usedItems.put(n, usedItems.get(n) + 1);
usedItems.put(n, HashMapHelper.getOrDefault(usedItems, n,0) + 1);
}
public int getDeaths() {
@@ -68,30 +73,30 @@ public final class GameStatistics {
public boolean isDead() { return !hasUnlimitedLives() && getLivesLeft() < 1; }
public int getNumberOfKillsForMonsterType(String monsterTypeID) {
Integer v = killedMonsters.get(monsterTypeID);
if (v == null) return 0;
return v;
return HashMapHelper.getOrDefault(killedMonstersByTypeID, monsterTypeID, 0);
}
public int getNumberOfKillsForMonsterName(String monsterName) {
return HashMapHelper.getOrDefault(killedMonstersByName, monsterName, 0);
}
public String getTop5MostCommonlyKilledMonsters(WorldContext world, Resources res) {
if (killedMonsters.isEmpty()) return null;
List<Entry<String, Integer>> entries = new ArrayList<Entry<String, Integer>>(killedMonsters.entrySet());
if (killedMonstersByTypeID.isEmpty()) return null;
List<Entry<String, Integer>> entries = new ArrayList<Entry<String, Integer>>(killedMonstersByName.entrySet());
Collections.sort(entries, descendingValueComparator);
StringBuilder sb = new StringBuilder(100);
int i = 0;
for (Entry<String, Integer> e : entries) {
if (i++ >= 5) break;
MonsterType t = world.monsterTypes.getMonsterType(e.getKey());
if (t == null) continue;
sb.append(res.getString(R.string.heroinfo_gamestats_name_and_qty, t.name, e.getValue())).append('\n');
sb.append(res.getString(R.string.heroinfo_gamestats_name_and_qty, e.getKey(), e.getValue())).append('\n');
}
return sb.toString();
}
public String getMostPowerfulKilledMonster(WorldContext world) {
if (killedMonsters.isEmpty()) return null;
HashMap<String, Integer> expPerMonsterType = new HashMap<String, Integer>(killedMonsters.size());
for (String monsterTypeID : killedMonsters.keySet()) {
if (killedMonstersByTypeID.isEmpty()) return null;
HashMap<String, Integer> expPerMonsterType = new HashMap<String, Integer>(killedMonstersByTypeID.size());
for (String monsterTypeID : killedMonstersByTypeID.keySet()) {
MonsterType t = world.monsterTypes.getMonsterType(monsterTypeID);
expPerMonsterType.put(monsterTypeID, t != null ? t.exp : 0);
}
@@ -135,20 +140,15 @@ public final class GameStatistics {
}
public int getNumberOfUsedItems() {
int result = 0;
for (int v : usedItems.values()) result += v;
return result;
return HashMapHelper.sumIntegerValues(usedItems);
}
public int getNumberOfTimesItemHasBeenUsed(String itemId) {
if (!usedItems.containsKey(itemId)) return 0;
return usedItems.get(itemId);
return HashMapHelper.getOrDefault(usedItems, itemId, 0);
}
public int getNumberOfKilledMonsters() {
int result = 0;
for (int v : killedMonsters.values()) result += v;
return result;
return HashMapHelper.sumIntegerValues(killedMonstersByTypeID);
}
private static final Comparator<Entry<String, Integer>> descendingValueComparator = new Comparator<Entry<String, Integer>>() {
@@ -172,8 +172,14 @@ public final class GameStatistics {
if (type == null) continue;
id = type.id;
}
this.killedMonsters.put(id, value);
this.killedMonstersByTypeID.put(id, value);
// Also track by name, for statistics display (multiple IDs w/same name don't matter to player)
MonsterType t = world.monsterTypes.getMonsterType(id);
if (t != null) killedMonstersByName.put(t.name, getNumberOfKillsForMonsterName(t.name) + value);
}
if (fileversion <= 17) return;
final int numItems = src.readInt();
@@ -192,7 +198,7 @@ public final class GameStatistics {
public void writeToParcel(DataOutputStream dest) throws IOException {
dest.writeInt(deaths);
Set<Entry<String, Integer> > set = killedMonsters.entrySet();
Set<Entry<String, Integer> > set = killedMonstersByTypeID.entrySet();
dest.writeInt(set.size());
for (Entry<String, Integer> e : set) {
dest.writeUTF(e.getKey());

View File

@@ -7,9 +7,6 @@ import java.io.IOException;
import com.gpl.rpg.AndorsTrail.context.ControllerContext;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.model.actor.Player;
import com.gpl.rpg.AndorsTrail.model.map.LayeredTileMap;
import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap;
import com.gpl.rpg.AndorsTrail.resource.tiles.TileCollection;
public final class ModelContainer {

View File

@@ -6,6 +6,8 @@ import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Calendar;
public final class WorldData {
private long worldTime = 0; // Measured in number of game rounds
private final HashMap<String, Long> timers = new HashMap<String, Long>();
@@ -36,6 +38,62 @@ public final class WorldData {
return v + duration <= worldTime;
}
public int getDate(String format) {
Calendar now = Calendar.getInstance();
int ret;
switch (format) {
case "YYYYMMDD":
ret = now.get(Calendar.YEAR)*10000 + (now.get(Calendar.MONTH) + 1)*100 + now.get(Calendar.DAY_OF_MONTH);
break;
case "YYYYMM":
ret = now.get(Calendar.YEAR)*100 + (now.get(Calendar.MONTH) + 1);
break;
case "YYYY":
ret = now.get(Calendar.YEAR);
break;
case "MMDD":
ret = (now.get(Calendar.MONTH) + 1)*100 + now.get(Calendar.DAY_OF_MONTH);
break;
case "MM":
ret = (now.get(Calendar.MONTH) + 1);
break;
case "DD":
ret = now.get(Calendar.DAY_OF_MONTH);
break;
default:
ret = 99999999; //never true
}
return ret;
}
public int getTime(String format) {
Calendar now = Calendar.getInstance();
int ret;
switch (format) {
case "HHMMSS":
ret = now.get(Calendar.HOUR_OF_DAY)*10000 + now.get(Calendar.MINUTE)*100 + now.get(Calendar.SECOND);
break;
case "HHMM":
ret = now.get(Calendar.HOUR_OF_DAY)*100 + now.get(Calendar.MINUTE);
break;
case "HH":
ret = now.get(Calendar.HOUR_OF_DAY);
break;
case "MMSS":
ret = now.get(Calendar.MINUTE)*100 + now.get(Calendar.SECOND);
break;
case "MM":
ret = now.get(Calendar.MINUTE);
break;
case "SS":
ret = now.get(Calendar.SECOND);
break;
default:
ret = 99999999; //never true
}
return ret;
}
// ====== PARCELABLE ===================================================================
public WorldData(DataInputStream src, int fileversion) throws IOException {

View File

@@ -4,8 +4,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import android.util.SparseArray;
import com.gpl.rpg.AndorsTrail.controller.Constants;
import com.gpl.rpg.AndorsTrail.model.ability.SkillInfo.SkillLevelRequirement;
import com.gpl.rpg.AndorsTrail.model.actor.Player;
@@ -85,7 +83,7 @@ public final class SkillCollection {
public static final int PER_SKILLPOINT_INCREASE_COINFINDER_CHANCE_PERCENT = 30;
public static final int PER_SKILLPOINT_INCREASE_MAGICFINDER_CHANCE_PERCENT = 50;
public static final int PER_SKILLPOINT_INCREASE_COINFINDER_QUANTITY_PERCENT = 50;
public static final int PER_SKILLPOINT_INCREASE_MORE_EXP_PERCENT = 5;
public static final int PER_SKILLPOINT_INCREASE_MORE_EXP_PERCENT = 10;
public static final int PER_SKILLPOINT_INCREASE_CLEAVE_AP = 3;
public static final int PER_SKILLPOINT_INCREASE_EATER_HEALTH = 1;
public static final int PER_SKILLPOINT_INCREASE_FORTITUDE_HEALTH = 1;

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