Skip to content

Commit

Permalink
✨ 🐛 5e: Magic Variants
Browse files Browse the repository at this point in the history
  • Loading branch information
ebullient committed Oct 31, 2023
1 parent 3737892 commit afbabe8
Show file tree
Hide file tree
Showing 15 changed files with 733 additions and 58 deletions.
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
<quarkus.platform.version>3.5.0</quarkus.platform.version>
<!-- Libraries -->
<assertj.version>3.24.2</assertj.version>
<evalex.version>3.0.5</evalex.version>
<github-slugify.version>3.0.6</github-slugify.version>
<icu4j.version>73.2</icu4j.version><!-- Optional dependency of Slugify -->
<!-- Packaging -->
Expand Down Expand Up @@ -83,6 +84,11 @@
<artifactId>icu4j</artifactId>
<version>${icu4j.version}</version>
</dependency>
<dependency>
<groupId>com.ezylang</groupId>
<artifactId>EvalEx</artifactId>
<version>${evalex.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-qute</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ default String replaceTokens(String input, BiFunction<String, Boolean, String> t

for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
//char c2 = i + 1 < input.length() ? input.charAt(i + 1) : NUL;

switch (c) {
case '{':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.fasterxml.jackson.databind.JsonNode;

import dev.ebullient.convert.qute.ImageRef;
import dev.ebullient.convert.tools.JsonNodeReader;
import dev.ebullient.convert.tools.Tags;
import dev.ebullient.convert.tools.dnd5e.ItemProperty.PropertyEnum;
import dev.ebullient.convert.tools.dnd5e.ItemType.ItemEnum;
Expand Down Expand Up @@ -302,4 +303,12 @@ String createDetail(String attunement, Collection<ItemProperty> properties) {
return replacement.toString();
}

enum ItemFields implements JsonNodeReader {
hasFluff,
hasFluffImages,
property,
type,
value,
weight,
}
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import dev.ebullient.convert.qute.ImageRef;
import dev.ebullient.convert.tools.JsonNodeReader;
import dev.ebullient.convert.tools.Tags;
import dev.ebullient.convert.tools.ToolsIndex.TtrpgValue;
import dev.ebullient.convert.tools.dnd5e.Tools5eIndex.Tuple;
import dev.ebullient.convert.tools.dnd5e.qute.QuteRace;

Expand Down Expand Up @@ -167,6 +168,8 @@ public static List<Tuple> findRaceVariants(Tools5eIndex index, Tools5eIndexType
index.originSubraces(sources).forEach(sr -> {
JsonNode newNode = copier.mergeSubrace(type, sr, jsonSource);
String srKey = Tools5eIndexType.subrace.createKey(newNode);
TtrpgValue.indexInputType.setIn(newNode, Tools5eIndexType.subrace.name());
TtrpgValue.indexKey.setIn(newNode, srKey);
variants.add(new Tuple(srKey, newNode));

// {@race Aasimar (Fallen)|VGM}
Expand Down
21 changes: 21 additions & 0 deletions src/main/java/dev/ebullient/convert/tools/dnd5e/JsonSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -1077,6 +1077,25 @@ default String numberToText(int value) {
strValue);
}

default String damageTypeToFull(String dmgType) {
return switch (dmgType) {
case "A" -> "acid";
case "B" -> "bludgeoning";
case "C" -> "cold";
case "F" -> "fire";
case "O" -> "force";
case "L" -> "lightning";
case "N" -> "necrotic";
case "P" -> "piercing";
case "I" -> "poison";
case "Y" -> "psychic";
case "R" -> "radiant";
case "S" -> "slashing";
case "T" -> "thunder";
default -> dmgType;
};
};

default String convertCurrency(int cp) {
List<String> result = new ArrayList<>();
int gp = cp / 100;
Expand Down Expand Up @@ -1160,6 +1179,7 @@ enum Tools5eFields implements JsonNodeReader {
amount,
appliesTo,
attributes,
basicRules,
by,
className,
classSource,
Expand All @@ -1184,6 +1204,7 @@ enum Tools5eFields implements JsonNodeReader {
size,
sort, // monsters, vehicles (sorted traits)
speed,
srd,
style,
subclass,
subrace,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1047,20 +1047,22 @@ void removeFromArray(String originKey, JsonNode modInfo, String prop, ArrayNode
}
}
} else if (items != null) {
for (JsonNode itemToRemove : iterableElements(items)) {
int index = findIndex(tgtArray, itemToRemove);
if (index >= 0) {
tgtArray.remove(index);
} else {
tui().errorf("Error (%s / %s): Unable to remove %s; %s", originKey, prop, itemToRemove, modInfo);
}
}
removeFromArr(tgtArray, items);
} else {
tui().errorf("Error (%s / %s): One of names or items must be provided to remove elements from array; %s", originKey,
prop, modInfo);
}
}

void removeFromArr(ArrayNode tgtArray, JsonNode items) {
for (JsonNode itemToRemove : iterableElements(items)) {
int index = findIndex(tgtArray, itemToRemove);
if (index >= 0) {
tgtArray.remove(index);
}
}
}

boolean replaceArray(String originKey, JsonNode modInfo, ArrayNode tgtArray, JsonNode items) {
if (items == null || !items.isArray()) {
return false;
Expand Down Expand Up @@ -1205,34 +1207,35 @@ enum MetaFields implements JsonNodeReader {
_preserve,
_root,
_trait,
alias,
apply,
data,
dex,
dex_mod,
flags,
floor,
force,
index,
items,
joiner,
max,
mode,
names,
overwrite,
prof_bonus,
prop,
props,
range,
regex,
replace,
root,
str,
with,
prop,
scalar,
floor,
max,
value,
type,
range,
skills,
alias,
overwrite;
str,
type,
value,
with,
;
}

enum TemplateVariable implements JsonNodeReader.FieldValue {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,22 @@
import dev.ebullient.convert.tools.dnd5e.qute.Tools5eQuteBase;

public interface JsonTextReplacement extends JsonTextConverter<Tools5eIndexType> {
Pattern FRACTIONAL = Pattern.compile("^(\\d+)?([⅛¼⅜½⅝¾⅞⅓⅔⅙⅚])?$");

Pattern linkifyPattern = Pattern.compile(
static final Pattern FRACTIONAL = Pattern.compile("^(\\d+)?([⅛¼⅜½⅝¾⅞⅓⅔⅙⅚])?$");
static final Pattern linkifyPattern = Pattern.compile(
"\\{@(action|background|class|condition|creature|deity|disease|feat|card|deck|hazard|item|legroup|object|race|reward|sense|skill|spell|status|table|variantrule|vehicle|optfeature|classFeature|subclassFeature|trap) ([^}]+)}");

Pattern dicePattern = Pattern.compile("\\{@(dice|damage) ([^{}]+)}");

Pattern chancePattern = Pattern.compile("\\{@chance ([^}]+)}");
Pattern fontPattern = Pattern.compile("\\{@font ([^}]+)}");
Pattern homebrewPattern = Pattern.compile("\\{@homebrew ([^}]+)}");
Pattern quickRefPattern = Pattern.compile("\\{@quickref ([^}]+)}");
Pattern notePattern = Pattern.compile("\\{@note (\\*|Note:)?\\s?([^}]+)}");
Pattern footnotePattern = Pattern.compile("\\{@footnote ([^}]+)}");
Pattern abilitySavePattern = Pattern.compile("\\{@(ability|savingThrow) ([^}]+)}"); // {@ability str 20}
Pattern skillCheckPattern = Pattern.compile("\\{@skillCheck ([^}]+)}"); // {@skillCheck animal_handling 5}
Pattern optionalFeaturesFilter = Pattern.compile("\\{@filter ([^|}]+)\\|optionalfeatures\\|([^}]+)*}");
Pattern featureTypePattern = Pattern.compile("(?:[Ff]eature )?[Tt]ype=([^|}]+)");
Pattern featureSourcePattern = Pattern.compile("source=([^|}]+)");
Pattern superscriptCitationPattern = Pattern.compile("\\{@(sup|cite) ([^}]+)}");
static final Pattern dicePattern = Pattern.compile("\\{@(dice|damage) ([^{}]+)}");
static final Pattern chancePattern = Pattern.compile("\\{@chance ([^}]+)}");
static final Pattern fontPattern = Pattern.compile("\\{@font ([^}]+)}");
static final Pattern homebrewPattern = Pattern.compile("\\{@homebrew ([^}]+)}");
static final Pattern quickRefPattern = Pattern.compile("\\{@quickref ([^}]+)}");
static final Pattern notePattern = Pattern.compile("\\{@note (\\*|Note:)?\\s?([^}]+)}");
static final Pattern footnotePattern = Pattern.compile("\\{@footnote ([^}]+)}");
static final Pattern abilitySavePattern = Pattern.compile("\\{@(ability|savingThrow) ([^}]+)}"); // {@ability str 20}
static final Pattern skillCheckPattern = Pattern.compile("\\{@skillCheck ([^}]+)}"); // {@skillCheck animal_handling 5}
static final Pattern optionalFeaturesFilter = Pattern.compile("\\{@filter ([^|}]+)\\|optionalfeatures\\|([^}]+)*}");
static final Pattern featureTypePattern = Pattern.compile("(?:[Ff]eature )?[Tt]ype=([^|}]+)");
static final Pattern featureSourcePattern = Pattern.compile("source=([^|}]+)");
static final Pattern superscriptCitationPattern = Pattern.compile("\\{@(sup|cite) ([^}]+)}");

Tools5eIndex index();

Expand Down
33 changes: 21 additions & 12 deletions src/main/java/dev/ebullient/convert/tools/dnd5e/Tools5eIndex.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
Expand Down Expand Up @@ -260,6 +261,10 @@ private boolean addHomebrewSourcesIfPresent(String filename, JsonNode node) {
}

void addToIndex(Tools5eIndexType type, JsonNode node) {
if (type == Tools5eIndexType.magicvariant) {
// This will populate the source field..
Json2QuteMagicVariant.populateGenericVariant(node, copier);
}
String key = type.createKey(node);
if (nodeIndex.containsKey(key)) {
return;
Expand All @@ -275,18 +280,15 @@ void addToIndex(Tools5eIndexType type, JsonNode node) {
String lookupKey = String.format("%s|%s|", parts[0], parts[1]);
classRoot.put(lookupKey, key);
}
}
if (type == Tools5eIndexType.itemProperty && homebrew != null) {
} else if (type == Tools5eIndexType.itemProperty && homebrew != null) {
// lookup by abbreviation
String[] parts = key.split("\\|");
homebrew.itemProperties.put(parts[1].toLowerCase(), new CustomItemProperty(node));
}
if (type == Tools5eIndexType.itemType && homebrew != null) {
} else if (type == Tools5eIndexType.itemType && homebrew != null) {
// lookup by abbreviation
String[] parts = key.split("\\|");
homebrew.itemTypes.put(parts[1].toLowerCase(), new CustomItemType(node));
}
if (type == Tools5eIndexType.optionalfeature) {
} else if (type == Tools5eIndexType.optionalfeature) {
String lookup = null;
for (String ft : toListOfStrings(node.get("featureType"))) {
try {
Expand All @@ -305,21 +307,19 @@ void addToIndex(Tools5eIndexType type, JsonNode node) {
if (lookup != null) {
((ObjectNode) node).put("typeLookup", lookup);
}
}
if (type == Tools5eIndexType.subclass) {
} else if (type == Tools5eIndexType.subclass) {
String lookupKey = Tools5eIndexType.getSubclassKey(
getTextOrEmpty(node, "className"), getTextOrEmpty(node, "classSource"),
getTextOrEmpty(node, "shortName"), getTextOrEmpty(node, "source"));
// add subclass to alias. Referenced from spells
addAlias(lookupKey, key);
}
if (type == Tools5eIndexType.table || type == Tools5eIndexType.tableGroup || type == Tools5eIndexType.citation) {
} else if (type == Tools5eIndexType.table || type == Tools5eIndexType.tableGroup) {
SourceAndPage sp = new SourceAndPage(node);
tableIndex.computeIfAbsent(sp, k -> new ArrayList<>()).add(node);
}
if (type == Tools5eIndexType.language && HomebrewFields.fonts.existsIn(node)) {
} else if (type == Tools5eIndexType.language && HomebrewFields.fonts.existsIn(node)) {
Tools5eSources.addFonts(node, HomebrewFields.fonts);
}

if (node.has("srd")) {
srdKeys.add(key);
}
Expand Down Expand Up @@ -495,6 +495,8 @@ List<Tuple> findVariants(String key, JsonNode jsonSource) {
Tools5eIndexType type = Tools5eIndexType.getTypeFromKey(key);
if (type == Tools5eIndexType.race) {
return Json2QuteRace.findRaceVariants(this, type, key, jsonSource, copier);
} else if (type == Tools5eIndexType.magicvariant) {
return Json2QuteMagicVariant.findSpecificVariants(this, type, key, jsonSource, copier);
} else if (type == Tools5eIndexType.monster && jsonSource.has("summonedBySpellLevel")) {
return Json2QuteMonster.findConjuredMonsterVariants(this, type, key, jsonSource);
} else if (key.contains("splugoth the returned") || key.contains("prophetess dran")) {
Expand Down Expand Up @@ -766,6 +768,13 @@ private Optional<JsonNode> matchTable(String rowData, JsonNode table) {
return Optional.empty();
}

public List<JsonNode> originNodesMatching(Function<JsonNode, Boolean> filter) {
return nodeIndex.entrySet().stream()
.filter(e -> filter.apply(e.getValue()))
.map(Entry::getValue)
.collect(Collectors.toList());
}

public JsonNode getOrigin(String finalKey) {
return nodeIndex.get(finalKey);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ public boolean writeFile() {
hazard,
item,
legendaryGroup,
// magicvariant,
magicvariant,
monster,
object,
optionalfeature,
Expand Down Expand Up @@ -470,7 +470,7 @@ public String getRelativePath() {
case card, deck -> "decks";
case deity -> "deities";
case legendaryGroup -> "bestiary/legendary-group";
// case magicvariant -> "items";
case magicvariant -> "items";
case monster -> "bestiary";
case optionalfeature, optionalFeatureTypes -> "optional-features";
case race, subrace -> "races";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ private QuteBase json2qute(Tools5eIndexType type, JsonNode jsonSource) {
case feat -> new Json2QuteFeat(index, type, jsonSource).build();
case hazard, trap -> new Json2QuteHazard(index, type, jsonSource).build();
case item -> new Json2QuteItem(index, type, jsonSource).build();
case magicvariant -> new Json2QuteMagicVariant(index, type, jsonSource).build();
case monster -> new Json2QuteMonster(index, type, jsonSource).build();
case object -> new Json2QuteObject(index, type, jsonSource).build();
case optionalfeature -> new Json2QuteOptionalFeature(index, type, jsonSource).build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public QuteItem(Tools5eSources sources, String name, String source, String detai
this.stealthPenalty = stealthPenalty;
this.cost = costGp;
this.weight = weightLbs;
this.fluffImages = images;
this.fluffImages = images == null ? List.of() : images;
this.prerequisite = prerequisite; // optional
}
}
5 changes: 0 additions & 5 deletions src/test/java/dev/ebullient/convert/tools/TokenizerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,31 +28,26 @@ public static void prepare() {

@Override
public void appendToText(List<String> inner, JsonNode target, String heading) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'appendToText'");
}

@Override
public CompendiumConfig cfg() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'cfg'");
}

@Override
public String linkify(IndexType type, String s) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'linkify'");
}

@Override
public String replaceText(String s) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'replaceText'");
}

@Override
public Tui tui() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'tui'");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ public void testItemList(Path outputPath) {

MarkdownWriter writer = new MarkdownWriter(outputPath, templates, tui);
index.markdownConverter(writer, TtrpgConfig.imageFallbackPaths())
.writeFiles(Tools5eIndexType.item)
.writeFiles(List.of(Tools5eIndexType.item, Tools5eIndexType.magicvariant))
.writeImages();

TestUtils.assertDirectoryContents(itemDir, tui);
Expand Down
Loading

0 comments on commit afbabe8

Please sign in to comment.