private static string WriteSpecialAbility(HeroLabCharacter character, HeroLabSpecial specialAbilities) { var stringBuilder = new StringBuilder($"!HeroLabImporter --name {character.Name} --mode add --addtype abilities"); stringBuilder.Append($" --set name {specialAbilities.Name}"); stringBuilder.Append($" --set type {GetSpecialAbilityType(specialAbilities.Type)}"); stringBuilder.Append($" --set descflag 1"); stringBuilder.Append($" --set options-flag 0"); stringBuilder.Append($" --set description {OneLineString(specialAbilities.Description.Replace('\r', ' ').Replace('\n', ' ').Trim())}"); return(stringBuilder.ToString()); }
private static string WriteNpcSpellLikeAbility(HeroLabCharacter character, HeroLabSpecial spellLikeAbility) { var stringBuilder = new StringBuilder($"!HeroLabImporter --name {character.Name} --mode add --addtype spell-like"); if (spellLikeAbility.Name.ToLower().Contains("(constant)")) { stringBuilder.Append(" --set timesperday constant"); } else if (spellLikeAbility.Name.ToLower().Contains("(at will)")) { stringBuilder.Append(" --set timesperday at-will"); } else if (spellLikeAbility.Name.ToLower().Contains("/day")) { stringBuilder.Append(" --set timesperday per-day"); } else if (spellLikeAbility.Name.ToLower().Contains("/hour")) { stringBuilder.Append(" --set timesperday per-hour"); } else if (spellLikeAbility.Name.ToLower().Contains("/week")) { stringBuilder.Append(" --set timesperday per-week"); } else if (spellLikeAbility.Name.ToLower().Contains("/month")) { stringBuilder.Append(" --set timesperday per-month"); } else if (spellLikeAbility.Name.ToLower().Contains("/year")) { stringBuilder.Append(" --set timesperday per-year"); } var trackedResource = character.TrackedResources.Items.FirstOrDefault(tr => tr.Name == spellLikeAbility.Name); if (trackedResource != null) { stringBuilder.Append($" --set perday_max {trackedResource.Max}"); } stringBuilder.Append($" --set spellname {spellLikeAbility.ShortName}"); stringBuilder.Append($" --set spelldesc {spellLikeAbility.Description.Replace('\r', ' ').Replace('\n', ' ')}"); var spell = SpellDatabase.Instance.FirstOrDefault(ss => ss.Name == spellLikeAbility.ShortName); WriteNpcSpellInfo(stringBuilder, character, spell, 2); return(stringBuilder.ToString()); }
private static string WriteNpcSpecialAttack(HeroLabCharacter character, HeroLabSpecial special) { var stringBuilder = new StringBuilder($"!HeroLabImporter --name {character.Name} --mode add --addtype npcatk-special"); stringBuilder.Append($" --set atkname {special.ShortName}"); stringBuilder.Append($" --set atkdisplay {special.ShortName}"); stringBuilder.Append($" --set options-flag 0"); var trackedResource = character.TrackedResources?.Items?.FirstOrDefault(tr => tr.Name == special.Name); if (trackedResource != null) { stringBuilder.Append($" --set perday 0"); stringBuilder.Append($" --set perday!max {trackedResource.Max}"); } stringBuilder.Append($" --set atkdesc {OneLineString(special.Description)}"); //First, we need to find the item that contains information on how this thing works. var checkers = Regex.Matches(special.Name, @"(?<=\().+?(?=\))"); bool hasAttack = false; bool hasRange = false; bool hasArea = false; bool hasEffect = false; bool hasSavingThrow = false; bool hasSavingThrowDc = false; bool hasDamage = false; bool hasDamage2 = false; string saveDc = null; string saveText = null; foreach (Match check in checkers) { if (check.Value.Contains("DC") || check.Value.Contains("ft.") || check.Value.Contains("rounds") || check.Value.Contains("rnd")) { var checkItems = check.Value.Split(new[] { ',', ';' }); foreach (var item in checkItems) { if (item.ToLower().Contains("cone") && !hasRange) { stringBuilder.Append(" --set rangeflag " + PreventRollingString("{{range=@{atkrange}}}")); stringBuilder.Append($" --set atkrange {item}"); hasRange = true; } else if (item.ToLower().Contains("dc") && !hasSavingThrowDc) { var dc = Regex.Match(item, @"\d+"); if (dc.Success) { saveDc = dc.Value; stringBuilder.Append($" --set atkdc {dc.Value}"); hasSavingThrowDc = true; if (hasSavingThrow) { stringBuilder.Append(" --set atksaveflag " + PreventRollingString("{{save=1}}{{savedc=@{atkdc}}}{{saveeffect=@{atksave}}}")); } } if (!hasSavingThrow) { var desc = special.Description.ToLower(); var modDesc = ""; if (desc.Contains("half") || desc.Contains("halves")) { modDesc = "half"; } else if (desc.Contains("partial")) { modDesc = "partial"; } else if (desc.Contains("negate")) { modDesc = "negates"; } var checkDesc = ""; if (desc.Contains("fortitude")) { checkDesc = "Fortitude"; } if (desc.Contains("reflex")) { checkDesc = "Reflex"; } if (desc.Contains("will")) { checkDesc = "Will"; } if (!string.IsNullOrEmpty(modDesc) && !string.IsNullOrEmpty(checkDesc)) { stringBuilder.Append($" --set atksave {checkDesc} {modDesc}"); saveText = $"{checkDesc} {modDesc}"; hasSavingThrow = true; if (hasSavingThrowDc) { stringBuilder.Append(" --set atksaveflag " + PreventRollingString("{{save=1}}{{savedc=@{atkdc}}}{{saveeffect=@{atksave}}}")); } } } } else if (item.ToLower().Contains("feet") && !hasRange) { stringBuilder.Append(" --set rangeflag " + PreventRollingString("{{range=@{atkrange}}}")); stringBuilder.Append($" --set atkrange {item}"); hasRange = true; } else if ((item.ToLower().Contains("fire") || item.ToLower().Contains("sonic") || item.ToLower().Contains("acid") || item.ToLower().Contains("cold") || item.ToLower().Contains("sonic")) && !hasDamage) { var possibleDamage = Regex.Match(item.ToLower(), @"\d+d\d+[+-]?\d*"); if (possibleDamage.Success) { stringBuilder.Append(" --set dmgflag1 1"); stringBuilder.Append(" --set dmgflag " + PreventRollingString("{{damage=1}}{{dmg1flag=1}}{{dmg1=[[@{dmgbase}[MOD]+@{rollmod_damage}[QUERY]]]}}{{dmg1type=@{dmgtype}}}{{dmg1crit=[[(@{dmgbase}[MOD]+@{rollmod_damage}[QUERY])*@{dmgcritmulti}]]}}")); //stringBuilder.Append(" --set dmgflag "+ PreventRollingString("{{damage=1}}{{dmg1flag=1}}{{dmg1=[[" + possibleDamage.Value + "]]}}{{dmg1type=" + item.ToLower().Replace(possibleDamage.Value, "").Trim() + "}}{{dmg1crit=[[(" + possibleDamage.Value + ")*2]]}}")); stringBuilder.Append($" --set dmgbase {possibleDamage.Value}"); stringBuilder.Append( $" --set dmgtype {item.ToLower().Replace(possibleDamage.Value, "").Trim()}"); hasDamage = true; } } else if ((item.ToLower().Contains("fire") || item.ToLower().Contains("sonic") || item.ToLower().Contains("acid") || item.ToLower().Contains("cold") || item.ToLower().Contains("sonic")) && !hasDamage2) { var possibleDamage = Regex.Match(item.ToLower(), @"\d+d\d+[+-]?\d*"); if (possibleDamage.Success) { stringBuilder.Append(" --set dmgflag2 " + PreventRollingString("{{damage=1}}{{dmg2flag=1}}{{dmg2=[[@{dmg2base}[MOD]+@{rollmod_damage}[QUERY]]]}}{{dmg2type=@{dmg2type}}}{{dmg1crit=[[(@{dmg2base}[MOD]+@{rollmod_damage}[QUERY])*@{dmg2critmulti}]]}}")); //stringBuilder.Append(" --set dmgflag2 " + PreventRollingString("{{damage=1}}{{dmg2flag=1}}{{dmg2=[[" + possibleDamage.Value + "]]}}{{dmg2type=" + item.ToLower().Replace(possibleDamage.Value, "").Trim() + "}}{{dmg2crit=[[(" + possibleDamage.Value + ")]]}}")); stringBuilder.Append($" --set dmgbase2 {possibleDamage.Value}"); stringBuilder.Append( $" --set dmgtype2 {item.ToLower().Replace(possibleDamage.Value, "").Trim()}"); hasDamage2 = true; } } else if ((item.ToLower().Contains("half") || item.ToLower().Contains("partial") || item.ToLower().Contains("negates")) && !hasSavingThrow) { var fixedItem = Regex.Replace(item.ToLower(), @"dc \d*", "").Trim(); hasSavingThrow = true; stringBuilder.Append($" --set atksave {fixedItem}"); saveText = fixedItem; if (hasSavingThrowDc) { stringBuilder.Append(" --set atksaveflag " + PreventRollingString("{{save=1}}{{savedc=@{atkdc}}}{{saveeffect=@{atksave}}}")); } } else if (item.ToLower().Contains("every") && !hasEffect) { var finalItem = item.ToLower(); var replacements = Regex.Matches(item.ToLower(), @"\d+d\d+[+-]?\d*"); foreach (Match match in replacements) { finalItem = finalItem.Replace(match.Value, $"[[{match.Value}]]"); } stringBuilder.Append($" --set atkeffect {finalItem}"); stringBuilder.Append(" --set effectflag " + PreventRollingString("{{effect=@{atkeffect}}}")); hasEffect = true; } } } } stringBuilder.Append(" --set options-flag 0"); return(stringBuilder.ToString()); }