/// <summary> /// Generates the HTML representation. /// </summary> public string ToHtml(Attack owner, Enemy attackOwner, int baseIndent) { var htmlBuilder = new StringBuilder(); Type = EffectHandler.HandleEffect(Type, this, owner, attackOwner); // Replace end dot with a double dot if the effect has sub effects (visually looks better). if (Type[Type.Length - 1] == '.' && SubEffects.Count > 0) Type = Type.Substring(0, Type.Length - 1) + ':'; htmlBuilder.Append(Gw2Helper.AddTab(baseIndent)).Append("<p>").Append(Helper.ToUpper(Type)).Append("</p>").Append(Constants.LineEnding); htmlBuilder.Append(Gw2Helper.AddTab(baseIndent)).Append("<ul>").Append(Constants.LineEnding); foreach (var subEffect in SubEffects) { htmlBuilder.Append(Gw2Helper.AddTab(baseIndent + 1)).Append("<li>"); var str = EffectHandler.HandleEffect(subEffect, this, owner, attackOwner); htmlBuilder.Append(Helper.ToUpper(str.Replace("\\:", ":"))); htmlBuilder.Append("</li>").Append(Constants.LineEnding); } htmlBuilder.Append(Gw2Helper.AddTab(baseIndent)).Append("</ul>").Append(Constants.LineEnding); return htmlBuilder.ToString(); }
/*********************************************************************************************** * GenerateEnemies / 2014-08-01 / Wethospu * * * * Generates enemies for one dungeon. * * * * Returns list of generated enemies. * * enemyAttributes: Datamined enemy attributes and other info. * * * ***********************************************************************************************/ public static List<Enemy> GenerateEnemies(Dictionary<string, EnemyAttributes> enemyAttributes) { var enemyData = new List<Enemy>(); if (!Directory.Exists(Constants.DataEnemyRaw)) { Helper.ShowWarning("Directory " + Constants.DataEnemyRaw + " doesn't exist."); return enemyData; } var enemyFiles = Directory.GetFiles(Constants.DataEnemyRaw); foreach (var file in enemyFiles) { if (Path.GetExtension(file) != ".txt") continue; string[] lines; if (File.Exists(file)) lines = File.ReadAllLines(file, Constants.Encoding); else { Helper.ShowWarningMessage("File " + file + " doesn't exist!"); return null; } Helper.CurrentFile = file; for (var row = 0; row < lines.Length; row++) { Helper.InitializeWarningSystem(row + 1, lines[row]); HandleLine(lines[row], enemyData, enemyAttributes); } } // Add the last enemy. if (_currentEffect != null && _currentAttack != null) _currentAttack.Effects.Add(_currentEffect); if (_currentAttack != null && _currentEnemy != null) _currentEnemy.Attacks.Add(_currentAttack); if (_currentEnemy != null) enemyData.Add(_currentEnemy); // Reset internal state. Helper.InitializeWarningSystem(-1, ""); _currentEnemy = null; _currentAttack = null; _currentEffect = null; // Sort for consistency (also allows see enemies without proper ids). / 2015-10-05 / Wethospu enemyData.Sort(); // Set up internal indexes. / 2015-10-05 / Wethospu for (var i = 0; i < enemyData.Count; i++) enemyData[i].Index = i; return enemyData; }
/*********************************************************************************************** * EnemyLoop / 2014-08-01 / Wethospu * * * * Main process loop for enemies. * * * * tag: Tag of the line. * * data: Data of the line. * * enemies: Output. List of processed enemies. * * * ***********************************************************************************************/ private static int EnemyLoop(string tag, string data, List<Enemy> enemies, Dictionary<string, EnemyAttributes> enemyAttributes) { if (!tag.Equals("name") && !tag.Equals("id") && _currentEnemy != null & _currentEnemy.IsNameCopied) Helper.ShowWarning("ID or name not explicitly set for a copied enemy."); if (tag.Equals("copy")) { if (_currentEnemy != null) enemies.Add(_currentEnemy); var found = FindEnemy(data, enemies); if (found != null) { _currentEnemy = Helper.CloneJson(found); _currentEnemy.IsNameCopied = true; _currentEnemy.AreAnimationsCopied = true; } else Helper.ShowWarning("Copying failed. Enemy not found!"); } else if (tag.Equals("name")) { if (data.Length > 0) { if (_currentEnemy != null && !_currentEnemy.IsNameCopied) { enemies.Add(_currentEnemy); if (_currentEnemy.Paths.Count == 0) Helper.ShowWarning("Path not set for enemy " + _currentEnemy.Name); } if (data.Contains('_')) Helper.ShowWarning("Enemy name " + data + " containts '_'. Replace them with ' '!"); // For copies only set the name. / 2015-10-05 / Wethospu if (_currentEnemy != null && _currentEnemy.IsNameCopied) _currentEnemy.Name = data; else _currentEnemy = new Enemy(data); _currentEnemy.IsNameCopied = false; _currentAttack = null; _currentEffect = null; } else Helper.ShowWarning("Missing info. Use \"name='name'\"!"); } else if (tag.Equals("id")) { if (_currentEnemy == null) Helper.ShowWarning("Enemy not initialized with name."); else if (data.Length > 0) { _currentEnemy.IsNameCopied = false; var ids = data.Split('|'); // Enemies can have multiple genders if there are model variations. / 2015 - 09 - 28 / Wethospu // Each model has a different id so store old ones to get all added. / 2015-09-28 / Wethospu var oldGenders = ""; foreach (var id in ids) { _currentEnemy.InternalIds.Add(Helper.ParseI(id)); if (enemyAttributes.ContainsKey(id)) { _currentEnemy.Attributes = enemyAttributes[id]; if (oldGenders.Length > 0) { var genders = oldGenders.Split('|'); // If the sex is already there it can be ignored. / 2015-09-28 / Wethospu if (genders.Contains(_currentEnemy.Attributes.Gender)) _currentEnemy.Attributes.Gender = oldGenders; else _currentEnemy.Attributes.Gender = oldGenders + "|" + _currentEnemy.Attributes.Gender; } _currentEnemy.Rank = _currentEnemy.Attributes.GetRank(); oldGenders = _currentEnemy.Attributes.Gender; } else Helper.ShowWarning("Id " + data + " not found in enemy attributes."); } } else Helper.ShowWarning("Missing info. Use \"id='id'\"!"); } else if (tag.Equals("path")) { if (data.Length == 0) Helper.ShowWarning("Missing info. Use \"path='path1'|'path2'|'pathN'\"!"); if (data.Contains(" ")) { Helper.ShowWarning("' ' found. Use syntax \"path='path1'|'path2'|'pathN'\""); data = data.Replace(' ', '|'); } if (_currentEnemy == null) Helper.ShowWarning("Enemy not initialized with name."); else _currentEnemy.Paths = new List<string>(data.ToLower().Split('|')); } else if (tag.Equals("rank")) { if (_currentEnemy == null) Helper.ShowWarning("Enemy not initialized with name."); else if (data.Length > 0) { _currentEnemy.Rank = data.ToLower(); if (!LinkGenerator.EnemyCategories.Contains(_currentEnemy.Rank)) Helper.ShowWarning("Rank " + _currentEnemy.Rank + " not recognized. Check syntax for correct categories."); } else Helper.ShowWarning("Missing info. Use \"rank='rank'\"!"); } else if (tag.Equals("alt")) { if (_currentEnemy == null) Helper.ShowWarning("Enemy not initialized with name."); else if (data.Length > 0) { if (data.Contains('_')) Helper.ShowWarning("Alt names " + data + " containts '_'. Replace them with ' '!"); var altNames = data.Split('|'); _currentEnemy.AltNames.Clear(); foreach (var altName in altNames) _currentEnemy.AddAlt(altName); } else Helper.ShowWarning("Missing info. Use \"alt='alt1'|'alt2'|'altN'\"!"); } else if (tag.Equals("image")) { if (_currentEnemy == null) Helper.ShowWarning("Enemy not initialized with name."); else if (data.Length > 0) { if (_currentEnemy.AreAnimationsCopied) { _currentEnemy.Medias.Clear(); _currentEnemy.AreAnimationsCopied = false; } _currentEnemy.Medias.Add(new Media(data)); } else Helper.ShowWarning("Missing info. Use \"image='imagelink'\"!"); } else if (tag.Equals("level")) { if (_currentEnemy == null) Helper.ShowWarning("Enemy not initialized with name."); else if (data.Length > 0) { _currentEnemy.Level = Helper.ParseI(data); } else Helper.ShowWarning("Missing info. Use \"level='amount'\""); } else if (tag.Equals("scaling")) { if (_currentEnemy == null) Helper.ShowWarning("Enemy not initialized with name."); else if (data.Length > 0) { var scalingSplit = data.Split('|'); _currentEnemy.ScalingType = scalingSplit[0]; if (scalingSplit.Length > 1) { int result; if (int.TryParse(scalingSplit[1], out result)) _currentEnemy.ScalingFractal = result; else Helper.ShowWarning("Fractal scale " + scalingSplit[1] + " is not an integer!"); if (scalingSplit.Length > 2) { if (int.TryParse(scalingSplit[2], out result)) _currentEnemy.ScalingLevel = result; else Helper.ShowWarning("Enemy level " + scalingSplit[2] + " is not an integer!"); } } } else Helper.ShowWarning("Missing info. Use \"scaling='type'|'fractal scale'|'enemy level'\"!"); } else if (tag.Equals("attack")) { if (_currentEnemy == null) Helper.ShowWarning("Enemy not initialized with name."); else if (_currentEnemy.Rank.Length == 0) Helper.ShowWarningMessage("Rank not set for enemy " + _currentEnemy.Name + ". Please fix!"); return 1; } else if (tag.Equals("tactic")) { // Set validity to over max so custom tactics never get overridden. / 2015-08-09 / Wethospu _currentEnemy.TacticValidity = 2.0; if (data.Length > 0) _currentEnemy.Tactics.AddTactics(data); else Helper.ShowWarning("Missing info. Use \"tactic='tactic1'|'tactic2'|'tacticN'\"."); } else if (tag.Equals("health")) { if (data.Length > 0) { _currentEnemy.Attributes.Multipliers.HealthMultiplier = Helper.ParseD(data); // If vitality is not set, initialize it with something sensible so the page can calculate something. / 2015-09-10 / Wethospu if (_currentEnemy.Attributes.Multipliers.Vitality < 0.1) _currentEnemy.Attributes.Multipliers.Vitality = 1; if (Helper.ParseD(data) > 1000) Helper.ShowWarning("Health values should be multipliers. Calculate the multiplier."); } else Helper.ShowWarning("Missing info. Use \"health='amount'."); } else if (tag.Equals("toughness")) { if (data.Length > 0) { _currentEnemy.Attributes.Multipliers.Toughness = Helper.ParseD(data); if (Helper.ParseD(data) > 100) Helper.ShowWarning("Toughness values should be multipliers. Calculate the multiplier."); } else Helper.ShowWarning("Missing info. Use \"toughness='amount'."); } else if (tag.Equals("armor")) { Helper.ShowWarning("Armor values shouldn't be used. Calculate the toughness multiplier."); } else if (tag.Equals("condition")) { if (data.Length > 0) { _currentEnemy.Attributes.Multipliers.ConditionDamage = Helper.ParseD(data); if (Helper.ParseD(data) > 100) Helper.ShowWarning("Condition damage values should be multipliers. Calculate the multiplier."); } else Helper.ShowWarning("Missing info. Use \"condition='amount'."); } else if (tag.Equals("race")) { if (data.Length > 0) { _currentEnemy.Attributes.Family.Name = data; } else Helper.ShowWarning("Missing info. Use \"race='value'."); } else if (tag.Equals("tag")) { if (data.Length > 0) { var split = data.Split('|'); foreach (var str in split) _currentEnemy.Tags.Add(str.ToLower()); } else Helper.ShowWarning("Missing info. Use \"tag='tactic1'|'tactic2'|'tacticN'\"!"); } // Normal content. else if (tag.Equals("")) { // Preprocess the line to avoid doing same stuff 25+ times. _currentEnemy.Tactics.AddLine(LinkGenerator.CreatePageLinks(LinkGenerator.CheckLinkSyntax(data))); } else if (tag.Equals("type") || tag.Equals("effect") || tag.Equals("cooldown") || tag.Equals("additional") || tag.Equals("animation")) Helper.ShowWarning("Missing attack name (\"attack='name'\")!"); else Helper.ShowWarning("Unrecognized tag: " + tag); return 0; }
/*********************************************************************************************** * EffectLoop / 2014-08-01 / Wethospu * * * * Sub process loop for attack effects. * * * * tag: Tag of the line. * * data: Data of the line. * * * ***********************************************************************************************/ private static int EffectLoop(string tag, string data) { // Add old effect and start a new one. if (tag.Equals("effect")) { if (data.Length == 0) Helper.ShowWarning("Missing info. Use \"effect='type'\"!"); if (_currentEffect != null) _currentAttack.Effects.Add(_currentEffect); var type = data.ToLower(); foreach (var enemyTag in Constants.AttackTypeTags) { if (type.Contains(enemyTag)) _currentEnemy.Tags.Add(enemyTag); } _currentEffect = new Effect(LinkGenerator.CreatePageLinks(LinkGenerator.CheckLinkSyntax(data))); } // Tag from attack loop. Save effect and exit this loop. else if (tag.Equals("attack")) { if (_currentEffect != null) _currentAttack.Effects.Add(_currentEffect); _currentEffect = null; return -1; } // Tag from main loop. Save both effect and attack and then exit this loop. else if (tag.Equals("name") || tag.Equals("potion") || tag.Equals("copy")) { if (_currentEffect != null) { _currentAttack.Effects.Add(_currentEffect); _currentEnemy.Attacks.Add(_currentAttack); } _currentEffect = null; _currentAttack = null; return -2; } else if (tag.Equals("count")) { if (data.Length > 0) { if (data.Equals("?")) _currentEffect.HitCount = -1; else _currentEffect.HitCount = Helper.ParseI(data); if (_currentEffect.HitCount == 0) Helper.ShowWarning("Hit count can't be zero."); } else Helper.ShowWarning("Missing info. Use \"count='number'\""); } else if (tag.Equals("length")) { if (data.Length > 0) _currentEffect.HitLength = Helper.ParseD(data); else Helper.ShowWarning("Missing info. Use \"length='number'\""); } else if (tag.Equals("frequency")) { if (data.Length > 0) _currentEffect.HitFrequency = Helper.ParseD(data); else Helper.ShowWarning("Missing info. Use \"frequency='number'\""); } // Add subeffects to the effect. else if (tag.Equals("subeffect")) { if (data.Length > 0) { data = LinkGenerator.CheckLinkSyntax(data); _currentEffect.SubEffects.Add(data); } else Helper.ShowWarning("Missing info. Use TODO!"); } // Error handling for wrongly placed tags. else if (tag.Equals("additional") || tag.Equals("cooldown") || tag.Equals("animation")) Helper.ShowWarning("Wrong position for tag " + tag + ". Move above any type-tags."); else if (tag.Equals("")) Helper.ShowWarning("Something wrong with line " + data + "."); else Helper.ShowWarning("Unrecognized tag: " + tag); return 0; }
/*********************************************************************************************** * AttackLoop / 2014-08-01 / Wethospu * * * * Sub process loop for enemy attacks. * * * * tag: Tag of the line. * * data: Data of the line. * * * ***********************************************************************************************/ static int AttackLoop(string tag, string data) { // Add old attack and start a new one. if (tag.Equals("attack")) { if (data.Length == 0) Helper.ShowWarning("Missing info. Use \"attack='name'\"!"); if (_currentAttack != null) _currentEnemy.Attacks.Add(_currentAttack); _currentAttack = new Attack(LinkGenerator.CreatePageLinks(LinkGenerator.CheckLinkSyntax(data))); _currentEffect = null; } // Tags from main loop. Save attack and exit this loop. else if (tag.Equals("name") || tag.Equals("copy") || tag.Equals("potion")) { if (_currentAttack != null) _currentEnemy.Attacks.Add(_currentAttack); _currentAttack = null; _currentEffect = null; return -1; } else if (tag.Equals("id")) { if (data.Length > 0) { _currentAttack.LoadAttributes(Helper.ParseI(data), _currentEnemy.Attributes); } else Helper.ShowWarning("Missing info. Use \"id=number\"."); } // Tags from effect loop. Exit immediately. else if (tag.Equals("effect")) { return 1; } else if (tag.Equals("cooldown")) { if (data.Length > 0) _currentAttack.Cooldown = Helper.ParseD(data); else Helper.ShowWarning("Missing info. Use \"cooldown='number'\"."); } else if (tag.Equals("additional")) { // Treat additional as an effect. / 2015-09-22 / Wethospu if (data.Length == 0) Helper.ShowWarning("Missing info. Use \"additional='text'\"."); if (_currentEffect != null) _currentAttack.Effects.Add(_currentEffect); var lower = data.ToLower(); // Check for interesting tags. / 2015-09-22 / Wethospu if (lower.Contains("can't be blocked") || lower.Contains("can't block")) _currentEnemy.Tags.Add("can't block"); if (lower.Contains("can't be evaded") || lower.Contains("can't evade")) _currentEnemy.Tags.Add("can't evade"); _currentEffect = new Effect(LinkGenerator.CreatePageLinks(LinkGenerator.CheckLinkSyntax(data))); } else if (tag.Equals("animation")) { if (data.Length > 0) { if (data.Contains(':') && !data.Contains('=')) Helper.ShowWarning("Potentially use of wrong syntax. Use \"animation='pre cast'|'time'|'after cast'\" !"); _currentAttack.Animation = data; } else Helper.ShowWarning("Missing info. Use \"animation='pre cast'|'time'|'after cast'\" !"); } else if (tag.Equals("image")) { if (data.Length > 0) { _currentAttack.Medias.Add(new Media(data)); } else Helper.ShowWarning("Missing info. Use \"image='imagelink'\"!"); } else if (tag.Equals("subeffect")) Helper.ShowWarning("Missing attack effect (\"effect='type'\")!"); else if (tag.Equals("")) Helper.ShowWarning("Something wrong with line " + data + "."); else Helper.ShowWarning("Unrecognized tag: " + tag); return 0; }
/// <summary> /// Converts raw effect data to html outpout. /// </summary> /// <param name="effectStr">Effect information-</param> /// <param name="baseEffect">Base effect.</param> /// <param name="baseAttack">Base attack for the base effect.</param> /// <param name="baseEnemy">Base enemy for the base attack.</param> /// <returns>Converted data.</returns> public static string HandleEffect(string effectStr, Effect baseEffect, Attack baseAttack, Enemy baseEnemy) { /* What is wanted: * Damage: <span>(count*stack*amount)</span> over time (<span>amount</span> per hit). * Swiftness: (count*stack*amount) over time (amount per hit). * count*stack stability: for amount over time (stack per hit) * count*stack might: <span>count*stack</span>% more damage for amount over time (<span>stack</span>% more damage per hit) */ // Note: Listing per hit for might/stability may not make sense if there is only stack. // Keep the original string for error logging purposes. var original = string.Copy(effectStr); // Copy values from the base effect to avoid changing it. If this ever gets refactored feel free to use them directly. SubEffectInformation information = new SubEffectInformation(); information.hitCount = baseEffect.HitCount; information.hitLength = baseEffect.HitLength; information.hitFrequency = baseEffect.HitFrequency; information.variableHitCount = false; var split = effectStr.Split('|'); effectStr = split[0]; // Some effects get applied randomly. Don't add total damage/effect in those cases. Refactor this if possible. var effectChance = ""; if (split.Length > 1) effectChance = split[1]; if (effectChance.Length > 0) information.hitCount = 1; if (information.hitCount < 0) { information.variableHitCount = true; information.hitCount = 1; } // First effect type determines the icon. var firstType = ""; var firstStacks = 0; var startIcon = ""; var index = 0; while (true) { TagData text = TagData.FromString(effectStr, ':', ref index, new[] { ' ', '|', '(' }, new[] { ' ', '|', ')' }); if (text == null) break; // Ignore other stuff like enemies. if (text.Tag.Contains("=")) continue; if (text.Tag.Length == 0 || text.Data.Length == 0) { ErrorHandler.ShowWarningMessage("Enemy " + baseEnemy.Name + ": Something wrong with line '" + original + "'. Note: Use '\\:' instead of ':' in the text!"); effectStr = effectStr.Remove(index, 1); continue; } if (!SubEffect.EffectTypes.ContainsKey(text.Tag.ToLower())) { ErrorHandler.ShowWarningMessage("Skipping an effect. Effect " + text.Tag + " not recognized."); continue; } var subEffect = SubEffect.EffectTypes[text.Tag.ToLower()]; var effectType = subEffect.Name; // Effect info format varies based on tag (separated by :). information = ExtractInformation(information, subEffect, text, baseAttack, baseEnemy); var tag = SubEffect.GetTag(effectType); if (tag.Length > 0) baseEnemy.Tags.Add(tag); information = HandleStackingRules(information, subEffect); StringBuilder replace = GenerateReplace(information, subEffect, baseAttack); var toReplace = text.Tag + ":" + text.Data; effectStr = effectStr.Replace(toReplace, replace.ToString()); index = index - toReplace.Length + replace.Length; // Get the first subeffect type to display an icon. if (firstType.Equals("")) { if (information.icon.Equals("-") && effectType == EffectType.Buff) startIcon = "Buff"; else startIcon = "<span class=" + Constants.IconClass + " data-src=\"" + information.icon.ToLower() + "\" title=\"" + Helper.ToUpper(information.name.Replace('_', ' ')) + "\">" + Helper.ToUpper(information.name.Replace('_', ' ')) + "</span>"; firstType = information.name; firstStacks = information.stacks; } } return BuildHTML(firstType, startIcon, firstStacks, effectStr, effectChance).ToString(); }
private static SubEffectInformation ExtractInformation(SubEffectInformation effect, SubEffect subEffect, TagData text, Attack baseAttack, Enemy baseEnemy) { var effectType = subEffect.Name; var effectData = text.Data.Split(':'); effect.name = text.Tag.ToLower(); effect.amount = -1; effect.duration = 0.0; effect.stacks = 1; effect.buff = ""; effect.icon = effect.name; effect.suffix = "damage"; if (effectType == EffectType.Damage || effectType == EffectType.DamageFixed || effectType == EffectType.DamagePercent) { if (effectData[0].Equals("-")) effect.amount = baseAttack.Coefficient; else if (effectData[0].Equals("?")) effect.amount = -1; else effect.amount = Helper.ParseD(effectData[0]); effect.icon = "damage"; effect.stacks = 1; } else if (effectType == EffectType.Healing || effectType == EffectType.HealingPercent) { if (effectData[0].Equals("-")) effect.amount = baseAttack.Coefficient; else if (effectData[0].Equals("?")) effect.amount = -1; else effect.amount = Helper.ParseD(effectData[0]); effect.suffix = "healing"; effect.icon = "healing"; effect.stacks = 1; } if (effectType == EffectType.Boon || effectType == EffectType.Condition || effectType == EffectType.Control) { baseEnemy.Tags.Add(effect.name); } if (effectType == EffectType.Agony || effectType == EffectType.Boon || effectType == EffectType.Condition) { if (effectData[0].Equals("-")) effect.duration = baseAttack.Coefficient; else if (effectData[0].Equals("?")) effect.duration = -1; else effect.duration = Helper.ParseD(effectData[0]); if (effectType == EffectType.Agony || effect.name.Equals("bleeding") || effect.name.Equals("torment") || effect.name.Equals("burning") || effect.name.Equals("poison") || effect.name.Equals("confusion") || effect.name.Equals("regeneration") || effect.name.Equals("might")) effect.amount = effect.duration; if (effectData.Length > 1) effect.stacks = Helper.ParseI(effectData[1]); if (subEffect.StacksDuration || effectType == EffectType.Boon) effect.suffix = "seconds"; if (effect.name.Equals("regeneration")) effect.suffix = "healing"; if (effect.name.Equals("retaliation")) effect.suffix = "damage per hit"; if (effect.name.Equals("might")) effect.suffix = "more damage"; if (effect.name.Equals("retaliation") || effect.name.Equals("might")) effect.amount = 1; } if (effectType == EffectType.Control) { if (effectData[0].Equals("?")) effect.duration = 0; else effect.duration = Helper.ParseD(effectData[0]); if (effectData.Length > 1) effect.stacks = Helper.ParseI(effectData[1]); } if (effectType == EffectType.Buff) { effect.buff = effectData[0]; effect.icon = effect.buff; if (effectData.Length > 1 && effectData[1].Length > 0) effect.duration = Helper.ParseD(effectData[1]); if (effectData.Length > 2 && effectData[2].Length > 0) effect.stacks = Helper.ParseI(effectData[2]); if (effectData.Length > 3 && effectData[3].Length > 0) effect.icon = effectData[3]; if (effectData.Length > 4) subEffect.StacksDuration = Helper.ParseI(effectData[4]) > 0 ? true : false; } return effect; }
private static StringBuilder GenerateReplace(SubEffectInformation effect, SubEffect subEffect, Attack baseAttack) { // Syntax: <span class="TAGValue">VALUE</span> var replace = new StringBuilder(); var HTMLClass = SubEffect.GetHTMLClass(subEffect.Name); //// Put both total and damage per hit. if (effect.amount > -1) { // All amounts need clientside formatting. // Add information as data values so it can be recalculated in the browser when enemy level changes. replace.Append("<span class=\"").Append(HTMLClass).Append("\" data-effect=\"").Append(effect.name); if (effect.name.Equals("confusion")) replace.Append("1"); replace.Append("\" data-amount=\"").Append(effect.totalAmount).Append("\" data-weapon=\"").Append(baseAttack.Weapon).Append("\"></span>"); replace.Append(" ").Append(effect.suffix); } if (effect.totalDuration > 0) { if (effect.amount > -1) replace.Append(" over "); replace.Append(effect.totalDuration).Append(" second"); if (effect.totalDuration != 1.0) replace.Append("s"); } replace.Append(HitLengthStr(effect.totalLength)); if (effect.hitCount > 1 && (effect.amount > -1 || effect.duration > 0)) { // Same as above but for a single hit. replace.Append("<span class=\"secondary-info\"> ("); if (effect.amount > -1) { replace.Append("<span class=\"").Append(HTMLClass).Append("\" data-effect=\"").Append(effect.name); if (effect.name.Equals("confusion")) replace.Append("1"); replace.Append("\" data-amount=\"").Append(effect.amount).Append("\"></span>"); replace.Append(" ").Append(effect.suffix); } if (effect.duration > 0) { if (effect.amount > -1) replace.Append(" over "); replace.Append(effect.duration).Append(" second"); if (effect.totalDuration != 1.0) replace.Append("s"); } replace.Append(" per hit)</span>"); } if (effect.name.Equals("confusion")) { effect.suffix = "damage per skill usage"; replace.Append(". "); if (effect.amount > -1) { replace.Append("<span class=\"").Append(HTMLClass).Append("\" data-effect=\"").Append(effect.name).Append("2"); replace.Append("\" data-amount=\"").Append(effect.totalAmount).Append("\"></span>"); replace.Append(" ").Append(effect.suffix); } if (effect.duration > 0) { if (effect.amount > -1) replace.Append(" over "); replace.Append(effect.totalLength).Append(" second"); if (effect.totalLength != 1.0) replace.Append("s"); } replace.Append(HitLengthStr(effect.hitLength)); if (effect.hitCount > 1) { replace.Append("<span class=\"secondary-info\"> ("); if (effect.amount > -1) { replace.Append("<span class=\"").Append(HTMLClass).Append("\" data-effect=\"").Append(effect.name).Append("2"); if (effect.name.Equals("confusion")) replace.Append("1"); replace.Append("\" data-amount=\"").Append(effect.amount).Append("\"></span>"); replace.Append(" ").Append(effect.suffix); } if (effect.duration > 0) { if (effect.amount > -1) replace.Append(" over "); replace.Append(effect.duration).Append(" second"); if (effect.duration != 1.0) replace.Append("s"); } replace.Append(" per hit)</span>"); } } // Some effects can have variable or unknown hit count. Just add " per hit" in those cases. if (effect.variableHitCount) replace.Append(" per hit"); if (effect.hitFrequency > 0.01) { replace.Append(" every ").Append(effect.hitFrequency).Append(" second"); if (effect.hitFrequency != 1.0) replace.Append("s"); } if (subEffect.Name == EffectType.Buff) { // Add the buff name because people probably don't recognize all icons. replace.Append(" (").Append(effect.buff.Replace('_', ' ')).Append(")"); } return replace; }
private static void HandleCooldown(string data, Attack currentAttack) { if (data.Length == 0) ErrorHandler.ShowWarning("Missing info. Use \"cooldown='number'\"."); currentAttack.Cooldown = Helper.ParseD(data); }
private static void HandleAttackMedia(string data, Attack currentAttack) { if (data.Length == 0) ErrorHandler.ShowWarning("Missing info. Use \"image='imagelink'\"!"); if (!data.StartsWith("http://") && !data.StartsWith("https://")) data = Constants.WebsiteMediaLocation + "Enemies" + "/" + data; currentAttack.Medias.Add(new Media(data)); }
private static void HandleAttackId(string data, Attack currentAttack, Enemy currentEnemy) { if (data.Length == 0) ErrorHandler.ShowWarning("Missing info. Use \"id=number\"."); currentAttack.LoadAttributes(Helper.ParseI(data), currentEnemy.Attributes); }
private static void HandleAnimation(string data, Attack currentAttack) { if (data.Length == 0) ErrorHandler.ShowWarning("Missing info. Use \"animation='pre cast'|'time'|'after cast'\" !"); if (data.Contains(':') && !data.Contains('=')) ErrorHandler.ShowWarning("Potentially use of wrong syntax. Use \"animation='pre cast'|'time'|'after cast'\" !"); currentAttack.Animation = data; }
private static void HandleAdditional(string data, Attack currentAttack, Enemy currentEnemy) { // Treat additional information as an effect for a simpler UI. if (data.Length == 0) ErrorHandler.ShowWarning("Missing info. Use \"additional='text'\"."); var lower = data.ToLower(); if (lower.Contains("can't be blocked") || lower.Contains("can't block")) { currentEnemy.Tags.Add("can't block"); currentAttack.CantBeBlocked = true; } if (lower.Contains("can't be evaded") || lower.Contains("can't evade")) currentEnemy.Tags.Add("can't evade"); currentAttack.Effects.Add(new Effect(LinkGenerator.CheckLinkSyntax(data))); }