Create Clean Spell List
Gogo1951 opened this issue ยท 9 comments
Here's what I go through to get the clean data.
1 - Export Abilities
import requests
import csv
import io
patch_version = "2.5.2.39832"
#url = 'https://wow.tools/dbc/api/export/?name=%s&build=%s&locale=enUS'
url = "https://wow.tools/dbc/api/export/?name=%s&build=%s"
def connect(dbc, patch):
text = requests.get(url % (dbc, patch), headers={'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:91.0) Gecko/20100101 Firefox/91.0'}).text
reader = csv.DictReader(io.StringIO(text))
return reader
spells = connect("spell", patch_version)
levels = connect("SpellLevels", patch_version)
classes = connect("SpellClassOptions", patch_version)
names = connect("SpellName", patch_version)
print("AbilityID, Rank, LevelAvailable, Name, Class")
levels_table = {}
class_table = {}
names_table = {}
for data in classes:
class_table[data["SpellID"]] = data
for data in names:
names_table[data["ID"]] = data["Name_lang"]
for data in levels:
levels_table[data["SpellID"]] = data
for spell in spells:
id = spell["ID"]
if id in levels_table and id in names_table and id in class_table:
rank = spell["NameSubtext_lang"]
if not rank or len(rank) == 0:
rank = "Rank 1"
print(id, end='')
print(", \"", end='')
print(rank, end='')
print("\", ", end='')
print(levels_table[id]["BaseLevel"], end='')
print(", \"", end='')
print(names_table[id], end='')
print("\", ", end='')
print(class_table[id]["SpellClassSet"])
Output Looks Like:
I reformatted this inside of Excel...
2 - Delete any row where the ability doesn't have a numeric "Rank".
Example:
34426 3 Greater Invisibility Passive 1
3 - Delete any row where the ability "LevelAvailable" isn't greater than 1.
These seem like GM abilities, or other odd abilities.
Example:
31751 3 Arcane Missiles 1 0
You can also delete any ability with Class = 0, or 13 (Consumables).
4 - Delete any ability that only has 1 unique value in the "Rank".
Example:
37988 3 Ancient Fire 1 20
16067 3 Arcane Blast 1 35
18091 3 Arcane Blast 1 35
20883 3 Arcane Blast 1 50
30451 3 Arcane Blast 1 64
35927 3 Arcane Blast 1 64
36032 3 Arcane Blast 1 1
38881 3 Arcane Blast 1 64
Careful: Some abilities upgrade to different names. Example. Curious if there is any sort of grouping in the DB. Doubt it. So... probably fine to just purge them and we can re-add as one-off cases manually later.
759 3 Conjure Mana Agate 1 28
3552 3 Conjure Mana Jade 1 38
10053 3 Conjure Mana Citrine 1 48
10054 3 Conjure Mana Ruby 1 58
36883 3 Conjure Mana Diamond 1 68
27101 3 Conjure Mana Emerald 1 68
Careful: Some abilities are GM-only abilities. From the example above... curious if there is any way to weed out the abilities not available to players? Maybe cross check if an ability is learned from a trainer, or learned from a book? Don't know if there is a way to do that.
36883 3 Conjure Mana Diamond 1 68
5 - Sync "LevelAvailable" by Class + Ability + Rank
Watch out for situations where abilities are available, but impacted by talents that are not available until later levels. When encountered, set the "LevelAvailable" to the lowest level for all in that rank.
Example:
6136 3 Chilled 1 1
7321 3 Chilled 1 30
12484 3 Chilled 1 1
15850 3 Chilled 1 1
16927 3 Chilled 1 63
18101 3 Chilled 1 1
31257 3 Chilled 1 70
Desired Output:
6136 3 Chilled 1 1
7321 3 Chilled 1 1
12484 3 Chilled 1 1
15850 3 Chilled 1 1
16927 3 Chilled 1 1
18101 3 Chilled 1 1
31257 3 Chilled 1 1
6 - Compute "MaxLevelBeforeReplace" for all Abilities; should be easier once the above steps are taken.
Note we want to keep the Level 70 abilities in there, and just add "70" for those.
Example:
31661 3 Dragon's Breath 1 50
35250 3 Dragon's Breath 1 70
37289 3 Dragon's Breath 1 70
33041 3 Dragon's Breath 2 56
33042 3 Dragon's Breath 3 64
33043 3 Dragon's Breath 4 70
Desired Output:
31661 3 Dragon's Breath 1 50 55
35250 3 Dragon's Breath 1 50 55
37289 3 Dragon's Breath 1 50 55
33041 3 Dragon's Breath 2 56 63
33042 3 Dragon's Breath 3 64 69
33043 3 Dragon's Breath 4 70 70
7 - Delete All Heals*
*All... not really. Delete heals from Paladins, Priests, Shamans, and Druids that do not have a CD Timer. So like spam-able heals; but we want to keep a few spells, like Tranquility, because there's no reason to cast a low-rank when it's got a long CD. Likely has to stay manual process.
8 - Complete Buff Min Levels
For things like Blessing of Might, the buff can only be given to players who are 10 levels under the "LevelAvailable" level.
Example:
19740 10 Blessing of Might 1 4
19834 10 Blessing of Might 2 12
19835 10 Blessing of Might 3 22
19836 10 Blessing of Might 4 32
19837 10 Blessing of Might 5 42
19838 10 Blessing of Might 6 52
25291 10 Blessing of Might 7 60
27140 10 Blessing of Might 8 70
Desired Output:
19740 10 Blessing of Might 1 4 11 0
19834 10 Blessing of Might 2 12 21 2
19835 10 Blessing of Might 3 22 31 12
19836 10 Blessing of Might 4 32 41 22
19837 10 Blessing of Might 5 42 51 32
19838 10 Blessing of Might 6 52 59 42
25291 10 Blessing of Might 7 60 69 50
27140 10 Blessing of Might 8 70 70 60
9 - Delete All Abilities on Known Ignore List
10 - Clean Up Data into LUA format for DataTables file.
https://github.com/Gogo1951/GogoWatch/blob/main/DataTables.lua
This is just a mid point, working on the trimming rules. Getting to a place where we deal with all spells of the same name at the same time.
This should address 2, 3, 3.5, and 6 so far.
from collections import defaultdict
import requests
import csv
import io
patch_version = "2.5.2.39832"
#url = 'https://wow.tools/dbc/api/export/?name=%s&build=%s&locale=enUS'
url = "https://wow.tools/dbc/api/export/?name=%s&build=%s"
def connect(dbc, patch):
text = requests.get(url % (dbc, patch), headers={'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:91.0) Gecko/20100101 Firefox/91.0'}).text
reader = csv.DictReader(io.StringIO(text))
return reader
spells = connect("spell", patch_version)
levels = connect("SpellLevels", patch_version)
classes = connect("SpellClassOptions", patch_version)
names = connect("SpellName", patch_version)
print("AbilityID, Rank, LevelAvailable, Name, Class")
levels_table = {}
class_table = {}
names_table = {}
spells_table = {}
for data in classes:
class_table[data["SpellID"]] = data
for data in names:
names_table[data["ID"]] = data["Name_lang"]
for data in levels:
levels_table[data["SpellID"]] = data
for data in spells:
spells_table[data["ID"]] = data
skip_spells = [
'27204', #QA Spell
'30331', #Permanent Sheen of Zanza
'30336', #Permanent Sheen of Spirit
'34176', #QA Heal Coefficient 1
'34177', #QA Damage Coefficient
]
no_ranks = ['Summon', 'Shapeshift', 'Passive', 'Racial', '0', 'Racial Passive', '(OLD)']
spell_name_skip_prefixes = ['Gossip', 'Brewfest', 'Cosmetic', 'Winter', 'TEST' ]
# In order to keep some context around and make spells easier to apply logic to
# this will make a dictionary with the key of the spell name and the value be a
# list of the spells with that name
spell_groups_by_name = defaultdict(list)
for spell_id, name in names_table.items():
# print(f'Adding spell {spell_id} {name}')
spell_groups_by_name[name].append(spell_id)
full_spells = {}
def get_spell_details(id):
if id in levels_table and id in names_table and id in class_table and id not in skip_spells:
spell = spells_table[id]
if names_table[id] == 'Fireball':
print(f'fireball {spell}')
rank = spell["NameSubtext_lang"]
print(f"RANK {rank} {spell['NameSubtext_lang']} {spell}")
if not rank or len(rank) == 0:
adjusted_rank = "Rank 1"
else:
adjusted_rank = rank
# 2 - Delete any row where the ability doesn't have a numeric "Rank".
if adjusted_rank in no_ranks:
# print('Skipping - no rank -', end=':')
# print(names_table[id], end='')
# print("\", ", end='')
# print(class_table[id]["SpellClassSet"])
return None
# 3 - Delete any row where the ability "LevelAvailable" isn't greater than 1.
if int(levels_table[id]["BaseLevel"]) < 1:
# print('Skipping - base level < 1 - ', end=':')
# print(names_table[id], end='')
# print("\", ", end='')
# print(class_table[id]["SpellClassSet"])
return None
try:
#This is more readable than a regex, yes it could be a regex
rank_string = adjusted_rank.split(' ')[1]
if ":" in rank_string:
rank_string = rank_string.split(':')[0]
if rank_string in no_ranks:
# print(f'{adjusted_rank} made it passed the first filter')
return None
# 3 3.5 You can also delete any ability with Class = 0, or 13 (Consumables).
if class_table[id]['SpellClassSet'] in [0,13]:
return None
details = {
'id': int(id),
'rank': float(rank_string),
'base_level': int(levels_table[id]["BaseLevel"]),
'name': names_table[id],
'class': class_table[id]["SpellClassSet"],
}
return details
# print(f'Returning details:{details}')
except:
print(f'Rank was {rank}')
print(f'Adjusted rank {adjusted_rank}')
print(id, end='')
print(", \"", end='')
print(rank, end='')
print("\", ", end='')
print(levels_table[id]["BaseLevel"], end='')
print(", \"", end='')
print(names_table[id], end='')
print("\", ", end='')
print(class_table[id]["SpellClassSet"])
raise
# Use this list to know if a spell family was processed or not
processed_spells = {}
for spell in spells_table.values():
print(f'Spell {spell}')
id = spell['ID']
if id in processed_spells:
print(f'Already processed {id} skipping')
continue
name = names_table[id]
if any(name.startswith(x) for x in spell_name_skip_prefixes):
continue
# print(f'Looking for {name}')
related_spells = spell_groups_by_name[name]
print(f'{name}: related spells are {related_spells}')
spell_results = []
cut_for_rank = True
for related_id in related_spells:
processed_spells[related_id] = True
spell_details = get_spell_details(related_id)
print(f'{related_id} - {spell_details}')
if spell_details is not None:
# print(f'{related_id} added to results {spell_details}')
# print(f'deets: {spell_details}')
spell_results.append(spell_details)
if spell_details['rank'] != 1.0:
cut_for_rank = False
# 4 - Delete any ability that only has 1 unique value in the "Rank".
if cut_for_rank:
print(f'Cutting spell {id} {name}')
continue
for result in spell_results:
# 6 - Compute "MaxLevelBeforeReplace" for all Abilities; should be easier once the above steps are taken
any_set = False
for other_spell in spell_results:
if (result['rank'] + 1) == other_spell['rank'] and (result['base_level'] < other_spell['base_level']):
result['max_level_before_replace'] = other_spell['base_level'] - 1
any_set = True
if not any_set:
result['max_level_before_replace'] = 70
# print(f'Spell {result}')
full_spells[result['id']] = result
for k, v in full_spells.items():
print(k, v)
Making a checklist:
- 2 - Delete any row where the ability doesn't have a numeric "Rank".
Example:
34426 3 Greater Invisibility Passive 1
- 3 - Delete any row where the ability "LevelAvailable" isn't greater than 1.
These seem like GM abilities, or other odd abilities.
Example:
31751 3 Arcane Missiles 1 0
-
You can also delete any ability with Class = 0, or 13 (Consumables).
-
4 - Delete any ability that only has 1 unique value in the "Rank".
Example:
37988 3 Ancient Fire 1 20
16067 3 Arcane Blast 1 35
18091 3 Arcane Blast 1 35
20883 3 Arcane Blast 1 50
30451 3 Arcane Blast 1 64
35927 3 Arcane Blast 1 64
36032 3 Arcane Blast 1 1
38881 3 Arcane Blast 1 64
Careful: Some abilities upgrade to different names. Example. Curious if there is any sort of grouping in the DB. Doubt it. So... probably fine to just purge them and we can re-add as one-off cases manually later.
759 3 Conjure Mana Agate 1 28
3552 3 Conjure Mana Jade 1 38
10053 3 Conjure Mana Citrine 1 48
10054 3 Conjure Mana Ruby 1 58
36883 3 Conjure Mana Diamond 1 68
27101 3 Conjure Mana Emerald 1 68
Careful: Some abilities are GM-only abilities. From the example above... curious if there is any way to weed out the abilities not available to players? Maybe cross check if an ability is learned from a trainer, or learned from a book? Don't know if there is a way to do that.
36883 3 Conjure Mana Diamond 1 68
- 5 - Sync "LevelAvailable" by Class + Ability + Rank
Watch out for situations where abilities are available, but impacted by talents that are not available until later levels. When encountered, set the "LevelAvailable" to the lowest level for all in that rank.
Example:
6136 3 Chilled 1 1
7321 3 Chilled 1 30
12484 3 Chilled 1 1
15850 3 Chilled 1 1
16927 3 Chilled 1 63
18101 3 Chilled 1 1
31257 3 Chilled 1 70
Desired Output:
6136 3 Chilled 1 1
7321 3 Chilled 1 1
12484 3 Chilled 1 1
15850 3 Chilled 1 1
16927 3 Chilled 1 1
18101 3 Chilled 1 1
31257 3 Chilled 1 1
- 6 - Compute "MaxLevelBeforeReplace" for all Abilities; should be easier once the above steps are taken.
Note we want to keep the Level 70 abilities in there, and just add "70" for those.
Example:
31661 3 Dragon's Breath 1 50
35250 3 Dragon's Breath 1 70
37289 3 Dragon's Breath 1 70
33041 3 Dragon's Breath 2 56
33042 3 Dragon's Breath 3 64
33043 3 Dragon's Breath 4 70
Desired Output:
31661 3 Dragon's Breath 1 50 55
35250 3 Dragon's Breath 1 50 55
37289 3 Dragon's Breath 1 50 55
33041 3 Dragon's Breath 2 56 63
33042 3 Dragon's Breath 3 64 69
33043 3 Dragon's Breath 4 70 70
- 7 - Delete All Heals*
*All... not really. Delete heals from Paladins, Priests, Shamans, and Druids that do not have a CD Timer. So like spam-able heals; but we want to keep a few spells, like Tranquility, because there's no reason to cast a low-rank when it's got a long CD. Likely has to stay manual process.
- 8 - Complete Buff Min Levels
For things like Blessing of Might, the buff can only be given to players who are 10 levels under the "LevelAvailable" level.
Example:
19740 10 Blessing of Might 1 4
19834 10 Blessing of Might 2 12
19835 10 Blessing of Might 3 22
19836 10 Blessing of Might 4 32
19837 10 Blessing of Might 5 42
19838 10 Blessing of Might 6 52
25291 10 Blessing of Might 7 60
27140 10 Blessing of Might 8 70
Desired Output:
19740 10 Blessing of Might 1 4 11 0
19834 10 Blessing of Might 2 12 21 2
19835 10 Blessing of Might 3 22 31 12
19836 10 Blessing of Might 4 32 41 22
19837 10 Blessing of Might 5 42 51 32
19838 10 Blessing of Might 6 52 59 42
25291 10 Blessing of Might 7 60 69 50
27140 10 Blessing of Might 8 70 70 60
- 9 - Delete All Abilities on Known Ignore List
- 10 - Clean Up Data into LUA format for DataTables file.
https://github.com/Gogo1951/GogoWatch/blob/main/DataTables.lua
This should have a python dict at the end with everything except 9 and 10
from collections import defaultdict
import requests
import csv
import io
patch_version = "2.5.2.39832"
# url = 'https://wow.tools/dbc/api/export/?name=%s&build=%s&locale=enUS'
url = "https://wow.tools/dbc/api/export/?name=%s&build=%s"
def connect(dbc, patch):
text = requests.get(
url % (dbc, patch),
headers={
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:91.0) Gecko/20100101 Firefox/91.0"
},
).text
reader = csv.DictReader(io.StringIO(text))
return reader
spells = connect("spell", patch_version)
levels = connect("SpellLevels", patch_version)
classes = connect("SpellClassOptions", patch_version)
names = connect("SpellName", patch_version)
cooldowns = connect("SpellCooldowns", patch_version)
spelleffects = connect("SpellEffect", patch_version)
levels_table = {}
class_table = {}
names_table = {}
spells_table = {}
spelleffects_table = {}
cooldowns_table = {}
for data in classes:
class_table[data["SpellID"]] = data
for data in cooldowns:
cooldowns_table[data["SpellID"]] = data
for data in names:
names_table[data["ID"]] = data["Name_lang"]
for data in levels:
levels_table[data["SpellID"]] = data
for data in spells:
spells_table[data["ID"]] = data
for data in spelleffects:
spelleffects_table[data["SpellID"]] = data
skip_spells = [
"27204", # QA Spell
"30331", # Permanent Sheen of Zanza
"30336", # Permanent Sheen of Spirit
"34176", # QA Heal Coefficient 1
"34177", # QA Damage Coefficient
]
no_ranks = ["Summon", "Shapeshift", "Passive", "Racial", "0", "Racial Passive", "(OLD)"]
spell_name_skip_prefixes = ["Gossip", "Brewfest", "Cosmetic", "Winter", "TEST"]
allowed_rank_one_spells = {
116: "Frostbolt",
1949: "Hellfire",
1008: "Amplify magic",
604: "Dampen Magic",
1120: "Drain Soul",
}
allowed_downranked_spells = {2120: "Flamestrike"}
# TODO these are single instances... may have to expand
any_rank_allowed = {
1454: "Life Tap",
18220: "Dark Pact",
755: "Health Funnel",
118: "Polymorph",
587: "Conjured Food",
5504: "Conjured Water",
42955: "Conjured Refreshment",
}
# In order to keep some context around and make spells easier to apply logic to
# this will make a dictionary with the key of the spell name and the value be a
# list of the spells with that name
spell_groups_by_name = defaultdict(list)
for spell_id, name in names_table.items():
# print(f'Adding spell {spell_id} {name}')
spell_groups_by_name[name].append(spell_id)
full_spells = {}
def get_spell_details(id):
if (
id in levels_table
and id in names_table
and id in class_table
and id not in skip_spells
):
spell = spells_table[id]
# if (names_table[id] == 'Tranquility'):
# print(id)
# print(spell)
# print(levels_table[id])
# print(class_table[id])
# raise
rank = spell["NameSubtext_lang"]
# print(f"RANK {rank} {spell['NameSubtext_lang']} {spell}")
if not rank or len(rank) == 0:
adjusted_rank = "Rank 1"
else:
adjusted_rank = rank
# 2 - Delete any row where the ability doesn't have a numeric "Rank".
if adjusted_rank in no_ranks:
# print('Skipping - no rank -', end=':')
# print(names_table[id], end='')
# print("\", ", end='')
# print(class_table[id]["SpellClassSet"])
return None
# 3 - Delete any row where the ability "LevelAvailable" isn't greater than 1.
if int(levels_table[id]["BaseLevel"]) < 1:
# print('Skipping - base level < 1 - ', end=':')
# print(names_table[id], end='')
# print("\", ", end='')
# print(class_table[id]["SpellClassSet"])
return None
try:
# This is more readable than a regex, yes it could be a regex
rank_string = adjusted_rank.split(" ")[1]
if ":" in rank_string:
rank_string = rank_string.split(":")[0]
if rank_string in no_ranks:
# print(f'{adjusted_rank} made it passed the first filter')
return None
# 3 3.5 You can also delete any ability with Class = 0, or 13 (Consumables).
if class_table[id]["SpellClassSet"] in [0, 13]:
return None
cooldown = 0
if id in cooldowns_table and (
cooldowns_table[id]["RecoveryTime"] != "0"
or cooldowns_table[id]["CategoryRecoveryTime"] != "0"
):
if cooldowns_table[id]["RecoveryTime"] != "0":
cooldown = int(cooldowns_table[id]["RecoveryTime"])
else:
cooldown = int(cooldowns_table[id]["CategoryRecoveryTime"])
spelleffect = spelleffects_table[id]
# https://wow.tools/dbc/?dbc=spelleffectnames&build=2.0.0.5666#page=1&search=heal
healing_effects = ["10", "67"]
# https://wow.tools/dbc/?dbc=spellauranames&build=2.0.0.5666#page=1&search=heal
healing_auras = [
"8",
"34",
"62",
"84",
"88",
"115",
"118",
"133",
"135",
"136",
]
is_heal = (
spelleffect["Effect"] in healing_effects
or spelleffect["EffectAura"] in healing_auras
)
name = names_table[id]
# 8 - Complete Buff Min Levels
min_target_level = 1
if (
"Blessing of" in name
or "Power Word" in name
or "Prayer of Spirit" in name
or "Fortitude" in name
):
if levels_table[id]["BaseLevel"] != "0":
min_target_level = int(levels_table[id]["BaseLevel"]) - 10
print(spell)
print(levels_table[id])
details = {
"id": int(id),
"rank": float(rank_string),
"base_level": int(levels_table[id]["BaseLevel"]),
"name": names_table[id],
"class": class_table[id]["SpellClassSet"],
"heal": is_heal,
"cooldown": cooldown,
"min_target_level": min_target_level,
}
return details
# print(f'Returning details:{details}')
except:
print(f"Rank was {rank}")
print(f"Adjusted rank {adjusted_rank}")
print(id, end="")
print(', "', end="")
print(rank, end="")
print('", ', end="")
print(levels_table[id]["BaseLevel"], end="")
print(', "', end="")
print(names_table[id], end="")
print('", ', end="")
print(class_table[id]["SpellClassSet"])
raise
# Use this list to know if a spell family was processed or not
processed_spells = {}
for spell in spells_table.values():
# print(f'Spell {spell}')
id = spell["ID"]
if id == 740:
print(spell)
raise
if id in processed_spells:
# print(f'Already processed {id} skipping')
continue
name = names_table[id]
if any(name.startswith(x) for x in spell_name_skip_prefixes):
continue
# print(f'Looking for {name}')
related_spells = spell_groups_by_name[name]
# print(f'{name}: related spells are {related_spells}')
spell_results = []
cut_for_rank = True
for related_id in related_spells:
processed_spells[related_id] = True
spell_details = get_spell_details(related_id)
# print(f'{related_id} - {spell_details}')
if spell_details is not None:
# print(f'{related_id} added to results {spell_details}')
# print(f'deets: {spell_details}')
spell_results.append(spell_details)
if spell_details["rank"] != 1.0:
cut_for_rank = False
# 4 - Delete any ability that only has 1 unique value in the "Rank".
if cut_for_rank:
# print(f'Cutting spell {id} {name}')
continue
for result in spell_results:
# 6 - Compute "MaxLevelBeforeReplace" for all Abilities; should be easier once the above steps are taken
any_set = False
for other_spell in spell_results:
# Fix the max level before replace
if (result["rank"] + 1) == other_spell["rank"] and (
result["base_level"] < other_spell["base_level"]
):
result["max_level_before_replace"] = other_spell["base_level"] - 1
any_set = True
# Equalize the base level of a spell to its lowest level.
if (
result["rank"] == other_spell["rank"]
and result["base_level"] < other_spell["base_level"]
):
other_spell["base_level"] = result["base_level"]
if result["heal"] != other_spell["heal"] and other_spell["heal"]:
result["heal"] = True
# If a spell has a cooldown, apply that cooldown to everything in the group
if result["cooldown"] < other_spell["cooldown"]:
result["cooldown"] = other_spell["cooldown"]
if not any_set:
result["max_level_before_replace"] = 70
# print(f'Spell {result}')
if result["heal"] and result["cooldown"] < 1:
# print(f'skipping healing spell {result}')
continue
full_spells[result["id"]] = result
# def print_lua(all_spells: dict):
# for i in range(10):
# for k, v in all_spells.items():
# if v['class'] != i:
# continue
for k, v in full_spells.items():
if "Blessing of" in v["name"]:
key = str(k)
if key not in names_table:
print(f"wtf {k} is not in names table")
else:
print(names_table[key])
if key not in levels_table:
print(f"wtf {k} is not in levels table")
else:
print(levels_table[key])
if key not in class_table:
print(f"wtf {k} is not in classes table")
else:
print(class_table[key])
if key not in spells_table:
print(f"wtf {k} not in the spells table")
else:
print(spells_table[key])
print(k, v)
print("CSV BEGIN")
print("AbilityID, Rank, LevelAvailable, Name, Class")
output_list = []
for k, v in full_spells.items():
output_list.append({'AbilityID': v['id'], 'Rank': v['rank'], 'LevelAvailable': v['base_level'], 'Name': v['name'], 'Class': v['class'], 'MaxLevelBeforeReplace':v['max_level_before_replace'], 'MinTargetLevel': v['min_target_level']})
with open('spell-ranks.csv', 'w', newline='') as csvfile:
fieldnames = ['AbilityID', 'Rank', 'LevelAvailable', 'Name', 'Class', 'MaxLevelBeforeReplace', 'MinTargetLevel']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(output_list)
Really solid... few healing spells had to be removed, like Holy Shock, and Rejuvenation I think.
Needs to have Pally Res and Priest Res added back in.
Had an issue where there are some books that aren't in the game yet... had to filter a few of those out.
On the whole really solid!
There are a bunch that had like "test..." abilities that may be gumming things up.
https://classic.wowhead.com/search?q=ancestral+spirit#abilities only 5 ranks. not 6.
Not in the game yet...
https://tbc.wowhead.com/items/recipes/books/min-req-level:70/max-req-level:70/quality:3