Compare commits
No commits in common. 'master' and 'v1.6' have entirely different histories.
@ -1 +0,0 @@ |
|||||||
logging.yaml |
|
@ -0,0 +1,43 @@ |
|||||||
|
version: 1 |
||||||
|
|
||||||
|
formatters: |
||||||
|
standard: |
||||||
|
format: "%(asctime)s.%(msecs)03d | %(message)s" |
||||||
|
datefmt: "%H:%M:%S" |
||||||
|
|
||||||
|
handlers: |
||||||
|
console: |
||||||
|
class: "logging.StreamHandler" |
||||||
|
formatter: "standard" |
||||||
|
stream: "ext://sys.stdout" |
||||||
|
file: |
||||||
|
class: "logging.FileHandler" |
||||||
|
formatter: "standard" |
||||||
|
filename: "/tmp/vasl-templates.log" |
||||||
|
mode: "w" |
||||||
|
|
||||||
|
loggers: |
||||||
|
werkzeug: |
||||||
|
level: "WARNING" |
||||||
|
handlers: [ "file" ] |
||||||
|
vasl_mod: |
||||||
|
level: "WARNING" |
||||||
|
handlers: [ "file" ] |
||||||
|
update_vsav: |
||||||
|
level: "WARNING" |
||||||
|
handlers: [ "file" ] |
||||||
|
analyze_vsav: |
||||||
|
level: "WARNING" |
||||||
|
handlers: [ "file" ] |
||||||
|
analyze_vlog: |
||||||
|
level: "WARNING" |
||||||
|
handlers: [ "file" ] |
||||||
|
webdriver: |
||||||
|
level: "WARNING" |
||||||
|
handlers: [ "file" ] |
||||||
|
downloads: |
||||||
|
level: "WARNING" |
||||||
|
handlers: [ "file" ] |
||||||
|
control_tests: |
||||||
|
level: "INFO" |
||||||
|
handlers: [ "console", "file" ] |
Before Width: | Height: | Size: 3.8 MiB After Width: | Height: | Size: 1.8 MiB |
Before Width: | Height: | Size: 109 KiB After Width: | Height: | Size: 105 KiB |
Before Width: | Height: | Size: 1.8 MiB After Width: | Height: | Size: 1.6 MiB |
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 98 KiB |
Before Width: | Height: | Size: 902 KiB After Width: | Height: | Size: 1.5 MiB |
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 3.4 KiB |
@ -1,107 +0,0 @@ |
|||||||
#!/usr/bin/env python3 |
|
||||||
""" Freeze the vasl-templates loader program. |
|
||||||
|
|
||||||
This script is called by the main freeze script. |
|
||||||
""" |
|
||||||
|
|
||||||
import sys |
|
||||||
import os |
|
||||||
import shutil |
|
||||||
import tempfile |
|
||||||
import getopt |
|
||||||
|
|
||||||
from PyInstaller.__main__ import run as run_pyinstaller |
|
||||||
from PIL import Image |
|
||||||
|
|
||||||
APP_ICON = os.path.join( |
|
||||||
os.path.abspath( os.path.dirname( __file__ ) ), |
|
||||||
"../vasl_templates/webapp/static/images/app.ico" |
|
||||||
) |
|
||||||
|
|
||||||
# --------------------------------------------------------------------- |
|
||||||
|
|
||||||
def main( args ): |
|
||||||
"""Main processing.""" |
|
||||||
|
|
||||||
# parse the command-line options |
|
||||||
output_fname = "./loader" |
|
||||||
work_dir = os.path.join( tempfile.gettempdir(), "freeze-loader" ) |
|
||||||
cleanup = True |
|
||||||
opts,args = getopt.getopt( args, "o:w:", ["output=","work=","no-clean"] ) |
|
||||||
for opt, val in opts: |
|
||||||
if opt in ["-o","--output"]: |
|
||||||
output_fname = val.strip() |
|
||||||
elif opt in ["-w","--work"]: |
|
||||||
work_dir = val.strip() |
|
||||||
elif opt in ["--no-clean"]: |
|
||||||
cleanup = False |
|
||||||
else: |
|
||||||
raise RuntimeError( "Unknown argument: {}".format( opt ) ) |
|
||||||
|
|
||||||
# freeze the loader program |
|
||||||
freeze_loader( output_fname, work_dir, cleanup ) |
|
||||||
|
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|
||||||
|
|
||||||
def freeze_loader( output_fname, work_dir, cleanup ): |
|
||||||
"""Freeze the loader program.""" |
|
||||||
|
|
||||||
with tempfile.TemporaryDirectory() as dist_dir: |
|
||||||
|
|
||||||
# initialize |
|
||||||
base_dir = os.path.abspath( os.path.dirname( __file__ ) ) |
|
||||||
assets_dir = os.path.join( base_dir, "assets" ) |
|
||||||
|
|
||||||
# convert the app icon to an image |
|
||||||
if not os.path.isdir( work_dir ): |
|
||||||
os.makedirs( work_dir ) |
|
||||||
app_icon_fname = os.path.join( work_dir, "app-icon.png" ) |
|
||||||
_convert_app_icon( app_icon_fname ) |
|
||||||
|
|
||||||
# initialize |
|
||||||
app_name = "loader" |
|
||||||
args = [ |
|
||||||
"--distpath", dist_dir, |
|
||||||
"--workpath", work_dir, |
|
||||||
"--specpath", work_dir, |
|
||||||
"--onefile", |
|
||||||
"--name", app_name, |
|
||||||
] |
|
||||||
args.extend( [ |
|
||||||
"--add-data", app_icon_fname + os.pathsep + "assets/", |
|
||||||
"--add-data", os.path.join(assets_dir,"loading.gif") + os.pathsep + "assets/" |
|
||||||
] ) |
|
||||||
if sys.platform == "win32": |
|
||||||
args.append( "--noconsole" ) |
|
||||||
args.extend( [ "--icon", APP_ICON ] ) |
|
||||||
args.append( os.path.join( base_dir, "main.py" ) ) |
|
||||||
|
|
||||||
# freeze the program |
|
||||||
run_pyinstaller( args ) |
|
||||||
|
|
||||||
# save the generated artifact |
|
||||||
fname = app_name+".exe" if sys.platform == "win32" else app_name |
|
||||||
shutil.move( |
|
||||||
os.path.join( dist_dir, fname ), |
|
||||||
output_fname |
|
||||||
) |
|
||||||
|
|
||||||
# clean up |
|
||||||
if cleanup: |
|
||||||
shutil.rmtree( work_dir ) |
|
||||||
|
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|
||||||
|
|
||||||
def _convert_app_icon( save_fname ): |
|
||||||
"""Convert the app icon to an image.""" |
|
||||||
# NOTE: Tkinter's PhotoImage doesn't handle .ico files, so we convert the app icon |
|
||||||
# to an image, then insert it into the PyInstaller-generated executable (so that |
|
||||||
# we don't have to bundle Pillow into the release). |
|
||||||
img = Image.open( APP_ICON ) |
|
||||||
img = img.convert( "RGBA" ).resize( (48, 48) ) |
|
||||||
img.save( save_fname, "png" ) |
|
||||||
|
|
||||||
# --------------------------------------------------------------------- |
|
||||||
|
|
||||||
if __name__ == "__main__": |
|
||||||
main( sys.argv[1:] ) |
|
@ -1,207 +0,0 @@ |
|||||||
""" Load the main vasl-templates program. |
|
||||||
|
|
||||||
vasl-templates can be slow to start (especially on Windows), since it has to unpack the PyInstaller-generated EXE, |
|
||||||
then startup Qt. We want to show a splash screen while all this happening, but we can't just put it in vasl-templates, |
|
||||||
since it would only happen *after* all the slow stuff has finished :-/ So, we have this stub program that shows |
|
||||||
a splash screen, launches the main vasl-templates program, and waits for it to finish starting up. |
|
||||||
""" |
|
||||||
|
|
||||||
import sys |
|
||||||
import os |
|
||||||
import subprocess |
|
||||||
import threading |
|
||||||
import itertools |
|
||||||
import urllib.request |
|
||||||
from urllib.error import URLError |
|
||||||
import time |
|
||||||
import configparser |
|
||||||
|
|
||||||
# NOTE: It's important that this program start up quickly (otherwise it becomes pointless), |
|
||||||
# so we use tkinter, instead of PyQt (and also avoid bundling a 2nd copy of PyQt :-/). |
|
||||||
import tkinter |
|
||||||
import tkinter.messagebox |
|
||||||
|
|
||||||
if getattr( sys, "frozen", False ): |
|
||||||
BASE_DIR = sys._MEIPASS #pylint: disable=no-member,protected-access |
|
||||||
else: |
|
||||||
BASE_DIR = os.path.abspath( os.path.dirname( __file__ ) ) |
|
||||||
|
|
||||||
STARTUP_TIMEOUT = 60 # how to long to wait for vasl-templates to start (seconds) |
|
||||||
|
|
||||||
main_window = None |
|
||||||
|
|
||||||
# --------------------------------------------------------------------- |
|
||||||
|
|
||||||
def main( args ): |
|
||||||
"""Load the main vasl-templates program.""" |
|
||||||
|
|
||||||
# initialize Tkinter |
|
||||||
global main_window |
|
||||||
main_window = tkinter.Tk() |
|
||||||
main_window.option_add( "*Dialog.msg.font", "Helvetica 12" ) |
|
||||||
|
|
||||||
# load the app icon |
|
||||||
# NOTE: This image file doesn't exist in source control, but is created dynamically from |
|
||||||
# the main app icon by the freeze script, and inserted into the PyInstaller-generated executable. |
|
||||||
# We do things this way so that we don't have to bundle Pillow into the release. |
|
||||||
app_icon = tkinter.PhotoImage( |
|
||||||
file = make_asset_path( "app-icon.png" ) |
|
||||||
) |
|
||||||
|
|
||||||
# locate the main vasl-templates executable |
|
||||||
fname = os.path.join( os.path.dirname( sys.executable ), "vasl-templates-main" ) |
|
||||||
if sys.platform == "win32": |
|
||||||
fname += ".exe" |
|
||||||
if not os.path.isfile( fname ): |
|
||||||
show_error_msg( "Can't find the main vasl-templates program.", withdraw=True ) |
|
||||||
return -1 |
|
||||||
|
|
||||||
# launch the main vasl-templates program |
|
||||||
try: |
|
||||||
proc = subprocess.Popen( itertools.chain( [fname], args ) ) #pylint: disable=consider-using-with |
|
||||||
except Exception as ex: #pylint: disable=broad-except |
|
||||||
show_error_msg( "Can't start vasl-templates:\n\n{}".format( ex ), withdraw=True ) |
|
||||||
return -2 |
|
||||||
|
|
||||||
# get the webapp port number |
|
||||||
port = 5010 |
|
||||||
fname = os.path.join( os.path.dirname( fname ), "config/app.cfg" ) |
|
||||||
if os.path.isfile( fname ): |
|
||||||
config_parser = configparser.ConfigParser() |
|
||||||
config_parser.optionxform = str # preserve case for the keys :-/ |
|
||||||
config_parser.read( fname ) |
|
||||||
args = dict( config_parser.items( "System" ) ) |
|
||||||
port = args.get( "FLASK_PORT_NO", port ) |
|
||||||
|
|
||||||
# create the splash window |
|
||||||
create_window( app_icon ) |
|
||||||
|
|
||||||
# start a background thread to check on the main vasl-templates process |
|
||||||
threading.Thread( |
|
||||||
target = check_startup, |
|
||||||
args = ( proc, port ) |
|
||||||
).start() |
|
||||||
|
|
||||||
# run the main loop |
|
||||||
main_window.mainloop() |
|
||||||
|
|
||||||
return 0 |
|
||||||
|
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|
||||||
|
|
||||||
def create_window( app_icon ): |
|
||||||
"""Create the splash window.""" |
|
||||||
|
|
||||||
# create the splash window |
|
||||||
main_window.geometry( "275x64" ) |
|
||||||
main_window.title( "vasl-templates loader" ) |
|
||||||
main_window.overrideredirect( 1 ) # nb: "-type splash" doesn't work on Windows :-/ |
|
||||||
main_window.eval( "tk::PlaceWindow . center" ) |
|
||||||
main_window.wm_attributes( "-topmost", 1 ) |
|
||||||
main_window.tk.call( "wm", "iconphoto", main_window._w, app_icon ) #pylint: disable=protected-access |
|
||||||
main_window.protocol( "WM_DELETE_WINDOW", lambda: None ) |
|
||||||
|
|
||||||
# add the app icon |
|
||||||
label = tkinter.Label( main_window, image=app_icon ) |
|
||||||
label.grid( row=0, column=0, rowspan=2, padx=8, pady=8 ) |
|
||||||
|
|
||||||
# add the caption |
|
||||||
label = tkinter.Label( main_window, text="Loading vasl-templates...", font=("Helvetica",12) ) |
|
||||||
label.grid( row=0, column=1, padx=5, pady=(8,0) ) |
|
||||||
|
|
||||||
# add the "loading" image (we have to animate it ourself :-/) |
|
||||||
anim_label = tkinter.Label( main_window ) |
|
||||||
anim_label.grid( row=1, column=1, sticky=tkinter.N, padx=0, pady=0 ) |
|
||||||
fname = make_asset_path( "loading.gif" ) |
|
||||||
nframes = 13 |
|
||||||
frames = [ |
|
||||||
tkinter.PhotoImage( file=fname, format="gif -index {}".format( i ) ) |
|
||||||
for i in range(nframes) |
|
||||||
] |
|
||||||
frame_index = 0 |
|
||||||
def next_frame(): |
|
||||||
nonlocal frame_index |
|
||||||
frame = frames[ frame_index ] |
|
||||||
frame_index = ( frame_index + 1 ) % nframes |
|
||||||
anim_label.configure( image=frame ) |
|
||||||
main_window.after( 75, next_frame ) |
|
||||||
main_window.after( 0, next_frame ) |
|
||||||
|
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|
||||||
|
|
||||||
def check_startup( proc, port ): |
|
||||||
"""Check the startup of the main vasl-templates process.""" |
|
||||||
|
|
||||||
def do_check(): |
|
||||||
|
|
||||||
# check if we've waited for too long |
|
||||||
if time.time() - start_time > STARTUP_TIMEOUT: |
|
||||||
# yup - give up |
|
||||||
raise RuntimeError( "Couldn't start vasl-templates." ) |
|
||||||
|
|
||||||
# check if the main vasl-templates process has gone away |
|
||||||
if proc.poll() is not None: |
|
||||||
raise RuntimeError( "The vasl-templates program ended unexpectedly." ) |
|
||||||
|
|
||||||
# check if the webapp is responding |
|
||||||
url = "http://localhost:{}/ping".format( port ) |
|
||||||
try: |
|
||||||
with urllib.request.urlopen( url ) as resp: |
|
||||||
_ = resp.read() |
|
||||||
except URLError: |
|
||||||
# no response - the webapp is probably still starting up |
|
||||||
return False |
|
||||||
except Exception as ex: #pylint: disable=broad-except |
|
||||||
raise RuntimeError( "Couldn't communicate with vasl-templates:\n\n{}".format( ex ) ) from ex |
|
||||||
|
|
||||||
# the main vasl-templates program has started up and is responsive - our job is done! |
|
||||||
if sys.platform == "win32": |
|
||||||
# FUDGE! There is a short amount of time between the webapp server starting and |
|
||||||
# the main window appearing. We delay here for a bit, to try to synchronize |
|
||||||
# our window fading out with the main vasl-templates window appearing. |
|
||||||
time.sleep( 1 ) |
|
||||||
return True |
|
||||||
|
|
||||||
def on_done( msg ): |
|
||||||
if msg: |
|
||||||
show_error_msg( msg, withdraw=True ) |
|
||||||
fade_out( main_window, main_window.quit ) |
|
||||||
|
|
||||||
# run the main loop |
|
||||||
start_time = time.time() |
|
||||||
while True: |
|
||||||
try: |
|
||||||
if do_check(): |
|
||||||
on_done( None ) |
|
||||||
break |
|
||||||
except Exception as ex: #pylint: disable=broad-except |
|
||||||
on_done( str(ex) ) |
|
||||||
return |
|
||||||
time.sleep( 0.25 ) |
|
||||||
|
|
||||||
# --------------------------------------------------------------------- |
|
||||||
|
|
||||||
def fade_out( target, on_done ): |
|
||||||
"""Fade out the target window.""" |
|
||||||
alpha = target.attributes( "-alpha" ) |
|
||||||
if alpha > 0: |
|
||||||
alpha -= 0.1 |
|
||||||
target.attributes( "-alpha", alpha ) |
|
||||||
target.after( 50, lambda: fade_out( target, on_done ) ) |
|
||||||
else: |
|
||||||
on_done() |
|
||||||
|
|
||||||
def make_asset_path( fname ): |
|
||||||
"""Generate the path to an asset file.""" |
|
||||||
return os.path.join( BASE_DIR, "assets", fname ) |
|
||||||
|
|
||||||
def show_error_msg( error_msg, withdraw=False ): |
|
||||||
"""Show an error dialog.""" |
|
||||||
if withdraw: |
|
||||||
main_window.withdraw() |
|
||||||
tkinter.messagebox.showinfo( "vasl-templates loader error", error_msg ) |
|
||||||
|
|
||||||
# --------------------------------------------------------------------- |
|
||||||
|
|
||||||
if __name__ == "__main__": |
|
||||||
sys.exit( main( sys.argv[1:] ) ) |
|
@ -1,7 +1,7 @@ |
|||||||
pytest==7.4.2 |
pytest==6.2.1 |
||||||
grpcio-tools==1.58.0 |
grpcio-tools==1.34.1 |
||||||
tabulate==0.9.0 |
tabulate==0.8.7 |
||||||
lxml==4.9.3 |
lxml==4.6.2 |
||||||
pylint==2.17.5 |
pylint==2.6.0 |
||||||
pytest-pylint==0.19.0 |
pytest-pylint==0.18.0 |
||||||
pyinstaller==5.13.2 |
pyinstaller==4.2 |
||||||
|
@ -1,10 +1,7 @@ |
|||||||
# python 3.11.4 |
# python 3.8.7 |
||||||
|
|
||||||
flask==2.3.3 |
flask==1.1.2 |
||||||
pyyaml==6.0.1 |
pyyaml==5.3.1 |
||||||
# NOTE: Pillow 9.5.0 is the last version that provides 32-bit wheels. |
pillow==8.1.0 |
||||||
pillow==9.5.0 |
selenium==3.141.0 |
||||||
selenium==4.12.0 |
click==7.1.2 |
||||||
waitress==2.1.2 |
|
||||||
appdirs==1.4.4 |
|
||||||
click==8.1.7 |
|
||||||
|
@ -1,83 +0,0 @@ |
|||||||
#!/usr/bin/env python3 |
|
||||||
""" Prepare the piece info for a VASL module. |
|
||||||
|
|
||||||
The main program used to identify 5/8" counters by reading a module's buildFile and checking the height |
|
||||||
attribute of the PieceSlot nodes, but it turns out this is the wrong thing to do (this field actually |
|
||||||
controls the size of the piece's entry in the counter palette): |
|
||||||
https://github.com/vasl-developers/vasl/issues/1195 |
|
||||||
|
|
||||||
For each version of VASL supported, run vassal-shim (getPieceInfo command) to analyze the module's |
|
||||||
buildFile and get the correct counter sizes. Then pass the output into this script, to generate |
|
||||||
the final data file that should be saved in the $/data/vasl-$VERSION/ directory, where it will |
|
||||||
be read by the main program. |
|
||||||
|
|
||||||
NOTE: Introducing this process opens the possibility of also extracting the image file paths |
|
||||||
within the .vmod file, instead of the current messy parsing of the PieceSlot CDATA... :-/ |
|
||||||
""" |
|
||||||
|
|
||||||
import sys |
|
||||||
import os |
|
||||||
import json |
|
||||||
|
|
||||||
import xml.etree.ElementTree as ET |
|
||||||
|
|
||||||
# --------------------------------------------------------------------- |
|
||||||
|
|
||||||
# initialize |
|
||||||
report = {} |
|
||||||
|
|
||||||
# figure out which GPID's we're interested in |
|
||||||
gpids = set() |
|
||||||
def get_gpids( vo_type ): |
|
||||||
"""Get the GPID's from our data files.""" |
|
||||||
dname = os.path.join( os.path.dirname(__file__), "../webapp/data", vo_type ) |
|
||||||
for root,_,fnames in os.walk( dname ): |
|
||||||
for fname in fnames: |
|
||||||
if os.path.splitext( fname )[1] != ".json": |
|
||||||
continue |
|
||||||
fname = os.path.join( root, fname ) |
|
||||||
with open( fname, "r", encoding="utf-8" ) as fp: |
|
||||||
entries = json.load( fp ) |
|
||||||
for entry in entries: |
|
||||||
entry_gpid = entry.get( "gpid" ) |
|
||||||
if not entry_gpid: |
|
||||||
continue |
|
||||||
if isinstance( entry_gpid, list ): |
|
||||||
gpids.update( str(g) for g in entry_gpid ) |
|
||||||
else: |
|
||||||
gpids.add( str( entry_gpid ) ) |
|
||||||
get_gpids( "vehicles" ) |
|
||||||
get_gpids( "ordnance" ) |
|
||||||
|
|
||||||
# parse the piece info generated by vassal-shim |
|
||||||
doc = ET.parse( sys.stdin ) |
|
||||||
for piece_info in doc.getroot(): |
|
||||||
gpid = piece_info.attrib["gpid"] |
|
||||||
if gpid not in gpids: |
|
||||||
continue |
|
||||||
info = {} |
|
||||||
# check if the next piece is small |
|
||||||
# FUDGE! We used to check for <= 48, but what we get is GamePiece.boundingBox(), which is |
|
||||||
# the click zone for the counter, not the actual size of the counter's image :-/ |
|
||||||
if int( piece_info.attrib["height"] ) <= 55: |
|
||||||
info["is_small"] = True |
|
||||||
if info: |
|
||||||
report[ gpid ] = info |
|
||||||
|
|
||||||
# FUDGE! These are from extensions - it's not worth trying to figure these out programtically. |
|
||||||
report[ "adf:1948" ] = { "is_small": True } # BFP Blood & Jungle: Dutch Brandt 47mm Mortar |
|
||||||
report[ "adf:75" ] = { "is_small": True } # BFP Blood & Jungle: Indonesian Type 89 Heavy Grenade Launcher |
|
||||||
report[ "adf:77" ] = { "is_small": True } # BFP Blood & Jungle: Indonesian Type 97 Automatic Gun |
|
||||||
report[ "adf:76" ] = { "is_small": True } # BFP Blood & Jungle: Indonesian Year-11 Flat-Trajectory INF Gun |
|
||||||
report[ "adf:1407" ] = { "is_small": True } # BFP Poland In Flames: German 2cm Tankbusche S-18 |
|
||||||
report[ "08d:75" ] = { "is_small": True } # Fight For Seoul: American M20(L) 75mm Recoilless Rifle |
|
||||||
|
|
||||||
# output the final report |
|
||||||
print( "{" ) |
|
||||||
lines = [] |
|
||||||
for gpid, piece_info in report.items(): |
|
||||||
lines.append( "\"{}\": {}".format( |
|
||||||
gpid, json.dumps( piece_info ) |
|
||||||
) ) |
|
||||||
print( ",\n".join( lines ) ) |
|
||||||
print( "}" ) |
|
@ -1,5 +0,0 @@ |
|||||||
<html> <!-- vasl-templates:id {{SNIPPET_ID}} --> |
|
||||||
|
|
||||||
<img src="{{IMAGES_BASE_URL}}/compass/{{COMPASS}}.png"> |
|
||||||
|
|
||||||
</html> |
|
@ -1,41 +0,0 @@ |
|||||||
<html> <!-- vasl-templates:id {{SNIPPET_ID}} --> |
|
||||||
|
|
||||||
<!-- vasl-templates:name Booby Traps --> |
|
||||||
<!-- vasl-templates:description Data chart for Booby Traps. --> |
|
||||||
|
|
||||||
<!-- player = {{PLAYER_DROPLIST:|Player}} |
|
||||||
<!-- boards = {{BOARDS*:/8|Board(s)}} --> |
|
||||||
|
|
||||||
<head> |
|
||||||
<meta charset="utf-8"> |
|
||||||
<style> |
|
||||||
.header { |
|
||||||
background: {{PLAYER_COLORS[PLAYER_DROPLIST][0]}} ; |
|
||||||
border-bottom: 1px solid {{PLAYER_COLORS[PLAYER_DROPLIST][2]}} ; |
|
||||||
padding: 2px 5px ; |
|
||||||
font-size: 105% ; font-weight: bold ; |
|
||||||
} |
|
||||||
.header .level { font-size: 90% ; font-style: italic ; } |
|
||||||
{{CSS:common}} |
|
||||||
</style> |
|
||||||
</head> |
|
||||||
|
|
||||||
<table> |
|
||||||
|
|
||||||
<tr> |
|
||||||
<td class="header"> |
|
||||||
<img src="{{PLAYER_FLAGS[PLAYER_DROPLIST]}}?prefh={{PLAYER_FLAG_SIZE_LARGE}}" width="{{PLAYER_FLAG_SIZE_LARGE}}" height="{{PLAYER_FLAG_SIZE_LARGE}}"> Booby Traps <span class="level">(Level {{LEVEL:A::B::C/3|Level}})</span> |
|
||||||
|
|
||||||
<tr> |
|
||||||
<td style="padding:2px 5px;"> |
|
||||||
<b> {%if BOARDS%} Boards: {{BOARDS}} {%else%} Entire map {%endif%} </b> |
|
||||||
<ul> |
|
||||||
<li> Original TC |
|
||||||
{% if LEVEL == "A" %} ≥ 11 |
|
||||||
{% elif LEVEL == "B" %} 11 |
|
||||||
{% elif LEVEL == "C" %} 12 |
|
||||||
{%else%} ??? {%endif%} |
|
||||||
<li> Search Casualties |
|
||||||
</ul> |
|
||||||
|
|
||||||
</table> |
|
@ -1,87 +0,0 @@ |
|||||||
<html> <!-- vasl-templates:id {{SNIPPET_ID}} --> |
|
||||||
|
|
||||||
<!-- vasl-templates:name Kampfgruppe Scherer --> |
|
||||||
<!-- vasl-templates:description Data charts for Grenade Bundles and Molotov Cocktails. --> |
|
||||||
<!-- {{TYPE:Grenade Bundles::Molotov Cocktails/10|Data chart}} --> |
|
||||||
|
|
||||||
<head> |
|
||||||
<meta charset="utf-8"> |
|
||||||
<style> {{CSS:common}} </style> |
|
||||||
</head> |
|
||||||
|
|
||||||
<table> |
|
||||||
|
|
||||||
<tr> |
|
||||||
<td colspan="2" style=" |
|
||||||
background: {{PLAYER_COLORS["german"][0]}} ; |
|
||||||
border-bottom: 1px solid {{PLAYER_COLORS["german"][2]}} ; |
|
||||||
padding: 2px 5px ; |
|
||||||
font-size: 105% ; font-weight: bold ; |
|
||||||
"> |
|
||||||
{# Some versions of Java require <img> tags to have the width and height specified!?! #} |
|
||||||
{%if PLAYER_FLAGS["german"]%}<img src="{{PLAYER_FLAGS["german"]}}?prefh={{PLAYER_FLAG_SIZE_LARGE}}" width="{{PLAYER_FLAG_SIZE_LARGE}}" height="{{PLAYER_FLAG_SIZE_LARGE}}"> {%endif%}{{TYPE}} |
|
||||||
|
|
||||||
{% if TYPE == "Grenade Bundles" %} |
|
||||||
|
|
||||||
<tr> |
|
||||||
<td style="padding:3px 5px 0 5px;"> |
|
||||||
CC Attack -2 DRM |
|
||||||
|
|
||||||
<tr> |
|
||||||
<td style="padding:3px 5px 0 5px;"> |
|
||||||
<b>ATMM check</b>: dr ≤ 3 (△) |
|
||||||
<table style="margin-left:10px;"> |
|
||||||
<tr> |
|
||||||
<td style="width:20px;"> +1 |
|
||||||
<td> HS/crew |
|
||||||
<tr> |
|
||||||
<td> +2 |
|
||||||
<td> SMC |
|
||||||
<tr> |
|
||||||
<td> +1 |
|
||||||
<td> CX |
|
||||||
<tr> |
|
||||||
<td> +1 |
|
||||||
<td> vs. non-armored vehicle |
|
||||||
</table> |
|
||||||
original 6 = pinned (CCV reduced by 1) |
|
||||||
|
|
||||||
{% elif TYPE == "Molotov Cocktails" %} |
|
||||||
|
|
||||||
<tr> |
|
||||||
<td style="padding:3px 5px 0 5px;"> |
|
||||||
Against AFV only. |
|
||||||
|
|
||||||
<tr> |
|
||||||
<td style="padding:3px 5px 0 5px;"> |
|
||||||
<b>MOL check</b>: dr ≤ 3 (△) |
|
||||||
<table style="margin-left:10px;"> |
|
||||||
<tr> |
|
||||||
<td style="width:20px;"> +1 |
|
||||||
<td> HS/crew |
|
||||||
<tr> |
|
||||||
<td> +2 |
|
||||||
<td> SMC |
|
||||||
<tr> |
|
||||||
<td> +1 |
|
||||||
<td> CX |
|
||||||
</table> |
|
||||||
|
|
||||||
<tr> |
|
||||||
<td style="padding:3px 5px 0 5px;"> |
|
||||||
<b>IFT DR original colored dr</b>: |
|
||||||
<ul> |
|
||||||
<li> 1 = Flame in target Location |
|
||||||
<li> 6 = thrower breaks, Flame in their Location |
|
||||||
</ul> |
|
||||||
|
|
||||||
<tr> |
|
||||||
<td style="padding:3px 5px 0 5px;"> |
|
||||||
<b>Kindling Attempt</b>: +2 DRM |
|
||||||
|
|
||||||
{%endif%} |
|
||||||
|
|
||||||
</table> |
|
||||||
|
|
||||||
</html> |
|
||||||
|
|
@ -0,0 +1,49 @@ |
|||||||
|
<html> <!-- vasl-templates:id {{SNIPPET_ID}} --> |
||||||
|
|
||||||
|
<!-- vasl-templates:name KGS Grenade Bundles --> |
||||||
|
<!-- vasl-templates:description Data chart for Grenade Bundles in <i>Kampfgruppe Scherer</i>. --> |
||||||
|
|
||||||
|
<head> |
||||||
|
<meta charset="utf-8"> |
||||||
|
<style> {{CSS:common}} </style> |
||||||
|
</head> |
||||||
|
|
||||||
|
<table> |
||||||
|
|
||||||
|
<tr> |
||||||
|
<td colspan="2" style=" |
||||||
|
background: {{PLAYER_COLORS["german"][0]}} ; |
||||||
|
border-bottom: 1px solid {{PLAYER_COLORS["german"][2]}} ; |
||||||
|
padding: 2px 5px ; |
||||||
|
font-size: 105% ; font-weight: bold ; |
||||||
|
"> |
||||||
|
{# Some versions of Java require <img> tags to have the width and height specified!?! #} |
||||||
|
{%if PLAYER_FLAGS["german"]%}<img src="{{PLAYER_FLAGS["german"]}}" {{PLAYER_FLAG_SIZE_LARGE}}> {%endif%}Grenade Bundles |
||||||
|
|
||||||
|
<tr> |
||||||
|
<td style="padding:3px 5px 0 5px;"> |
||||||
|
-2 CC Attack DRM |
||||||
|
|
||||||
|
<tr> |
||||||
|
<td style="padding:3px 5px 0 5px;"> |
||||||
|
ATMM check: dr ≤ 3 (△) |
||||||
|
<table style="margin-left:10px;"> |
||||||
|
<tr> |
||||||
|
<td style="width:20px;"> +1 |
||||||
|
<td> HS/crew |
||||||
|
<tr> |
||||||
|
<td> +2 |
||||||
|
<td> SMC |
||||||
|
<tr> |
||||||
|
<td> +1 |
||||||
|
<td> CX |
||||||
|
<tr> |
||||||
|
<td> +1 |
||||||
|
<td> vs. non-armored vehicle |
||||||
|
</table> |
||||||
|
original 6 = pinned (CCV reduced by 1) |
||||||
|
|
||||||
|
</table> |
||||||
|
|
||||||
|
</html> |
||||||
|
|
@ -0,0 +1,57 @@ |
|||||||
|
<html> <!-- vasl-templates:id {{SNIPPET_ID}} --> |
||||||
|
|
||||||
|
<!-- vasl-templates:name KGS Molotov Cocktails --> |
||||||
|
<!-- vasl-templates:description Data chart for Molotov Cocktails in <i>Kampfgruppe Scherer</i>. --> |
||||||
|
|
||||||
|
<head> |
||||||
|
<meta charset="utf-8"> |
||||||
|
<style> {{CSS:common}} </style> |
||||||
|
</head> |
||||||
|
|
||||||
|
<table> |
||||||
|
|
||||||
|
<tr> |
||||||
|
<td colspan="2" style=" |
||||||
|
background: {{PLAYER_COLORS["german"][0]}} ; |
||||||
|
border-bottom: 1px solid {{PLAYER_COLORS["german"][2]}} ; |
||||||
|
padding: 2px 5px ; |
||||||
|
font-size: 105% ; font-weight: bold ; |
||||||
|
"> |
||||||
|
{# Some versions of Java require <img> tags to have the width and height specified!?! #} |
||||||
|
{%if PLAYER_FLAGS["german"]%}<img src="{{PLAYER_FLAGS["german"]}}" {{PLAYER_FLAG_SIZE_LARGE}}> {%endif%}Molotov Cocktails |
||||||
|
|
||||||
|
<tr> |
||||||
|
<td style="padding:3px 5px 0 5px;"> |
||||||
|
vs. AFV only |
||||||
|
|
||||||
|
<tr> |
||||||
|
<td style="padding:3px 5px 0 5px;"> |
||||||
|
MOL check: dr ≤ 3 (△) |
||||||
|
<table style="margin-left:10px;"> |
||||||
|
<tr> |
||||||
|
<td style="width:20px;"> +1 |
||||||
|
<td> HS/crew |
||||||
|
<tr> |
||||||
|
<td> +2 |
||||||
|
<td> SMC |
||||||
|
<tr> |
||||||
|
<td> +1 |
||||||
|
<td> CX |
||||||
|
</table> |
||||||
|
|
||||||
|
<tr> |
||||||
|
<td style="padding:3px 5px 0 5px;"> |
||||||
|
IFT DR original colored dr: |
||||||
|
<ul> |
||||||
|
<li> 1 = Flame in target Location |
||||||
|
<li> 6 = thrower breaks, Flame in their Location |
||||||
|
</ul> |
||||||
|
|
||||||
|
<tr> |
||||||
|
<td style="padding:3px 5px 0 5px;"> |
||||||
|
Kindling Attempt: +2 DRM |
||||||
|
|
||||||
|
</table> |
||||||
|
|
||||||
|
</html> |
||||||
|
|
@ -1,2 +1,2 @@ |
|||||||
{# Some versions of Java require <img> tags to have the width and height specified!?! #} |
{# Some versions of Java require <img> tags to have the width and height specified!?! #} |
||||||
{%if PLAYER_FLAG%}<img src="{{PLAYER_FLAG}}?prefh={{PLAYER_FLAG_SIZE}}" width="{{PLAYER_FLAG_SIZE}}" height="{{PLAYER_FLAG_SIZE}}"> {%endif%} |
{%if PLAYER_FLAG%}<img src="{{PLAYER_FLAG}}" {{PLAYER_FLAG_SIZE}}> {%endif%} |
||||||
|
@ -1,2 +1,2 @@ |
|||||||
{# Some versions of Java require <img> tags to have the width and height specified!?! #} |
{# Some versions of Java require <img> tags to have the width and height specified!?! #} |
||||||
{%if PLAYER_FLAG%}<img src="{{PLAYER_FLAG}}?prefh={{PLAYER_FLAG_SIZE_LARGE}}" width="{{PLAYER_FLAG_SIZE_LARGE}}" height="{{PLAYER_FLAG_SIZE_LARGE}}"> {%endif%} |
{%if PLAYER_FLAG%}<img src="{{PLAYER_FLAG}}" {{PLAYER_FLAG_SIZE_LARGE}}> {%endif%} |
||||||
|
@ -1,116 +0,0 @@ |
|||||||
<html> <!-- vasl-templates:id {{SNIPPET_ID}} --> |
|
||||||
|
|
||||||
<head> |
|
||||||
<meta charset="utf-8"> |
|
||||||
<style> {{CSS:common}} </style> |
|
||||||
|
|
||||||
<style> |
|
||||||
|
|
||||||
td { |
|
||||||
width: 50px ; min-width: 50px ; |
|
||||||
height: {%if TURN_TRACK_PREVIEW_MODE%} 50px {%else%} 43px {%endif%} ; |
|
||||||
padding: 2px ; |
|
||||||
border: 1px solid black ; |
|
||||||
} |
|
||||||
{% set RESET_TD = "min-width: unset ; height: unset ; padding: 0 ; border: none" %} |
|
||||||
td.turn-no { |
|
||||||
{{RESET_TD}} ; width: unset ; |
|
||||||
text-align: center ; vertical-align: center ; font-size: 18px ; font-weight: bold ; |
|
||||||
} |
|
||||||
td.no-reinforce { {{RESET_TD}} ; width: 13px ; } |
|
||||||
{# NOTE: We do the reinforcement flags as CSS backgrounds, since VASSAL is incredibly slow downloading normal images. #} |
|
||||||
td.reinforce1 { {{RESET_TD}} ; width: 13px ; background: url("{{TURN_TRACK_FLAG_1}}") top left no-repeat ; vertical-align: top ; } |
|
||||||
td.reinforce2 { {{RESET_TD}} ; width: 13px ; background: url("{{TURN_TRACK_FLAG_2}}") bottom right no-repeat ; vertical-align: bottom ; } |
|
||||||
td.half-turn { |
|
||||||
background: url("{{TURN_TRACK_HALF_TURN_IMAGE_URL}}") bottom right no-repeat ; |
|
||||||
background-size: contain ; {# nb: doesn't work in VASSAL, the image file needs to be the correct size :-/ #} |
|
||||||
} |
|
||||||
|
|
||||||
{% if TURN_TRACK_PREVIEW_MODE %} |
|
||||||
body { margin: 0 ; } |
|
||||||
body ::selection {} |
|
||||||
body ::moz-selection {} |
|
||||||
body { user-select: none ; } |
|
||||||
.reinforce1, .reinforce2 { opacity: 0 ; } |
|
||||||
.flag-click { width: 13px ; height: 13px ; cursor: pointer ; } |
|
||||||
.shading-click { cursor: pointer ; } |
|
||||||
{%endif%} |
|
||||||
|
|
||||||
</style> |
|
||||||
|
|
||||||
</head> |
|
||||||
|
|
||||||
{% if TURN_TRACK_PREVIEW_MODE %} |
|
||||||
<script> |
|
||||||
// notify the parent window of clicks |
|
||||||
function onFlagClick( turnNo, playerNo ) { |
|
||||||
window.parent.postMessage( { |
|
||||||
type: "FlagClick", |
|
||||||
turnNo: turnNo, uiPlayerNo: playerNo |
|
||||||
}, "*" ) ; |
|
||||||
} |
|
||||||
function onShadingClick( turnNo ) { |
|
||||||
window.parent.postMessage( { |
|
||||||
type: "ShadingClick", |
|
||||||
turnNo: turnNo |
|
||||||
}, "*" ) ; |
|
||||||
} |
|
||||||
</script> |
|
||||||
{%endif%} |
|
||||||
|
|
||||||
<table class="turn-track"> |
|
||||||
|
|
||||||
{% for row in TURN_TRACK_SQUARES %} |
|
||||||
<tr> |
|
||||||
|
|
||||||
{% for turnSquare in row %} |
|
||||||
<td id="turn-square-{{turnSquare[0]}}" |
|
||||||
{%if turnSquare[0] == TURN_TRACK_HALF_TURN%} class="half-turn" {%endif%} |
|
||||||
{% if turnSquare[3] %} style="background-color:{{turnSquare[3]}};" {%endif%} |
|
||||||
> |
|
||||||
|
|
||||||
<table style="width:100%;height:100%;"> <tr> |
|
||||||
|
|
||||||
<td id="flag-{{turnSquare[0]}}_1" width="100%" |
|
||||||
class = {% if turnSquare[1] %} "reinforce1" {%else%} "no-reinforce" {%endif%} |
|
||||||
> |
|
||||||
{% if TURN_TRACK_PREVIEW_MODE %} |
|
||||||
<div class="flag-click" |
|
||||||
onclick = "onFlagClick( {{turnSquare[0]}}, 1 )" |
|
||||||
> </div> |
|
||||||
{%endif%} |
|
||||||
</td> |
|
||||||
|
|
||||||
<td class="turn-no"> |
|
||||||
{% if TURN_TRACK_PREVIEW_MODE %} |
|
||||||
<div class="shading-click" |
|
||||||
onclick = "onShadingClick( {{turnSquare[0]}} )" |
|
||||||
> |
|
||||||
{{turnSquare[0]}} |
|
||||||
</div> |
|
||||||
{%else%} |
|
||||||
{{turnSquare[0]}} |
|
||||||
{%endif%} |
|
||||||
</td> |
|
||||||
|
|
||||||
<td id="flag-{{turnSquare[0]}}_2" width="100%" |
|
||||||
class = {% if turnSquare[2] and turnSquare[0] != TURN_TRACK_HALF_TURN %} "reinforce2" {%else%} "no-reinforce" {%endif%} |
|
||||||
> |
|
||||||
{% if TURN_TRACK_PREVIEW_MODE and turnSquare[0] != TURN_TRACK_HALF_TURN %} |
|
||||||
<div class="flag-click" |
|
||||||
onclick = "onFlagClick( {{turnSquare[0]}}, 2 )" |
|
||||||
> </div> |
|
||||||
{%endif%} |
|
||||||
</td> |
|
||||||
|
|
||||||
</tr> </table> |
|
||||||
|
|
||||||
</td> |
|
||||||
{%endfor%} |
|
||||||
|
|
||||||
</tr> |
|
||||||
{%endfor%} |
|
||||||
|
|
||||||
</table> |
|
||||||
|
|
||||||
</html> |
|
@ -1,26 +0,0 @@ |
|||||||
[ |
|
||||||
|
|
||||||
{ "name": "81mm Granatkastare m/29", |
|
||||||
"type": "MTR", |
|
||||||
"capabilities2": { "s": 8 }, |
|
||||||
"comments": [ "QSU" ], |
|
||||||
"note_number": "1", |
|
||||||
"id": "swe/o:000", |
|
||||||
"gpid": 13832 |
|
||||||
}, |
|
||||||
{ "name": "37mm Pansarvärnskanon m/38", |
|
||||||
"type": "AT", |
|
||||||
"comments": [ "QSU" ], |
|
||||||
"note_number": "2", |
|
||||||
"id": "swe/o:001", |
|
||||||
"gpid": 13835 |
|
||||||
}, |
|
||||||
{ "name": "8.4cm Feltkanon m/1887", |
|
||||||
"type": "ART", |
|
||||||
"comments": [ "QSU", "No Gunshield", "Acquisition NA" ], |
|
||||||
"note_number": "3", |
|
||||||
"id": "swe/o:002", |
|
||||||
"gpid": 13836 |
|
||||||
} |
|
||||||
|
|
||||||
] |
|
@ -1,65 +0,0 @@ |
|||||||
{ |
|
||||||
"6996": {"is_small": true}, |
|
||||||
"485": {"is_small": true}, |
|
||||||
"850": {"is_small": true}, |
|
||||||
"849": {"is_small": true}, |
|
||||||
"12689": {"is_small": true}, |
|
||||||
"856": {"is_small": true}, |
|
||||||
"857": {"is_small": true}, |
|
||||||
"11336": {"is_small": true}, |
|
||||||
"858": {"is_small": true}, |
|
||||||
"11337": {"is_small": true}, |
|
||||||
"1149": {"is_small": true}, |
|
||||||
"1153": {"is_small": true}, |
|
||||||
"12687": {"is_small": true}, |
|
||||||
"3b5:7613": {"is_small": true}, |
|
||||||
"11359": {"is_small": true}, |
|
||||||
"3b5:11259": {"is_small": true}, |
|
||||||
"1632": {"is_small": true}, |
|
||||||
"1636": {"is_small": true}, |
|
||||||
"1641": {"is_small": true}, |
|
||||||
"1648": {"is_small": true}, |
|
||||||
"1982": {"is_small": true}, |
|
||||||
"1983": {"is_small": true}, |
|
||||||
"1984": {"is_small": true}, |
|
||||||
"1985": {"is_small": true}, |
|
||||||
"1986": {"is_small": true}, |
|
||||||
"1987": {"is_small": true}, |
|
||||||
"1988": {"is_small": true}, |
|
||||||
"2172": {"is_small": true}, |
|
||||||
"2173": {"is_small": true}, |
|
||||||
"2176": {"is_small": true}, |
|
||||||
"2179": {"is_small": true}, |
|
||||||
"11391": {"is_small": true}, |
|
||||||
"11392": {"is_small": true}, |
|
||||||
"11395": {"is_small": true}, |
|
||||||
"11396": {"is_small": true}, |
|
||||||
"11440": {"is_small": true}, |
|
||||||
"3b5:8401": {"is_small": true}, |
|
||||||
"3b5:8402": {"is_small": true}, |
|
||||||
"2465": {"is_small": true}, |
|
||||||
"2474": {"is_small": true}, |
|
||||||
"3252": {"is_small": true}, |
|
||||||
"3253": {"is_small": true}, |
|
||||||
"3263": {"is_small": true}, |
|
||||||
"3422": {"is_small": true}, |
|
||||||
"3428": {"is_small": true}, |
|
||||||
"6730": {"is_small": true}, |
|
||||||
"3605": {"is_small": true}, |
|
||||||
"3608": {"is_small": true}, |
|
||||||
"6763": {"is_small": true}, |
|
||||||
"3679": {"is_small": true}, |
|
||||||
"3680": {"is_small": true}, |
|
||||||
"3681": {"is_small": true}, |
|
||||||
"3682": {"is_small": true}, |
|
||||||
"3691": {"is_small": true}, |
|
||||||
"3692": {"is_small": true}, |
|
||||||
"3959": {"is_small": true}, |
|
||||||
"11558": {"is_small": true}, |
|
||||||
"11559": {"is_small": true}, |
|
||||||
"3b5:10150": {"is_small": true}, |
|
||||||
"3b5:10151": {"is_small": true}, |
|
||||||
"11600": {"is_small": true}, |
|
||||||
"11604": {"is_small": true}, |
|
||||||
"3b5:7871": {"is_small": true} |
|
||||||
} |
|
@ -1,65 +0,0 @@ |
|||||||
{ |
|
||||||
"6996": {"is_small": true}, |
|
||||||
"485": {"is_small": true}, |
|
||||||
"850": {"is_small": true}, |
|
||||||
"849": {"is_small": true}, |
|
||||||
"12689": {"is_small": true}, |
|
||||||
"856": {"is_small": true}, |
|
||||||
"857": {"is_small": true}, |
|
||||||
"11336": {"is_small": true}, |
|
||||||
"858": {"is_small": true}, |
|
||||||
"11337": {"is_small": true}, |
|
||||||
"1149": {"is_small": true}, |
|
||||||
"1153": {"is_small": true}, |
|
||||||
"12687": {"is_small": true}, |
|
||||||
"3b5:7613": {"is_small": true}, |
|
||||||
"11359": {"is_small": true}, |
|
||||||
"3b5:11259": {"is_small": true}, |
|
||||||
"1632": {"is_small": true}, |
|
||||||
"1636": {"is_small": true}, |
|
||||||
"1641": {"is_small": true}, |
|
||||||
"1648": {"is_small": true}, |
|
||||||
"1982": {"is_small": true}, |
|
||||||
"1983": {"is_small": true}, |
|
||||||
"1984": {"is_small": true}, |
|
||||||
"1985": {"is_small": true}, |
|
||||||
"1986": {"is_small": true}, |
|
||||||
"1987": {"is_small": true}, |
|
||||||
"1988": {"is_small": true}, |
|
||||||
"2172": {"is_small": true}, |
|
||||||
"2173": {"is_small": true}, |
|
||||||
"2176": {"is_small": true}, |
|
||||||
"2179": {"is_small": true}, |
|
||||||
"11391": {"is_small": true}, |
|
||||||
"11392": {"is_small": true}, |
|
||||||
"11395": {"is_small": true}, |
|
||||||
"11396": {"is_small": true}, |
|
||||||
"11440": {"is_small": true}, |
|
||||||
"3b5:8401": {"is_small": true}, |
|
||||||
"3b5:8402": {"is_small": true}, |
|
||||||
"2465": {"is_small": true}, |
|
||||||
"2474": {"is_small": true}, |
|
||||||
"3252": {"is_small": true}, |
|
||||||
"3253": {"is_small": true}, |
|
||||||
"3263": {"is_small": true}, |
|
||||||
"3422": {"is_small": true}, |
|
||||||
"3428": {"is_small": true}, |
|
||||||
"6730": {"is_small": true}, |
|
||||||
"3605": {"is_small": true}, |
|
||||||
"3608": {"is_small": true}, |
|
||||||
"6763": {"is_small": true}, |
|
||||||
"3679": {"is_small": true}, |
|
||||||
"3680": {"is_small": true}, |
|
||||||
"3681": {"is_small": true}, |
|
||||||
"3682": {"is_small": true}, |
|
||||||
"3691": {"is_small": true}, |
|
||||||
"3692": {"is_small": true}, |
|
||||||
"3959": {"is_small": true}, |
|
||||||
"11558": {"is_small": true}, |
|
||||||
"11559": {"is_small": true}, |
|
||||||
"3b5:10150": {"is_small": true}, |
|
||||||
"3b5:10151": {"is_small": true}, |
|
||||||
"11600": {"is_small": true}, |
|
||||||
"11604": {"is_small": true}, |
|
||||||
"3b5:7871": {"is_small": true} |
|
||||||
} |
|
@ -1,65 +0,0 @@ |
|||||||
{ |
|
||||||
"6996": {"is_small": true}, |
|
||||||
"485": {"is_small": true}, |
|
||||||
"850": {"is_small": true}, |
|
||||||
"849": {"is_small": true}, |
|
||||||
"12689": {"is_small": true}, |
|
||||||
"856": {"is_small": true}, |
|
||||||
"857": {"is_small": true}, |
|
||||||
"11336": {"is_small": true}, |
|
||||||
"858": {"is_small": true}, |
|
||||||
"11337": {"is_small": true}, |
|
||||||
"1149": {"is_small": true}, |
|
||||||
"1153": {"is_small": true}, |
|
||||||
"12687": {"is_small": true}, |
|
||||||
"3b5:7613": {"is_small": true}, |
|
||||||
"11359": {"is_small": true}, |
|
||||||
"3b5:11259": {"is_small": true}, |
|
||||||
"1632": {"is_small": true}, |
|
||||||
"1636": {"is_small": true}, |
|
||||||
"1641": {"is_small": true}, |
|
||||||
"1648": {"is_small": true}, |
|
||||||
"1982": {"is_small": true}, |
|
||||||
"1983": {"is_small": true}, |
|
||||||
"1984": {"is_small": true}, |
|
||||||
"1985": {"is_small": true}, |
|
||||||
"1986": {"is_small": true}, |
|
||||||
"1987": {"is_small": true}, |
|
||||||
"1988": {"is_small": true}, |
|
||||||
"2172": {"is_small": true}, |
|
||||||
"2173": {"is_small": true}, |
|
||||||
"2176": {"is_small": true}, |
|
||||||
"2179": {"is_small": true}, |
|
||||||
"11391": {"is_small": true}, |
|
||||||
"11392": {"is_small": true}, |
|
||||||
"11395": {"is_small": true}, |
|
||||||
"11396": {"is_small": true}, |
|
||||||
"11440": {"is_small": true}, |
|
||||||
"3b5:8401": {"is_small": true}, |
|
||||||
"3b5:8402": {"is_small": true}, |
|
||||||
"2465": {"is_small": true}, |
|
||||||
"2474": {"is_small": true}, |
|
||||||
"3252": {"is_small": true}, |
|
||||||
"3253": {"is_small": true}, |
|
||||||
"3263": {"is_small": true}, |
|
||||||
"3422": {"is_small": true}, |
|
||||||
"3428": {"is_small": true}, |
|
||||||
"6730": {"is_small": true}, |
|
||||||
"3605": {"is_small": true}, |
|
||||||
"3608": {"is_small": true}, |
|
||||||
"6763": {"is_small": true}, |
|
||||||
"3679": {"is_small": true}, |
|
||||||
"3680": {"is_small": true}, |
|
||||||
"3681": {"is_small": true}, |
|
||||||
"3682": {"is_small": true}, |
|
||||||
"3691": {"is_small": true}, |
|
||||||
"3692": {"is_small": true}, |
|
||||||
"3959": {"is_small": true}, |
|
||||||
"11558": {"is_small": true}, |
|
||||||
"11559": {"is_small": true}, |
|
||||||
"3b5:10150": {"is_small": true}, |
|
||||||
"3b5:10151": {"is_small": true}, |
|
||||||
"11600": {"is_small": true}, |
|
||||||
"11604": {"is_small": true}, |
|
||||||
"3b5:7871": {"is_small": true} |
|
||||||
} |
|
@ -1,43 +0,0 @@ |
|||||||
{ |
|
||||||
|
|
||||||
"1555": { |
|
||||||
"name": "2pdr Portee", |
|
||||||
"front_images": [ "br/vehicles/portee.gif", "br/vehicles/portee0.gif" ], |
|
||||||
"back_images": null |
|
||||||
}, |
|
||||||
|
|
||||||
"2212": { |
|
||||||
"name": "76* INF FRC", |
|
||||||
"front_images": [ "al/gun/alINF76.gif", "al/gun/alINF76u.gif" ], |
|
||||||
"back_images": "al/gun/alINF76b.gif" |
|
||||||
}, |
|
||||||
|
|
||||||
"7409": { |
|
||||||
"name": "76 ItK/28 B(s)", |
|
||||||
"front_images": "fi/gun/fiAA76L.png", |
|
||||||
"back_images": [ "fi/gun/fiAA76L.png", "fi/gun/fiAA76LB.png" ] |
|
||||||
}, |
|
||||||
|
|
||||||
"adf:1828": { |
|
||||||
"name": "105 ART wz.29", |
|
||||||
"front_images": "po/gun/poARTwz29-BFP.png", |
|
||||||
"back_images": [ "po/gun/poARTwz29-BFP.png", "po/gun/poARTwz29-BFPb.png" ] |
|
||||||
}, |
|
||||||
"adf:1829": { |
|
||||||
"name": "120* ART wz09.31", |
|
||||||
"front_images": "po/gun/poARTwz0931-BFP.png", |
|
||||||
"back_images": [ "po/gun/poARTwz0931-BFP.png", "po/gun/poARTwz0931-BFPb.png" ] |
|
||||||
}, |
|
||||||
"adf:1830": { |
|
||||||
"name": "155 ART wz.17", |
|
||||||
"front_images": "po/gun/poARTwz17-BFP.png", |
|
||||||
"back_images": [ "po/gun/poARTwz17-BFP.png", "po/gun/poARTwz17-BFPb.png" ] |
|
||||||
}, |
|
||||||
|
|
||||||
"3b5:3676": { |
|
||||||
"name": "M19A1 MGMC", |
|
||||||
"front_images": [ "us/veh/usM19A1MGMC(trailer)KFW.png", "us/veh/usM19A1MGMC(KFW).png" ], |
|
||||||
"back_images": null |
|
||||||
} |
|
||||||
|
|
||||||
} |
|