kopia lustrzana https://github.com/Aircoookie/WLED
231 wiersze
5.9 KiB
Python
231 wiersze
5.9 KiB
Python
'''
|
|
File for generating roll labels and info text for the InfoMenu.
|
|
|
|
Uses a very limited markdown language for styling text.
|
|
'''
|
|
import math
|
|
from pathlib import Path
|
|
import re
|
|
from textwrap import indent
|
|
|
|
# Variables for calculating values in info text
|
|
CASTER_LEVEL = 9
|
|
SPELL_ABILITY_MOD = 6
|
|
BASE_ATK_BONUS = 6
|
|
SIZE_BONUS = 1
|
|
STR_BONUS = 2
|
|
DEX_BONUS = -1
|
|
|
|
# TFT library color values
|
|
TFT_BLACK =0x0000
|
|
TFT_NAVY =0x000F
|
|
TFT_DARKGREEN =0x03E0
|
|
TFT_DARKCYAN =0x03EF
|
|
TFT_MAROON =0x7800
|
|
TFT_PURPLE =0x780F
|
|
TFT_OLIVE =0x7BE0
|
|
TFT_LIGHTGREY =0xD69A
|
|
TFT_DARKGREY =0x7BEF
|
|
TFT_BLUE =0x001F
|
|
TFT_GREEN =0x07E0
|
|
TFT_CYAN =0x07FF
|
|
TFT_RED =0xF800
|
|
TFT_MAGENTA =0xF81F
|
|
TFT_YELLOW =0xFFE0
|
|
TFT_WHITE =0xFFFF
|
|
TFT_ORANGE =0xFDA0
|
|
TFT_GREENYELLOW =0xB7E0
|
|
TFT_PINK =0xFE19
|
|
TFT_BROWN =0x9A60
|
|
TFT_GOLD =0xFEA0
|
|
TFT_SILVER =0xC618
|
|
TFT_SKYBLUE =0x867D
|
|
TFT_VIOLET =0x915C
|
|
|
|
|
|
class Size:
|
|
def __init__(self, w, h):
|
|
self.w = w
|
|
self.h = h
|
|
|
|
|
|
# Font 1 6x8
|
|
# Font 2 12x16
|
|
CHAR_SIZE = {
|
|
1: Size(6, 8),
|
|
2: Size(12, 16),
|
|
}
|
|
|
|
SCREEN_SIZE = Size(128, 128)
|
|
|
|
# Calculates distance for short range spell.
|
|
def short_range() -> int:
|
|
return 25 + 5 * CASTER_LEVEL
|
|
|
|
# Entries in markdown language.
|
|
# Parameter 0 of the tuple is the roll name
|
|
# Parameter 1 of the tuple is the roll info.
|
|
# The text will be shown when the roll type is selected. An error will be raised
|
|
# if the text would unexpectedly goes past the end of the screen. There are a
|
|
# few styling parameters that need to be on their own lines:
|
|
# $COLOR - The color for the text
|
|
# $SIZE - Sets the text size (see CHAR_SIZE)
|
|
# $WRAP - By default text won't wrap and generate an error. This enables text wrapping. Lines will wrap mid-word.
|
|
ENTRIES = [
|
|
tuple(["Barb Chain", f'''\
|
|
$COLOR({TFT_RED})
|
|
Barb Chain
|
|
$COLOR({TFT_WHITE})
|
|
Atk/CMD {BASE_ATK_BONUS + SPELL_ABILITY_MOD}
|
|
Range: {short_range()}
|
|
$WRAP(1)
|
|
$SIZE(1)
|
|
Summon {1 + math.floor((CASTER_LEVEL-1)/3)} chains. Make a melee atk 1d6 or a trip CMD=AT. On a hit make Will save or shaken 1d4 rnds.
|
|
''']),
|
|
tuple(["Saves", f'''\
|
|
$COLOR({TFT_GREEN})
|
|
Saves
|
|
$COLOR({TFT_WHITE})
|
|
FORT 8
|
|
REFLEX 8
|
|
WILL 9
|
|
''']),
|
|
tuple(["Skill", f'''\
|
|
Skill
|
|
''']),
|
|
tuple(["Attack", f'''\
|
|
Attack
|
|
Melee +{BASE_ATK_BONUS + SIZE_BONUS + STR_BONUS}
|
|
Range +{BASE_ATK_BONUS + SIZE_BONUS + DEX_BONUS}
|
|
''']),
|
|
tuple(["Cure", f'''\
|
|
Cure
|
|
Lit 1d8+{min(5, CASTER_LEVEL)}
|
|
Mod 2d8+{min(10, CASTER_LEVEL)}
|
|
Ser 3d8+{min(15, CASTER_LEVEL)}
|
|
''']),
|
|
tuple(["Concentrate", f'''\
|
|
Concentrat
|
|
+{CASTER_LEVEL + SPELL_ABILITY_MOD}
|
|
$SIZE(1)
|
|
Defensive 15+2*SP_LV
|
|
Dmg 10+DMG+SP_LV
|
|
Grapple 10+CMB+SP_LV
|
|
''']),
|
|
]
|
|
|
|
RE_SIZE = re.compile(r'\$SIZE\(([0-9])\)')
|
|
RE_COLOR = re.compile(r'\$COLOR\(([0-9]+)\)')
|
|
RE_WRAP = re.compile(r'\$WRAP\(([0-9])\)')
|
|
|
|
END_HEADER_TXT = '// GENERATED\n'
|
|
|
|
def main():
|
|
roll_info_file = Path(__file__).parent / 'roll_info.h'
|
|
old_contents = open(roll_info_file, 'r').read()
|
|
|
|
end_header = old_contents.index(END_HEADER_TXT)
|
|
|
|
with open(roll_info_file, 'w') as fd:
|
|
fd.write(old_contents[:end_header+len(END_HEADER_TXT)])
|
|
|
|
for key, entry in enumerate(ENTRIES):
|
|
size = 2
|
|
wrap = False
|
|
y_loc = 0
|
|
results = []
|
|
for line in entry[1].splitlines():
|
|
if line.startswith('$'):
|
|
m_size = RE_SIZE.match(line)
|
|
m_color = RE_COLOR.match(line)
|
|
m_wrap = RE_WRAP.match(line)
|
|
if m_size:
|
|
size = int(m_size.group(1))
|
|
results.append(f'tft.setTextSize({size});')
|
|
elif m_color:
|
|
results.append(
|
|
f'tft.setTextColor({int(m_color.group(1))});')
|
|
elif m_wrap:
|
|
wrap = bool(int(m_wrap.group(1)))
|
|
else:
|
|
print(f'Entry {key} unknown modifier "{line}".')
|
|
exit(1)
|
|
else:
|
|
max_chars_per_line = math.floor(
|
|
SCREEN_SIZE.w / CHAR_SIZE[size].w)
|
|
if len(line) > max_chars_per_line:
|
|
if wrap:
|
|
while len(line) > max_chars_per_line:
|
|
results.append(
|
|
f'tft.println("{line[:max_chars_per_line]}");')
|
|
line = line[max_chars_per_line:].lstrip()
|
|
y_loc += CHAR_SIZE[size].h
|
|
else:
|
|
print(f'Entry {key} line "{line}" too long.')
|
|
exit(1)
|
|
|
|
if len(line) > 0:
|
|
y_loc += CHAR_SIZE[size].h
|
|
results.append(f'tft.println("{line}");')
|
|
|
|
if y_loc > SCREEN_SIZE.h:
|
|
print(
|
|
f'Entry {key} line "{line}" went past bottom of screen.')
|
|
exit(1)
|
|
|
|
result = indent('\n'.join(results), ' ')
|
|
|
|
fd.write(f'''\
|
|
static void PrintRoll{key}() {{
|
|
{result}
|
|
}}
|
|
|
|
''')
|
|
|
|
results = []
|
|
for key, entry in enumerate(ENTRIES):
|
|
results.append(f'''\
|
|
case {key}:
|
|
return "{entry[0]}";''')
|
|
|
|
cases = indent('\n'.join(results), ' ')
|
|
|
|
fd.write(f'''\
|
|
static const char* GetRollName(uint8_t key) {{
|
|
switch (key) {{
|
|
{cases}
|
|
}}
|
|
return "";
|
|
}}
|
|
|
|
''')
|
|
|
|
results = []
|
|
for key, entry in enumerate(ENTRIES):
|
|
results.append(f'''\
|
|
case {key}:
|
|
PrintRoll{key}();
|
|
return;''')
|
|
|
|
cases = indent('\n'.join(results), ' ')
|
|
|
|
fd.write(f'''\
|
|
static void PrintRollInfo(uint8_t key) {{
|
|
tft.setTextColor(TFT_WHITE);
|
|
tft.setCursor(0, 0);
|
|
tft.setTextSize(2);
|
|
switch (key) {{
|
|
{cases}
|
|
}}
|
|
tft.setTextColor(TFT_RED);
|
|
tft.setCursor(0, 60);
|
|
tft.println("Unknown");
|
|
}}
|
|
|
|
''')
|
|
|
|
fd.write(f'static constexpr size_t NUM_ROLL_INFOS = {len(ENTRIES)};\n')
|
|
|
|
|
|
main()
|