diff --git a/parse.go b/parse.go
index b2481b2..1d88af0 100644
--- a/parse.go
+++ b/parse.go
@@ -154,6 +154,11 @@ func ParseEffects(data *JSONGameData, allEffects [][]JSONGameItemPossibleEffect,
 				numIsSpell = true
 			}
 
+			isTitle := false
+			if strings.Contains((*langs)["en"].Texts[currentEffect.DescriptionId], "Title:") {
+				isTitle = true
+			}
+
 			mappedEffect.Type = make(map[string]string)
 			mappedEffect.Templated = make(map[string]string)
 			var minMaxRemove int
@@ -188,14 +193,25 @@ func ParseEffects(data *JSONGameData, allEffects [][]JSONGameItemPossibleEffect,
 					}
 					templatedName = SingularPluralFormatter(templatedName, effect.MinimumValue, lang)
 
+					if isTitle { // titles are Title: 0 after formatting; TODO move this into the NumSpellFormatter
+						templatedName = strings.ReplaceAll(templatedName, "0", (*langs)[lang].Texts[data.titles[diceNum].NameMaleId]) // TODO male default, idk how to make it neutral yet
+					}
+
 					effectName = DeleteDamageFormatter(effectName)
 					effectName = SingularPluralFormatter(effectName, effect.MinimumValue, lang)
 
-					mappedEffect.Min = diceNum
+					if isTitle {
+						mappedEffect.Min = 0
+						mappedEffect.Max = 0
+						mappedEffect.IsMeta = true
+					} else {
+						mappedEffect.Min = diceNum
+						mappedEffect.Max = diceSide
+						mappedEffect.IsMeta = false
+					}
 					mappedEffect.Max = diceSide
 					mappedEffect.Type[lang] = effectName
 					mappedEffect.Templated[lang] = templatedName
-					mappedEffect.IsMeta = false
 				}
 
 				if lang == "en" && mappedEffect.Type[lang] == "" {
@@ -529,6 +545,7 @@ func ParseRawData(dir string) *JSONGameData {
 	breedsChan := make(chan map[int]JSONGameBreed)
 	mountFamilyChan := make(chan map[int]JSONGameMountFamily)
 	npcsChan := make(chan map[int]JSONGameNPC)
+	titlesChan := make(chan map[int]JSONGameTitle)
 
 	go func() {
 		ParseRawDataPart("npcs.json", npcsChan, dir)
@@ -569,6 +586,9 @@ func ParseRawData(dir string) *JSONGameData {
 	go func() {
 		ParseRawDataPart("effects.json", itemEffectsChan, dir)
 	}()
+	go func() {
+		ParseRawDataPart("titles.json", titlesChan, dir)
+	}()
 
 	data.Items = <-itemChan
 	close(itemChan)
@@ -609,6 +629,9 @@ func ParseRawData(dir string) *JSONGameData {
 	data.npcs = <-npcsChan
 	close(npcsChan)
 
+	data.titles = <-titlesChan
+	close(titlesChan)
+
 	return &data
 }
 
diff --git a/parse_types.go b/parse_types.go
index ec5c01c..a346434 100644
--- a/parse_types.go
+++ b/parse_types.go
@@ -325,6 +325,18 @@ func (i JSONGameNPC) GetID() int {
 	return i.Id
 }
 
+type JSONGameTitle struct {
+	Id           int  `json:"id"`
+	NameMaleId   int  `json:"nameMaleId"`
+	NameFemaleId int  `json:"nameFemaleId"`
+	Visible      bool `json:"visible"`
+	CategoryId   int  `json:"categoryId"`
+}
+
+func (i JSONGameTitle) GetID() int {
+	return i.Id
+}
+
 type JSONGameData struct {
 	Items        map[int]JSONGameItem
 	Sets         map[int]JSONGameSet
@@ -339,4 +351,5 @@ type JSONGameData struct {
 	classes      map[int]JSONGameBreed
 	MountFamilys map[int]JSONGameMountFamily
 	npcs         map[int]JSONGameNPC
+	titles       map[int]JSONGameTitle
 }