diff --git a/boards/bdFiles/bd10b b/boards/bdFiles/bd10b
index 8bf0a17cb..829e64a2e 100644
Binary files a/boards/bdFiles/bd10b and b/boards/bdFiles/bd10b differ
diff --git a/boards/bdFiles/bd11a b/boards/bdFiles/bd11a
index 27f628414..57cf25a11 100644
Binary files a/boards/bdFiles/bd11a and b/boards/bdFiles/bd11a differ
diff --git a/boards/bdFiles/bd13a b/boards/bdFiles/bd13a
index 502aa02d2..0300ae4d4 100644
Binary files a/boards/bdFiles/bd13a and b/boards/bdFiles/bd13a differ
diff --git a/boards/bdFiles/bd13b b/boards/bdFiles/bd13b
index a13dc2986..7af68da58 100644
Binary files a/boards/bdFiles/bd13b and b/boards/bdFiles/bd13b differ
diff --git a/boards/bdFiles/bd2b b/boards/bdFiles/bd2b
index 9b10aafaa..694994701 100644
Binary files a/boards/bdFiles/bd2b and b/boards/bdFiles/bd2b differ
diff --git a/boards/bdFiles/bd71 b/boards/bdFiles/bd71
index 3d7eb6bfa..00049adb7 100644
Binary files a/boards/bdFiles/bd71 and b/boards/bdFiles/bd71 differ
diff --git a/boards/bdFiles/bd7b b/boards/bdFiles/bd7b
index 0e3f8b0ad..817982202 100644
Binary files a/boards/bdFiles/bd7b and b/boards/bdFiles/bd7b differ
diff --git a/boards/bdFiles/bdAK1 b/boards/bdFiles/bdAK1
deleted file mode 100644
index 3c5dff8e2..000000000
Binary files a/boards/bdFiles/bdAK1 and /dev/null differ
diff --git a/boards/bdFiles/bdHOBI b/boards/bdFiles/bdHOBI
deleted file mode 100644
index 0b0bf0df9..000000000
Binary files a/boards/bdFiles/bdHOBI and /dev/null differ
diff --git a/boards/bdFiles/bdHOBII b/boards/bdFiles/bdHOBII
deleted file mode 100644
index 04b08d1ef..000000000
Binary files a/boards/bdFiles/bdHOBII and /dev/null differ
diff --git a/boards/bdFiles/bdNG b/boards/bdFiles/bdNG
index 286ab90d3..9acb0413c 100644
Binary files a/boards/bdFiles/bdNG and b/boards/bdFiles/bdNG differ
diff --git a/boards/bdFiles/bdSC b/boards/bdFiles/bdSC
index a1393f5ea..17f0d0355 100644
Binary files a/boards/bdFiles/bdSC and b/boards/bdFiles/bdSC differ
diff --git a/boards/bdFiles/bdSeoulN b/boards/bdFiles/bdSeoulN
deleted file mode 100644
index e69de29bb..000000000
diff --git a/boards/bdFiles/bdSeoulS b/boards/bdFiles/bdSeoulS
deleted file mode 100644
index e69de29bb..000000000
diff --git a/boards/bdFiles/bdSmithRidgeN b/boards/bdFiles/bdSmithRidgeN
deleted file mode 100644
index e69de29bb..000000000
diff --git a/boards/bdFiles/bdSmithRidgeS b/boards/bdFiles/bdSmithRidgeS
deleted file mode 100644
index e69de29bb..000000000
diff --git a/boards/bdFiles/bdTR1 b/boards/bdFiles/bdTR1
index 9ba2c4560..87d2fb4e8 100644
Binary files a/boards/bdFiles/bdTR1 and b/boards/bdFiles/bdTR1 differ
diff --git a/boards/bdFiles/bdTR2 b/boards/bdFiles/bdTR2
index 9190f03e9..18eb76471 100644
Binary files a/boards/bdFiles/bdTR2 and b/boards/bdFiles/bdTR2 differ
diff --git a/boards/bdFiles/bdTR3 b/boards/bdFiles/bdTR3
index d57ccbeac..679e94fb6 100644
Binary files a/boards/bdFiles/bdTR3 and b/boards/bdFiles/bdTR3 differ
diff --git a/boards/bdFiles/bdTR4 b/boards/bdFiles/bdTR4
index 191ba8edb..ba37d3abf 100644
Binary files a/boards/bdFiles/bdTR4 and b/boards/bdFiles/bdTR4 differ
diff --git a/boards/bdFiles/bdTR5 b/boards/bdFiles/bdTR5
index 1bc464b9b..9526074a9 100644
Binary files a/boards/bdFiles/bdTR5 and b/boards/bdFiles/bdTR5 differ
diff --git a/boards/bdFiles/bdTR6 b/boards/bdFiles/bdTR6
index 25544be19..c3ed82466 100644
Binary files a/boards/bdFiles/bdTR6 and b/boards/bdFiles/bdTR6 differ
diff --git a/boards/bdFiles/bdTR7 b/boards/bdFiles/bdTR7
index 27b8917d3..1167f50a0 100644
Binary files a/boards/bdFiles/bdTR7 and b/boards/bdFiles/bdTR7 differ
diff --git a/boards/bdFiles/bdTR8 b/boards/bdFiles/bdTR8
index d54a30a4a..36883866f 100644
Binary files a/boards/bdFiles/bdTR8 and b/boards/bdFiles/bdTR8 differ
diff --git a/boards/v5boardVersions.xml b/boards/v5boardVersions.xml
index 007953ba1..a961ca45f 100644
--- a/boards/v5boardVersions.xml
+++ b/boards/v5boardVersions.xml
@@ -83,19 +83,19 @@
-
-
+
+
-
+
-
+
-
+
@@ -105,9 +105,9 @@
-
-
-
+
+
+
@@ -262,8 +262,6 @@
-
-
@@ -285,7 +283,6 @@
-
@@ -293,7 +290,7 @@
-
+
@@ -328,7 +325,7 @@
-
+
@@ -381,6 +378,7 @@
+
@@ -388,6 +386,7 @@
+
@@ -475,8 +474,9 @@
+
-
+
diff --git a/dist/Whats New VASL670 b/dist/Whats New VASL670
new file mode 100644
index 000000000..f6d925c6e
--- /dev/null
+++ b/dist/Whats New VASL670
@@ -0,0 +1,8 @@
+1) Top concealment counter can now be made transparent for owner of non-dummy stack so they can see top unit. This feature can be turned on/off in preference tab
+2) Change was made to buildFile such that when a special ammo is selected as depleted, it automatically displays below counter
+3) Fixed bug where concealed broken sw was being revealed by the report broken/mal sw/gun button
+4) Minor fix to the LOS check function so that checking los to a depression hex containing multiple center locations is accurate
+5) Implementation of autosave feature. Creates save files every 10 minutes in users "board" directory. Maximum of 20 files created. Can be turned on/off in preferences tab.
+6) Removed deluxe hex size option
+7) Reordered the boards when selecing a map and added a searchbox feature
+8) Changed implementation of concealment counters. Now we try to take into consideration multiple locations within a hex denoted by counters (e.g. building levels)
diff --git a/dist/buildFile b/dist/buildFile
index 49b8ea18a..1e49474a7 100644
--- a/dist/buildFile
+++ b/dist/buildFile
@@ -1,5 +1,5 @@
-
+
@@ -18,6 +18,7 @@
+
@@ -43,7 +44,7 @@
-
+
@@ -397,8 +398,8 @@
+/null/prototype;DBCommon hide;72,130;HIP;;player:;0.30000001192092896;;false\ label;76,130;Label;10;255,255,255;0,0,0;t;0;c;0;b;c;$pieceName$ ($label$);Dialog;0;0;TextLabel;;false\\ emb2;;2;;Emerge;2;E;;2;;;;0;false;0;0; ,ML\/SewerE,ML\/SewerC,ML\/SewerD;,+ Can Emerge,+ Can't Emerge,+ Discovered;true;;;;false;;1;1;true;;69,130;;;1.0;;true\\\ emb2;;128;A;Lost;128;;;128;;;;0;false;0;0;ML\/Sewer,ML\/SewerB;Sewer,Sewer - Lost;true;;;;false;;1;1;true;;83,130;;;1.0;;true\\\\ moved;moved58\\\\\ piece;K;D;ML\/_sewer58;Sewer/ null\ \\ 3\\\ 1\\\\ false\\\\\ null;0;0;153;1;ppScale;1.0
- +/null/prototype;DBGlobal label;76,130;Label;10;255,255,255;0,0,0;t;0;c;0;b;c;$pieceName$ ($label$);Dialog;0;0;TextLabel;;false\ emb2;;2;;cw;2;X;ccw;2;Z;;;0;false;0;0;ML\/Bridge14,ML\/Bridge25,ML\/Bridge36;+: 1-4,+: 2-5,+: 3-6;true;;;;false;;1;1;true;;88,130;90,130;;1.0;;true\\ mark;Hindrance\\\ mark;Location\\\\ piece;K;D;ML\/_white58;Bridge/ \ 1\\ true\\\ \\\\ null;0;0;154;0
- +/null/prototype;DBGlobal label;76,130;Label;10;255,255,255;0,0,0;t;0;c;0;b;c;$pieceName$ ($label$);Dialog;0;0;TextLabel;;false\ emb2;;2;;cw;2;X;ccw;2;Z;;;0;false;0;0;MS\/Ftbridge14,MS\/Ftbridge25,MS\/Ftbridge36;Footbridge: 1-4,Footbridge: 2-5,Footbridge: 3-6;true;;;;false;;1;1;true;;88,130;90,130;;1.0;;true\\ mark;Location\\\ piece;K;D;MS\/_water12;Bridge Foot/ \ 1\\ \\\ null;0;0;155;0
+ +/null/prototype;Location prototype;DBGlobal\ label;76,130;Label;10;255,255,255;0,0,0;t;0;c;0;b;c;$pieceName$ ($label$);Dialog;0;0;TextLabel;;false\\ emb2;;2;;cw;2;X;ccw;2;Z;;;0;false;0;0;ML\/Bridge14,ML\/Bridge25,ML\/Bridge36;+: 1-4,+: 2-5,+: 3-6;true;;;;false;;1;1;true;;88,130;90,130;;1.0;;true\\\ mark;Hindrance\\\\ mark;Location\\\\\ piece;K;D;ML\/_white58;Bridge/ \ \\ 1\\\ true\\\\ \\\\\ null;0;0;;0
+ +/null/prototype;DBGlobal label;76,130;Label;10;255,255,255;0,0,0;t;0;c;0;b;c;$pieceName$ ($label$);Dialog;0;0;TextLabel;;false\ emb2;;2;;cw;2;X;ccw;2;Z;;;0;false;0;0;MS\/Ftbridge14,MS\/Ftbridge25,MS\/Ftbridge36;Footbridge: 1-4,Footbridge: 2-5,Footbridge: 3-6;true;;;;false;;1;1;true;;88,130;90,130;;1.0;;true\\ mark;Location\\\ piece;K;D;MS\/_water12;Bridge Foot/ \ 1\\ \\\ null;0;0;;0
+/null/prototype;DBGlobal label;76,130;Label;10;255,255,255;0,0,0;t;0;c;0;b;c;$pieceName$ ($label$);Dialog;0;0;TextLabel;;false\ emb2;;2;;cw;2;X;ccw;2;Z;;;0;false;0;0;ML\/BridgeL14,ML\/BridgeL25,ML\/BridgeL36;Heavy Bridge: 1-4,Heavy Bridge: 2-5,Heavy Bridge: 3-6;true;;;;false;;1;1;true;;88,130;90,130;;1.0;;true\\ mark;Hindrance\\\ mark;Location\\\\ piece;K;D;ML\/_water58;Bridge Heavy/ \ 1\\ true\\\ \\\\ null;0;0;156;0
+/null/prototype;DBGlobal label;76,130;Label;10;255,255,255;0,0,0;t;0;c;0;b;c;$pieceName$ ($label$);Dialog;0;0;TextLabel;;false\ emb2;;2;;cw;2;X;ccw;2;Z;;;0;false;0;0;ML\/BridgeP14,ML\/BridgeP25,ML\/BridgeP36;Pontoon Bridge: 1-4,Pontoon Bridge: 2-5,Pontoon Bridge: 3-6;true;;;;false;;1;1;true;;88,130;90,130;;1.0;;true\\ mark;Hindrance\\\ mark;Location\\\\ piece;K;D;ML\/_water58;Bridge Pontoon/ \ 1\\ true\\\ \\\\ null;0;0;157;0
+/null/prototype;DBGlobal placemark;Troll;84,130;+\/null\/delete\;Delete\;D\\ piece\;\;\;MS\\/ctrtroll\;countertroll\/\\ null\;24\;24;null;0;0;false;;;159;0;false;false;\ label;76,130;Label;10;255,255,255;0,0,0;t;0;c;0;b;c;$pieceName$ ($label$);Dialog;0;0;TextLabel;;false\\ emb2;;2;;cw;2;X;ccw;2;Z;;;0;false;0;0;ML\/BridgeX14,ML\/BridgeX25,ML\/BridgeX36;+ 1-4,+ 2-5,+ 3-6;true;;;;false;;1;1;true;;88,130;90,130;;1.0;;true\\\ mark;Location\\\\ piece;K;D;ML\/_white58;Dstr Bridge/ \ \\ 1\\\ \\\\ null;0;0;158;0
@@ -407,18 +408,18 @@
+/null/prototype;DBGlobal hide;72,130;HIP;;player:;0.30000001192092896;;false\ label;76,130;Label;10;255,255,255;0,0,0;t;0;c;0;b;c;$pieceName$ ($label$);Dialog;0;0;TextLabel;;false\\ emb2;;2;;Int \/ Des;2;F;;2;;;;0;false;0;0; ,ML\/pierIntO,ML\/pierDesO;,Interdicted +,Destroyed +;true;;;;false;;1;1;true;;70,130;;;1.0;;true\\\ emb2;Type;2;T;;2;X;;2;Z;;;0;false;0;0;ML\/PierS14,ML\/PierS25,ML\/PierS36;Stone Pier 1-4,Stone Pier 2-5,Stone Pier 3-6;true;;;;false;;1;1;false;84,130;88,130;90,130;;1.0;;true\\\\ mark;Hindrance\\\\\ mark;Location\\\\\\ emb2;;2;;cw;2;X;ccw;2;Z;;;0;false;0;0;ML\/PierW14,ML\/PierW25,ML\/PierW36;Wood Pier 1-4,Wood Pier 2-5,Wood Pier 3-6;true;;;;false;;1;1;true;;88,130;90,130;;1.0;;true\\\\\\\ piece;K;D;ML\/_water58;Pier/ null\ \\ 1\\\ 1\\\\ true\\\\\ \\\\\\ 1\\\\\\\ null;0;0;5843;0
- +/null/prototype;DBCommon hide;72,130;HIP;;player:;0.30000001192092896;;false\ label;76,130;Label;10;255,255,255;0,0,0;t;0;c;0;b;c;$pieceName$ ($label$);Dialog;0;0;TextLabel;;false\\ emb2;;2;;Higher;2;];Lower;2;[;;;0;false;0;0;ML\/Lev-1,ML\/Lev0,ML\/Lev1,ML\/Lev2,ML\/Lev3,ML\/LevRoof;+ Cellar,+ Ground Level,+ Level 1,+ Level 2,+ Level 3,+ Roof Level;true;;;;false;;1;1;true;;93,130;91,130;;1.0;;true\\\ piece;K;D;ML\/_white58;Building/ null\ \\ 5\\\ null;0;0;163;0
- +/null/prototype;DBCommon hide;72,130;HIP;;player:;0.30000001192092896;;false\ label;76,130;Label;10;255,255,255;0,0,0;t;0;c;0;b;c;$pieceName$ ($label$);Dialog;0;0;TextLabel;;false\\ emb2;;2;;Higher;2;];Lower;2;[;;;0;false;0;0;ML\/Lev-1,ML\/Lev0,ML\/Lev1,ML\/Lev2,ML\/Lev3,ML\/LevRoof;+ Cellar,+ Ground Level,+ Level 1,+ Level 2,+ Level 3,+ Roof Level;true;;;;false;;1;1;true;;93,130;91,130;;1.0;;true\\\ piece;K;D;ML\/_white58;Building/ null\ \\ 6\\\ null;0;0;165;0
- +/null/prototype;DBCommon hide;72,130;HIP;;player:;0.30000001192092896;;false\ label;76,130;Label;10;255,255,255;0,0,0;t;0;c;0;b;c;$pieceName$ ($label$);Dialog;0;0;TextLabel;;false\\ emb2;;2;;Higher;2;];Lower;2;[;;;0;false;0;0;ML\/Lev-1,ML\/Lev0,ML\/Lev1,ML\/Lev2,ML\/Lev3,ML\/LevRoof;+ Cellar,+ Ground Level,+ Level 1,+ Level 2,+ Level 3,+ Roof Level;true;;;;false;;1;1;true;;93,130;91,130;;1.0;;true\\\ piece;K;D;ML\/_white58;Building/ null\ \\ 3\\\ null;0;0;167;0
- +/null/prototype;DBCommon hide;72,130;HIP;;player:;0.30000001192092896;;false\ label;76,130;Label;10;255,255,255;0,0,0;t;0;c;0;b;c;$pieceName$ ($label$);Dialog;0;0;TextLabel;;false\\ emb2;;2;;Higher;2;];Lower;2;[;;;0;false;0;0;ML\/Lev-1,ML\/Lev0,ML\/Lev1,ML\/Lev2,ML\/Lev3,ML\/LevRoof;+ Cellar,+ Ground Level,+ Level 1,+ Level 2,+ Level 3,+ Roof Level;true;;;;false;;1;1;true;;93,130;91,130;;1.0;;true\\\ piece;K;D;ML\/_white58;Building/ null\ \\ 4\\\ null;0;0;169;0
- +/null/prototype;DBCommon hide;72,130;HIP;;player:;0.30000001192092896;;false\ label;76,130;Label;10;255,255,255;0,0,0;t;0;c;0;b;c;$pieceName$ ($label$);Dialog;0;0;TextLabel;;false\\ emb2;;2;;Higher;2;];Lower;2;[;;;0;false;0;0;ML\/Lev-1,ML\/Lev0,ML\/Lev1,ML\/Lev2,ML\/Lev3,ML\/LevRoof;+ Cellar,+ Ground Level,+ Level 1,+ Level 2,+ Level 3,+ Roof Level;true;;;;false;;1;1;true;;93,130;91,130;;1.0;;true\\\ piece;K;D;ML\/_white58;Building/ null\ \\ 1\\\ null;0;0;171;0
- +/null/prototype;DBCommon hide;72,130;HIP;;player:;0.30000001192092896;;false\ label;76,130;Label;10;255,255,255;0,0,0;t;0;c;0;b;c;$pieceName$ ($label$);Dialog;0;0;TextLabel;;false\\ emb2;;2;;Higher;2;];Lower;2;[;;;0;false;0;0;ML\/Lev-1,ML\/Lev0,ML\/Lev1,ML\/Lev2,ML\/Lev3,ML\/LevRoof;+ Cellar,+ Ground Level,+ Level 1,+ Level 2,+ Level 3,+ Roof Level;true;;;;false;;1;1;true;;93,130;91,130;;1.0;;true\\\ piece;K;D;ML\/_white58;Building/ null\ \\ 2\\\ null;0;0;173;0
+ +/null/prototype;Location prototype;DBCommon\ hide;72,130;HIP;;player:;0.30000001192092896;;false\\ label;76,130;Label;10;255,255,255;0,0,0;t;0;c;0;b;c;$pieceName$ ($label$);Dialog;0;0;TextLabel;;false\\\ emb2;;2;;Higher;2;];Lower;2;[;;;0;false;0;0;ML\/Lev-1,ML\/Lev0,ML\/Lev1,ML\/Lev2,ML\/Lev3,ML\/LevRoof;+ Cellar,+ Ground Level,+ Level 1,+ Level 2,+ Level 3,+ Roof Level;true;;;;false;;1;1;true;;93,130;91,130;;1.0;;true\\\\ piece;K;D;ML\/_white58;Building/ \ null\\ \\\ 5\\\\ null;0;0;;0
+ +/null/prototype;Location prototype;DBCommon\ hide;72,130;HIP;;player:;0.30000001192092896;;false\\ label;76,130;Label;10;255,255,255;0,0,0;t;0;c;0;b;c;$pieceName$ ($label$);Dialog;0;0;TextLabel;;false\\\ emb2;;2;;Higher;2;];Lower;2;[;;;0;false;0;0;ML\/Lev-1,ML\/Lev0,ML\/Lev1,ML\/Lev2,ML\/Lev3,ML\/LevRoof;+ Cellar,+ Ground Level,+ Level 1,+ Level 2,+ Level 3,+ Roof Level;true;;;;false;;1;1;true;;93,130;91,130;;1.0;;true\\\\ piece;K;D;ML\/_white58;Building/ \ null\\ \\\ 6\\\\ null;0;0;;0
+ +/null/prototype;Location prototype;DBCommon\ hide;72,130;HIP;;player:;0.30000001192092896;;false\\ label;76,130;Label;10;255,255,255;0,0,0;t;0;c;0;b;c;$pieceName$ ($label$);Dialog;0;0;TextLabel;;false\\\ emb2;;2;;Higher;2;];Lower;2;[;;;0;false;0;0;ML\/Lev-1,ML\/Lev0,ML\/Lev1,ML\/Lev2,ML\/Lev3,ML\/LevRoof;+ Cellar,+ Ground Level,+ Level 1,+ Level 2,+ Level 3,+ Roof Level;true;;;;false;;1;1;true;;93,130;91,130;;1.0;;true\\\\ piece;K;D;ML\/_white58;Building/ \ null\\ \\\ 3\\\\ null;0;0;;0
+ +/null/prototype;Location prototype;DBCommon\ hide;72,130;HIP;;player:;0.30000001192092896;;false\\ label;76,130;Label;10;255,255,255;0,0,0;t;0;c;0;b;c;$pieceName$ ($label$);Dialog;0;0;TextLabel;;false\\\ emb2;;2;;Higher;2;];Lower;2;[;;;0;false;0;0;ML\/Lev-1,ML\/Lev0,ML\/Lev1,ML\/Lev2,ML\/Lev3,ML\/LevRoof;+ Cellar,+ Ground Level,+ Level 1,+ Level 2,+ Level 3,+ Roof Level;true;;;;false;;1;1;true;;93,130;91,130;;1.0;;true\\\\ piece;K;D;ML\/_white58;Building/ \ null\\ \\\ 4\\\\ null;0;0;;0
+ +/null/prototype;Location prototype;DBCommon\ hide;72,130;HIP;;player:;0.30000001192092896;;false\\ label;76,130;Label;10;255,255,255;0,0,0;t;0;c;0;b;c;$pieceName$ ($label$);Dialog;0;0;TextLabel;;false\\\ emb2;;2;;Higher;2;];Lower;2;[;;;0;false;0;0;ML\/Lev-1,ML\/Lev0,ML\/Lev1,ML\/Lev2,ML\/Lev3,ML\/LevRoof;+ Cellar,+ Ground Level,+ Level 1,+ Level 2,+ Level 3,+ Roof Level;true;;;;false;;1;1;true;;93,130;91,130;;1.0;;true\\\\ piece;K;D;ML\/_white58;Building/ \ null\\ \\\ 1\\\\ null;0;0;;0
+ +/null/prototype;Location prototype;DBCommon\ hide;72,130;HIP;;player:;0.30000001192092896;;false\\ label;76,130;Label;10;255,255,255;0,0,0;t;0;c;0;b;c;$pieceName$ ($label$);Dialog;0;0;TextLabel;;false\\\ emb2;;2;;Higher;2;];Lower;2;[;;;0;false;0;0;ML\/Lev-1,ML\/Lev0,ML\/Lev1,ML\/Lev2,ML\/Lev3,ML\/LevRoof;+ Cellar,+ Ground Level,+ Level 1,+ Level 2,+ Level 3,+ Roof Level;true;;;;false;;1;1;true;;93,130;91,130;;1.0;;true\\\\ piece;K;D;ML\/_white58;Building/ \ null\\ \\\ 2\\\\ null;0;0;;0
- +/null/hide;72,130;HIP;;player:;0.30000001192092896;;false label;76,130;Label;10;255,255,255;0,0,0;t;0;c;0;b;c;$pieceName$ ($label$);Dialog;0;0;TextLabel;;false\ emb2;;2;;Higher;2;;Lower;2;;;;0;false;0;0;ML\/Steeple1.gif,ML\/Steeple2.gif,ML\/Steeple3.gif;+ Level 1,+ Level 2,+ Level 3;true;;;;false;;1;1;true;;93,130;91,130;;1.0;;true\\ piece;K;D;ML\/_white58;Steeple/null \ 3\\ null;0;0;7443;0
- +/null/hide;72,130;HIP;;player:;0.30000001192092896;;false label;76,130;Label;10;255,255,255;0,0,0;t;0;c;0;b;c;$pieceName$ ($label$);Dialog;0;0;TextLabel;;false\ emb2;;2;;Higher;2;;Lower;2;;;;0;false;0;0;ML\/Steeple1.gif,ML\/Steeple2.gif,ML\/Steeple3.gif;+ Level 1,+ Level 2,+ Level 3;true;;;;false;;1;1;true;;93,130;91,130;;1.0;;true\\ piece;K;D;ML\/_white58;Steeple/null \ 2\\ null;0;0;7445;0
- +/null/hide;72,130;HIP;;player:;0.30000001192092896;;false label;76,130;Label;10;255,255,255;0,0,0;t;0;c;0;b;c;$pieceName$ ($label$);Dialog;0;0;TextLabel;;false\ emb2;;2;;Higher;2;;Lower;2;;;;0;false;0;0;ML\/Steeple1.gif,ML\/Steeple2.gif,ML\/Steeple3.gif;+ Level 1,+ Level 2,+ Level 3;true;;;;false;;1;1;true;;93,130;91,130;;1.0;;true\\ piece;K;D;ML\/_white58;Steeple/null \ 1\\ null;0;0;7448;0
- +/null/prototype;StairOverlayProperties emb2;Activate;128;A;Change level;128;;;128;;;;1;false;0;0;Steeple3b.gif,Steeple1b.gif,Steeple2b.gif;,,;true;;;;false;;1;1;true;65,130;70,130;;;1.0;;true\ piece;;;;Steeple/ 1\ null;0;0;14341;1;ppScale;1.0
+ +/null/prototype;Location hide;72,130;HIP;;player:;0.30000001192092896;;false\ label;76,130;Label;10;255,255,255;0,0,0;t;0;c;0;b;c;$pieceName$ ($label$);Dialog;0;0;TextLabel;;false\\ emb2;;2;;Higher;2;;Lower;2;;;;0;false;0;0;ML\/Steeple1.gif,ML\/Steeple2.gif,ML\/Steeple3.gif;+ Level 1,+ Level 2,+ Level 3;true;;;;false;;1;1;true;;93,130;91,130;;1.0;;true\\\ piece;K;D;ML\/_white58;Steeple/ null\ \\ 3\\\ null;0;0;;0
+ +/null/prototype;Location hide;72,130;HIP;;player:;0.30000001192092896;;false\ label;76,130;Label;10;255,255,255;0,0,0;t;0;c;0;b;c;$pieceName$ ($label$);Dialog;0;0;TextLabel;;false\\ emb2;;2;;Higher;2;;Lower;2;;;;0;false;0;0;ML\/Steeple1.gif,ML\/Steeple2.gif,ML\/Steeple3.gif;+ Level 1,+ Level 2,+ Level 3;true;;;;false;;1;1;true;;93,130;91,130;;1.0;;true\\\ piece;K;D;ML\/_white58;Steeple/ null\ \\ 2\\\ null;0;0;;0
+ +/null/prototype;Location hide;72,130;HIP;;player:;0.30000001192092896;;false\ label;76,130;Label;10;255,255,255;0,0,0;t;0;c;0;b;c;$pieceName$ ($label$);Dialog;0;0;TextLabel;;false\\ emb2;;2;;Higher;2;;Lower;2;;;;0;false;0;0;ML\/Steeple1.gif,ML\/Steeple2.gif,ML\/Steeple3.gif;+ Level 1,+ Level 2,+ Level 3;true;;;;false;;1;1;true;;93,130;91,130;;1.0;;true\\\ piece;K;D;ML\/_white58;Steeple/ null\ \\ 1\\\ null;0;0;;0
+ +/null/prototype;StairOverlayProperties emb2;Activate;128;A;Change level;128;;;128;;;;1;false;0;0;Steeple3b.gif,Steeple1b.gif,Steeple2b.gif;,,;true;;;;false;;1;1;true;65,130;70,130;;;1.0;;true\ piece;;;;Steeple/ 1\ null;0;0;;1;ppScale;1.0
+/null/prototype;StairOverlayProperties emb2;Activate;128;A;Change level;128;;;128;;;;1;false;0;0;StairDavid3.gif,StairDavid1.gif,StairDavid2.gif;,,;true;;;;false;;1;1;true;65,130;70,130;;;1.0;;true\ piece;;;;Synagogue/ 1\ null;0;0;14346;1;ppScale;1.0
+/null/prototype;StairOverlayProperties emb2;Activate;128;A;Change level;128;;;128;;;;1;false;0;0;Mosque3.gif,Mosque1.gif,Mosque2.gif;,,;true;;;;false;;1;1;true;65,130;70,130;;;1.0;;true\ piece;;;;Minaret/ 1\ null;0;0;14344;1;ppScale;1.0
+/null/prototype;StairOverlayProperties emb2;Activate;128;A;Change level;128;;;128;;;;1;false;0;0;Stairwell3.gif,Stairwell2.gif,Stairwells.gif,Stairwellw.gif,Stairwells3.gif,Stairwellw3.gif;level 3,level 2,none-stone,none-wood,,;true;;;;false;;1;1;true;65,130;70,130;;;1.0;;true\ piece;;;;Stairwell/ 1\ null;0;0;14342;1;ppScale;1.0
@@ -7348,6 +7349,7 @@
+/null/hide;72,130;Invisible;;player:;0.5;;true immob;i;I;R;\ clone;Clone;67,130;\\ delete;Delete;68,130;\\\ mark;overlay\\\\ piece;;;;/null \ \\ \\\ true\\\\ null;0;0;;0
+/null/footprint;85,130;Movement Trail;false;false;4;255,0,0;0,0,0;100;0;0;0;1.0;;;77,130; piece;;;;/false;;0;false null;37;32;;0
+/null/footprint;85,130;Movement Trail;false;false;2;51,255,255;0,0,0;100;0;0;0;1.0;;;77,130; piece;;;;/false;;0;false null;37;32;;0
+ +/null/mark;separateLocation piece;;;;/true null;37;32;;0
diff --git a/dist/release-notes.md b/dist/release-notes.md
index f309a2e81..43f934b07 100644
--- a/dist/release-notes.md
+++ b/dist/release-notes.md
@@ -1,6 +1,6 @@
-# Release Notes: Version 6.7.0
+# Release Notes: Version 6.7.0-beta1
-**Release Date:** Nov 19th 2024
+**Release Date:** Nov 19th 2024
---
diff --git a/pom.xml b/pom.xml
index 5a49151f8..cc04bc7b5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
org.vasl
vasl
- 6.7.0
+ 6.7.0-beta1
jar
@@ -17,7 +17,7 @@
org.vassalengine
vassal-app
- 3.7.14
+ 3.7.15
diff --git a/scripts/test_pre_push.sh b/scripts/test_pre_push.sh
index 84e75de64..eb212eba3 100644
--- a/scripts/test_pre_push.sh
+++ b/scripts/test_pre_push.sh
@@ -82,32 +82,37 @@ for board_file in "$BD_FILES_DIR"/*; do
metadata_file=""
if [[ "$file_type" == *"Zip archive data"* ]]; then
- # Extract from ZIP archive
+
if command -v unzip &> /dev/null; then
- unzip -q -j "$board_file" -d "$TEMP_DIR" "*[Bb]oard[Mm]etadata.xml*" "data" 2>/dev/null
+ # List the ZIP file's contents
+ zip_contents=$(unzip -l "$board_file" | awk '{print $4}' | tail -n +4 | head -n -2)
+
+ # Check if either BoardMetadata.xml or data exists in the root directory
+ has_board_metadata=$(echo "$zip_contents" | grep -q "^BoardMetadata.xml$"; echo $?)
+ has_data=$(echo "$zip_contents" | grep -q "^data$"; echo $?)
+
+ # If neither file is found, print a warning message
+ if [[ $has_board_metadata -ne 0 && $has_data -ne 0 ]]; then
+ warnings+=("Warning: Neither BoardMetadata.xml nor data file is present in the root of $board_file.")
+ continue
+ fi
- if [[ -f "$TEMP_DIR/BoardMetadata.xml" ]]; then
+ # Extract the file that is present for further validation
+ if [[ $has_board_metadata -eq 0 ]]; then
+ unzip -q -j "$board_file" "BoardMetadata.xml" -d "$TEMP_DIR" 2>/dev/null
metadata_file="$TEMP_DIR/BoardMetadata.xml"
- elif [[ -f "$TEMP_DIR/boardMetadata.xml" ]]; then
- metadata_file="$TEMP_DIR/boardMetadata.xml"
- elif [[ -f "$TEMP_DIR/data" ]]; then
+ elif [[ $has_data -eq 0 ]]; then
+ unzip -q -j "$board_file" "data" -d "$TEMP_DIR" 2>/dev/null
metadata_file="$TEMP_DIR/data"
- else
- warnings+=("Warning: Neither BoardMetadata.xml nor data file found in $board_file.")
- continue
fi
else
echo "Error: unzip command is not available."
exit 1
fi
- elif [[ "$file_type" == *"ASCII text"* || "$file_type" == *"UTF-8 Unicode text"* ]]; then
- # Treat as plain text file
- metadata_file="$board_file"
- else
- warnings+=("Warning: Unsupported file type for $board_file. Skipping.")
- continue
+
fi
+
zip_version=$(extract_version "$metadata_file")
expected_version=$(echo "$expected_version" | tr -d '\r' | xargs) # Trim whitespace and carriage returns
diff --git a/src/VASL/build/module/ASLAutoSave.java b/src/VASL/build/module/ASLAutoSave.java
new file mode 100644
index 000000000..e594d97fb
--- /dev/null
+++ b/src/VASL/build/module/ASLAutoSave.java
@@ -0,0 +1,147 @@
+package VASL.build.module;
+
+import VASSAL.build.AbstractBuildable;
+import VASSAL.build.Buildable;
+import VASSAL.build.GameModule;
+import VASSAL.build.module.GameState;
+import VASSAL.configure.BooleanConfigurer;
+import VASSAL.preferences.Prefs;
+
+import java.io.File;
+import java.io.IOException;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Timer;
+import java.util.TimerTask;
+
+public class ASLAutoSave extends AbstractBuildable {
+ private static final String AUTOSAVE_OPTION = "autosave";
+ private static final int AUTOSAVE_INTERVAL_MS = 10 * 60 * 1000; // Autosave interval in milliseconds (10 minutes)
+ private static final int AUTOSAVE_DELAY_MS = 60 * 1000; // Initial delay before starting autosave (1 minute)
+ private static final int MAX_AUTOSAVE_FILES = 20; // Maximum number of autosave files to retain
+ private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HHmm");
+
+ private final Timer timer;
+ private boolean usingAutosave = false;
+ private final GameModule gameModule;
+ private final GameState gameState;
+ private final String directory;
+
+ public ASLAutoSave() {
+ this.gameModule = GameModule.getGameModule();
+ this.gameState = gameModule.getGameState();
+ this.timer = new Timer(true); // Daemon timer to handle autosave
+ this.directory = initializeDirectory();
+ }
+
+ /**
+ * Initializes the autosave directory based on game preferences.
+ * @return the autosave directory path
+ */
+ private String initializeDirectory() {
+ String dirPath = gameModule.getPrefs().getStoredValue("boardURL") + File.separator + gameModule.getGameName();
+ File dir = new File(dirPath);
+ if (!dir.exists() && !dir.mkdirs()) {
+ gameModule.warn("Failed to create autosave directory: " + dirPath); // Log a warning if directory creation fails
+ }
+ return dirPath;
+ }
+
+ /**
+ * Starts the autosave timer to periodically save the game.
+ */
+ public void startAutoSave() {
+ timer.scheduleAtFixedRate(new TimerTask() {
+ @Override
+ public void run() {
+ if (!usingAutosave || !gameState.isGameStarted()) {
+ return; // Exit if autosave is disabled or game is not started
+ }
+ deleteOldestFilesIfNeeded();
+ saveGame();
+ }
+ }, AUTOSAVE_DELAY_MS, AUTOSAVE_INTERVAL_MS);
+ }
+
+ /**
+ * Saves the current game state to a file with a timestamped filename.
+ */
+ private void saveGame() {
+ String autosaveFileName = directory + File.separator + "autosave " + getCurrentDateTime() + ".vsav";
+ File autosaveFile = new File(autosaveFileName);
+ try {
+ gameModule.warn("Autosaving game to: " + directory);
+ gameState.saveGame(autosaveFile);
+ } catch (IOException e) {
+ gameModule.warn("Failed to save autosave file: " + autosaveFileName + "\n" + e.getMessage());
+ }
+ }
+
+ /**
+ * Deletes the oldest autosave files if the maximum file limit is exceeded.
+ */
+ private void deleteOldestFilesIfNeeded() {
+ File dir = new File(directory);
+ File[] files = dir.listFiles((d, name) -> name.startsWith("autosave") && name.endsWith(".vsav"));
+ if (files != null && files.length > MAX_AUTOSAVE_FILES) {
+ Arrays.sort(files, Comparator.comparingLong(File::lastModified));
+ for (int i = 0; i < files.length - MAX_AUTOSAVE_FILES; i++) {
+ if (!files[i].delete()) {
+ gameModule.warn("Failed to delete old autosave file: " + files[i].getName());
+ }
+ }
+ }
+ }
+
+ /**
+ * Retrieves the current date and time as a formatted string.
+ * @return current date and time as string
+ */
+ private String getCurrentDateTime() {
+ return LocalDateTime.now().format(DATE_TIME_FORMATTER);
+ }
+
+ /**
+ * Stops the autosave timer, canceling any future scheduled saves.
+ */
+ public void stopAutoSave() {
+ timer.cancel();
+ }
+
+ @Override
+ public void addTo(Buildable parent) {
+ final Prefs modulePrefs = ((GameModule) parent).getPrefs();
+ BooleanConfigurer autoSaveOption = (BooleanConfigurer) modulePrefs.getOption(AUTOSAVE_OPTION);
+
+ if (autoSaveOption == null) {
+ autoSaveOption = new BooleanConfigurer(AUTOSAVE_OPTION, "AutoSave game every 10 minutes", Boolean.TRUE);
+ modulePrefs.addOption("VASL", autoSaveOption);
+ }
+
+ // Initialize usingAutosave based on saved preferences
+ usingAutosave = (Boolean) modulePrefs.getValue(AUTOSAVE_OPTION);
+
+ // Listen for changes to the autosave preference, updating usingAutosave in real-time
+ autoSaveOption.addPropertyChangeListener(e -> usingAutosave = (Boolean) e.getNewValue());
+
+ // Start the autosave timer (it will check usingAutosave each time it runs)
+ startAutoSave();
+ }
+
+ @Override
+ public String[] getAttributeNames() {
+ return new String[0]; // No attributes to expose
+ }
+
+ @Override
+ public void setAttribute(String key, Object value) {
+ // Method intentionally left blank; no attributes to set
+ }
+
+ @Override
+ public String getAttributeValueString(String key) {
+ return null; // No attribute values to return
+ }
+}
diff --git a/src/VASL/build/module/map/ASLBoardPicker.java b/src/VASL/build/module/map/ASLBoardPicker.java
index 883712845..6285e1ddc 100644
--- a/src/VASL/build/module/map/ASLBoardPicker.java
+++ b/src/VASL/build/module/map/ASLBoardPicker.java
@@ -71,6 +71,16 @@
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import javax.swing.*;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.Timer;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.time.temporal.ChronoUnit;
import static java.time.temporal.ChronoUnit.DAYS;
@@ -88,9 +98,10 @@ public class ASLBoardPicker extends BoardPicker implements ActionListener {
private File boardDir;
protected TerrainEditor terrain;
private SetupControls setupControls;
- private boolean enableDeluxe;
private boolean enableDB = false;
private boolean preservelevels;
+ private DirectoryConfigurer dirConfig;
+ private ListSelectionListener listSelectionListener;
// implement using xml file for board versions
private static final String boardsFileElement = "boardsMetadata";
@@ -269,119 +280,101 @@ public void initTerrainEditor() {
* Reads the current board directory and constructs the list of available boards
*/
public void refreshPossibleBoards() {
- final String files[] = boardDir != null ? boardDir.list() : null;
- boolean nomatch;
- // all boards are added to the list whether in local directory or not
- final List sorted = getallboards();
- final List newboards = getnewboards();
+ // Get the list of files in the board directory
+ final String[] files = boardDir != null ? boardDir.list() : null;
+ // Get the pre-defined list of all available boards
+ final List sortedBoards = getallboards(); // Pre-sorted list of boards
+ boolean noMatch;
+
+ // Add boards found in the local directory
if (files != null) {
for (String file : files) {
- // TODO - remove requirement that boards start with "bd"
- // add all boards found in local directory
- nomatch = true;
+ noMatch = true;
+ // TODO: Remove the requirement that board names start with "bd"
+ // Process files that start with "bd" and are not directories
if (file.startsWith("bd") && !(new File(boardDir, file)).isDirectory()) {
- String name = file.substring(2);
+ String name = file.substring(2); // Remove "bd" prefix
+ // Skip files with extensions (indicating they are not board files)
if (name.contains(".")) {
- name = null;
- nomatch = false;
+ noMatch = false; // Skip if it has an extension
+ continue;
}
- else {
- for (String bdname : sorted) {
- String[] split = bdname.split(" ");
- bdname = split[0];
- if (name.equals(bdname)) {
- nomatch = false;
- }
+ // Check if the board already exists in the pre-defined sorted list
+ for (String bdname : sortedBoards) {
+ String existingBoardName = bdname.split(" ")[0]; // Only compare the board name part
+ if (name.equals(existingBoardName)) {
+ noMatch = false; // Mark as already present
+ break;
}
}
- if (nomatch){sorted.add(name);}
+ // If the board is not found in the sorted list, add it
+ if (noMatch) {
+ sortedBoards.add(name);
+ }
}
}
}
- // * Strings with leading zeros sort ahead of those without.
- // * Strings with leading integer parts sort ahead of those without.
- // * Strings with lesser leading integer parts sort ahead of those with
- // greater leading integer parts.
- // * Strings which are otherwise equal are sorted lexicographically by
- // their trailing noninteger parts.
-
- final Comparator