#include "${LavishScript.HomeDirectory}/Scripts/mr/common/StringHelpers.iss" variable jsonvalue stealthRequiredEffects = "[ \"I need to be stealthed!\", \"You must be in stealth to use this!\", \"You must be sneaking to use this ability.\"]" variable jsonvalue flankingRequiredEffects = "[ \"Must be flanking or behind\" ]" variable jsonvalue noEpicEffects = "[ \"Does not affect Epic targets\"]" variable jsonvalue interruptEffects = "[ \"Interrupts target\" ]" variable jsonvalue stunEffects = "[ \"Stuns target\" ]" function:bool matchesItemInArray(jsonvalueref arr, string val) { if !${arr.Type.Equal[array]} { echo "effects is not an array ${arr.Type}" return FALSE } variable jsoniterator iter arr:GetIterator[iter] if ${iter:First(exists)} { do { if ${val.Equal["${iter.Value}"]} { return TRUE } } while ${iter:Next(exists)} } return FALSE } function:bool hasMatchingEffect(jsonvalueref effects, jsonvalueref specialEffects) { if !${effects.Type.Equal[array]} { echo "effects is not an array ${effects.Type}" return FALSE } variable jsoniterator effectIterator effects:GetIterator[effectIterator] if ${effectIterator:First(exists)} { do { call matchesItemInArray specialEffects "${effectIterator.Value.Get["description"]}" if ${Return} { return TRUE } } while ${effectIterator:Next(exists)} } return FALSE } function:jsonvalueref extractDamageFromEffect(jsonvalueref effectJo) { variable string description description:Set["${effectJo.Get["description"]}"] if ${description.Left[8].NotEqual["Inflicts"]} { return "{}" } variable int64 minDamage variable int64 maxDamage variable string damageType minDamage:Set["${description.Token[2, " "].Replace[",", ""]}"] if ${description.Token[3, " "].Equal["-"]} { maxDamage:Set["${description.Token[4, " "].Replace[",", ""]}"] damageType:Set["${description.Token[5, " "]}"] } else { maxDamage:Set["${description.Token[2, " "].Replace[",", ""]}"] damageType:Set["${description.Token[3, " "]}"] } variable jsonvalue damage damage:SetValue["$$>{ "type": "${damageType}", "min": ${minDamage}, "max": ${maxDamage} }<$$"] if !${damageType(exists)} { echo "huh?: ${description}" } return ${damage.AsJSON~} } function main() { variable index:ability MyAbilities variable iterator MyAbilitiesIterator variable jsonvalue abilityList = "{}" variable jsonvalue currentAbility = {} variable jsonvalue effects = [] variable jsonvalue abilityEffect = {} variable string abilityLineName variable int idx = 1 variable int Counter = 1 variable int Timer = 0 Me:QueryAbilities[MyAbilities] MyAbilities:GetIterator[MyAbilitiesIterator] if ${MyAbilitiesIterator:First(exists)} { do { if (!${MyAbilitiesIterator.Value.IsAbilityInfoAvailable}) { do { wait 2 } while (!${MyAbilitiesIterator.Value.IsAbilityInfoAvailable} && ${Timer:Inc} < 1500) } wait 5 echo "Exporting (${Counter} / ${MyAbilities.Used}) - ${MyAbilitiesIterator.Value.ToAbilityInfo.Name} (ID: ${MyAbilitiesIterator.Value.ID})" currentAbility:SetValue["$$>{ "id": ${MyAbilitiesIterator.Value.ID}, "name": "${MyAbilitiesIterator.Value.ToAbilityInfo.Name}", "description": ${MyAbilitiesIterator.Value.ToAbilityInfo.Description.AsJSON~}, "level": ${MyAbilitiesIterator.Value.ToAbilityInfo.Class[${Me.SubClass}].Level}, "tier": "${MyAbilitiesIterator.Value.ToAbilityInfo.Tier}", "healthCost": ${MyAbilitiesIterator.Value.ToAbilityInfo.HealthCost}, "powerCost": ${MyAbilitiesIterator.Value.ToAbilityInfo.PowerCost}, "dissonanceCost": ${MyAbilitiesIterator.Value.ToAbilityInfo.DissonanceCost}, "savageryCost": ${MyAbilitiesIterator.Value.ToAbilityInfo.SavageryCost}, "concentrationCost": ${MyAbilitiesIterator.Value.ToAbilityInfo.ConcentrationCost}, "mainIconID": ${MyAbilitiesIterator.Value.ToAbilityInfo.MainIconID}, "hoIconID": ${MyAbilitiesIterator.Value.ToAbilityInfo.HOIconID}, "castingTime": ${MyAbilitiesIterator.Value.ToAbilityInfo.CastingTime}, "recoveryTime": ${MyAbilitiesIterator.Value.ToAbilityInfo.RecoveryTime}, "recastTime": ${MyAbilitiesIterator.Value.ToAbilityInfo.RecastTime}, "maxDuration": ${MyAbilitiesIterator.Value.ToAbilityInfo.MaxDuration}, "numClasses": ${MyAbilitiesIterator.Value.ToAbilityInfo.NumClasses}, "numEffects": ${MyAbilitiesIterator.Value.ToAbilityInfo.NumEffects}, "backDropIconID": ${MyAbilitiesIterator.Value.ToAbilityInfo.BackDropIconID}, "healthCostPerTick": ${MyAbilitiesIterator.Value.ToAbilityInfo.HealthCostPerTick}, "powerCostPerTick": ${MyAbilitiesIterator.Value.ToAbilityInfo.PowerCostPerTick}, "dissonanceCostPerTick": ${MyAbilitiesIterator.Value.ToAbilityInfo.DissonanceCostPerTick}, "savageryCostPerTick": ${MyAbilitiesIterator.Value.ToAbilityInfo.SavageryCostPerTick}, "maxAOETargets": ${MyAbilitiesIterator.Value.ToAbilityInfo.MaxAOETargets}, "isBeneficial": "${MyAbilitiesIterator.Value.ToAbilityInfo.IsBeneficial.AsJSON}", "doesNotExpire": "${MyAbilitiesIterator.Value.ToAbilityInfo.DoesNotExpire.AsJSON}", "groupRestricted": "${MyAbilitiesIterator.Value.ToAbilityInfo.GroupRestricted.AsJSON}", "allowRaid": "${MyAbilitiesIterator.Value.ToAbilityInfo.AllowRaid.AsJSON}", "effectRadius": ${MyAbilitiesIterator.Value.ToAbilityInfo.EffectRadius}, "targetType": ${MyAbilitiesIterator.Value.ToAbilityInfo.TargetType}, "spellBookType": ${MyAbilitiesIterator.Value.ToAbilityInfo.SpellBookType}, "minRange": ${MyAbilitiesIterator.Value.ToAbilityInfo.MinRange}, "maxRange": ${MyAbilitiesIterator.Value.ToAbilityInfo.MaxRange} }<$$"] for (idx:Set[1] ; ${idx} < ${MyAbilitiesIterator.Value.ToAbilityInfo.NumEffects} ; idx:Inc ) { abilityEffect:SetValue["$$>{ "percentSuccess": ${MyAbilitiesIterator.Value.ToAbilityInfo.Effect[${idx}].PercentSuccess.AsJSON~}, "indentation": "${MyAbilitiesIterator.Value.ToAbilityInfo.Effect[${idx}].Indentation.AsJSON~}", "description": ${MyAbilitiesIterator.Value.ToAbilityInfo.Effect[${idx}].Description.AsJSON~} }<$$"] effects:Add["${abilityEffect.AsJSON~}"] call matchesItemInArray stealthRequiredEffects ${abilityEffect.Get["description"]} if ${Return} { currentAbility:Set["requiresStealth", ${Return.AsJSON~}] } call matchesItemInArray flankingRequiredEffects ${abilityEffect.Get["description"]} if ${Return} { currentAbility:Set["requiresFlanking", ${Return.AsJSON~}] } call matchesItemInArray noEpicEffects ${abilityEffect.Get["description"]} if ${Return} { currentAbility:Set["noEpic", ${Return.AsJSON~}] } call matchesItemInArray stunEffects ${abilityEffect.Get["description"]} if ${Return} { currentAbility:Set["stuns", ${Return.AsJSON~}] } call matchesItemInArray interruptEffects ${abilityEffect.Get["description"]} if ${Return} { currentAbility:Set["interrupts", ${Return.AsJSON~}] } call extractDamageFromEffect abilityEffect if ${Return.Get["type"](exists)} { variable string damageType variable int64 minDamage ; TODO: Add a loop to handle multiple damage effects. ; TODO: Modify extractDmaageFromEffect to also calculate damage for ; damage over time effects. damageType:Set["${Return.Get["type"]}"] minDamage:Set["${Return.Get["min"]}"] currentAbility:Set["doesDamage", TRUE] if ${currentAbility.Has["damage", "${Return.Get["type"]}"]} { variable int64 currentMinDamageTotal currentMinDamageTotal:Set["${currentAbility.Get["damage", ${damageType}]}"] currentMinDamageTotal:Inc[${minDamage}] currentAbility.Get["damage", ${damageType}]:Set[${currentMinDamageTotal}] } else { if ${currentAbility.Has["damage"]} { currentAbility.Get["damage"]:Set["${damageType}", "${minDamage}"] } else { currentAbility:Set["damage", "$$>{ "${damageType}": ${minDamage}, }<$$"] } } } abilityEffect:Clear } currentAbility:Set["effects", "${effects.AsJSON~}"] effects:Clear abilityLineName:Set["${MRStringHelpers.StripRomanNumerals[${currentAbility.Get["name"]}]}"] if !${abilityList.Has["${abilityLineName}"]} { abilityList:Set["${abilityLineName}", "[${currentAbility.AsJSON~}]"] } else { abilityList.Get["${abilityLineName}"]:Add["${currentAbility.AsJSON~}"] } Counter:Inc Timer:Set[0] } while ${MyAbilitiesIterator:Next(exists)} } abilityList:WriteFile["${LavishScript.HomeDirectory}/Scripts/mr/bot/ability_exports/${Me.Name}_${Me.SubClass}.json", multiline] }