Skip to content

Commit

Permalink
Make DNA conversion less likely to throw an exception when a gene tem…
Browse files Browse the repository at this point in the history
…plate has no weight block for given age and sex (#1851)

Sentry event ID: 1f6dd3eccb5f43b09d9feb735a716daf
  • Loading branch information
IhateTrains authored Mar 22, 2024
1 parent 3a77b29 commit 76957b4
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 42 deletions.
90 changes: 49 additions & 41 deletions ImperatorToCK3/CK3/Characters/DNAFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,25 +164,29 @@ public DNA GenerateDNA(Imperator.Characters.Character irCharacter, PortraitData
case "eyepatch_2": // TODO: check if this is correctly added to portrait modifiers if needed

Check warning on line 164 in ImperatorToCK3/CK3/Characters/DNAFactory.cs

View workflow job for this annotation

GitHub Actions / Upload development build (win-x64)

TODO check if this is correctly added to portrait modifiers if needed (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0026.md)

Check warning on line 164 in ImperatorToCK3/CK3/Characters/DNAFactory.cs

View workflow job for this annotation

GitHub Actions / Upload development build (linux-x64)

TODO check if this is correctly added to portrait modifiers if needed (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0026.md)
var eyePatchTemplate = ck3GenesDB.SpecialAccessoryGenes["special_headgear_eye_patch"]
.GeneTemplates["eye_patch"];
var eyePatchWeighBlock = eyePatchTemplate.AgeSexWeightBlocks[irCharacter.AgeSex];
var eyePatchObjectName = eyePatchWeighBlock.GetMatchingObject(1) ?? eyePatchWeighBlock.ObjectNames.Last();
accessoryDNAValues["special_headgear_eye_patch"] =
new DNAAccessoryGeneValue(eyePatchTemplate.Id, eyePatchObjectName, eyePatchWeighBlock);
if (eyePatchTemplate.AgeSexWeightBlocks.TryGetValue(irCharacter.AgeSex, out WeightBlock? eyePatchWeightBlock)) {
var eyePatchObjectName = eyePatchWeightBlock.GetMatchingObject(1) ?? eyePatchWeightBlock.ObjectNames.Last();
accessoryDNAValues["special_headgear_eye_patch"] = new(eyePatchTemplate.Id, eyePatchObjectName, eyePatchWeightBlock);
}

break;
case "blindfold_1": // TODO: check if this is correctly added to portrait modifiers if needed

Check warning on line 173 in ImperatorToCK3/CK3/Characters/DNAFactory.cs

View workflow job for this annotation

GitHub Actions / Upload development build (win-x64)

TODO check if this is correctly added to portrait modifiers if needed (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0026.md)

Check warning on line 173 in ImperatorToCK3/CK3/Characters/DNAFactory.cs

View workflow job for this annotation

GitHub Actions / Upload development build (linux-x64)

TODO check if this is correctly added to portrait modifiers if needed (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0026.md)
var blindfoldTemplate = ck3GenesDB.SpecialAccessoryGenes["special_headgear_blindfold"]
.GeneTemplates["blindfold"];
var blindfoldWeighBlock = blindfoldTemplate.AgeSexWeightBlocks[irCharacter.AgeSex];
var blindfoldObjectName = blindfoldWeighBlock.GetMatchingObject(1) ?? blindfoldWeighBlock.ObjectNames.Last();
accessoryDNAValues["special_headgear_blindfold"] =
new DNAAccessoryGeneValue(blindfoldTemplate.Id, blindfoldObjectName, blindfoldWeighBlock);
if (blindfoldTemplate.AgeSexWeightBlocks.TryGetValue(irCharacter.AgeSex, out WeightBlock? blindfoldWeightBlock)) {
var blindfoldObjectName = blindfoldWeightBlock.GetMatchingObject(1) ?? blindfoldWeightBlock.ObjectNames.Last();
accessoryDNAValues["special_headgear_blindfold"] = new(blindfoldTemplate.Id, blindfoldObjectName, blindfoldWeightBlock);
}

break;
case "blind_eyes": // TODO: check if this is correctly added to portrait modifiers if needed

Check warning on line 182 in ImperatorToCK3/CK3/Characters/DNAFactory.cs

View workflow job for this annotation

GitHub Actions / Upload development build (win-x64)

TODO check if this is correctly added to portrait modifiers if needed (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0026.md)

Check warning on line 182 in ImperatorToCK3/CK3/Characters/DNAFactory.cs

View workflow job for this annotation

GitHub Actions / Upload development build (linux-x64)

TODO check if this is correctly added to portrait modifiers if needed (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0026.md)
var blindEyesTemplate = ck3GenesDB.AccessoryGenes["eye_accessory"]
.GeneTemplates["blind_eyes"];
var blindEyesWeighBlock = blindEyesTemplate.AgeSexWeightBlocks[irCharacter.AgeSex];
var blindEyesObjectName = blindEyesWeighBlock.GetMatchingObject(1) ?? blindEyesWeighBlock.ObjectNames.Last();
accessoryDNAValues["eye_accessory"] = new DNAAccessoryGeneValue(blindEyesTemplate.Id, blindEyesObjectName, blindEyesWeighBlock);
if (blindEyesTemplate.AgeSexWeightBlocks.TryGetValue(irCharacter.AgeSex, out WeightBlock? blindEyesWeightBlock)) {
var blindEyesObjectName = blindEyesWeightBlock.GetMatchingObject(1) ?? blindEyesWeightBlock.ObjectNames.Last();
accessoryDNAValues["eye_accessory"] = new(blindEyesTemplate.Id, blindEyesObjectName, blindEyesWeightBlock);
}

break;
case "red_eyes": // TODO: check if this is correctly converted

Check warning on line 191 in ImperatorToCK3/CK3/Characters/DNAFactory.cs

View workflow job for this annotation

GitHub Actions / Upload development build (win-x64)

Check warning on line 191 in ImperatorToCK3/CK3/Characters/DNAFactory.cs

View workflow job for this annotation

GitHub Actions / Upload development build (linux-x64)

var magickRed = new MagickColor("#ff0000");
Expand All @@ -198,22 +202,24 @@ public DNA GenerateDNA(Imperator.Characters.Character irCharacter, PortraitData
}
if (irCharacter.Traits.Contains("blind")) {
var blindEyesTemplate = ck3GenesDB.AccessoryGenes["eye_accessory"].GeneTemplates["blind_eyes"];
var blindEyesWeighBlock = blindEyesTemplate.AgeSexWeightBlocks[irCharacter.AgeSex];
var blindEyesObjectName = blindEyesWeighBlock.GetMatchingObject(1) ?? blindEyesWeighBlock.ObjectNames.Last();
accessoryDNAValues["eye_accessory"] = new DNAAccessoryGeneValue(blindEyesTemplate.Id, blindEyesObjectName, blindEyesWeighBlock); // TODO: check if this is correctly added to portrait modifiers if needed

if (blindEyesTemplate.AgeSexWeightBlocks.TryGetValue(irCharacter.AgeSex, out WeightBlock? blindEyesWeighBlock)) {
var blindEyesObjectName = blindEyesWeighBlock.GetMatchingObject(1) ?? blindEyesWeighBlock.ObjectNames.Last();
accessoryDNAValues["eye_accessory"] = new(blindEyesTemplate.Id, blindEyesObjectName, blindEyesWeighBlock); // TODO: check if this is correctly added to portrait modifiers if needed

Check warning on line 207 in ImperatorToCK3/CK3/Characters/DNAFactory.cs

View workflow job for this annotation

GitHub Actions / Upload development build (win-x64)

TODO check if this is correctly added to portrait modifiers if needed (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0026.md)

Check warning on line 207 in ImperatorToCK3/CK3/Characters/DNAFactory.cs

View workflow job for this annotation

GitHub Actions / Upload development build (linux-x64)

TODO check if this is correctly added to portrait modifiers if needed (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0026.md)
}

var blindfoldTemplate = ck3GenesDB.SpecialAccessoryGenes["special_headgear_blindfold"]
.GeneTemplates["blindfold"];
var blindfoldWeighBlock = blindfoldTemplate.AgeSexWeightBlocks[irCharacter.AgeSex];
var blindfoldObjectName = blindfoldWeighBlock.GetMatchingObject(1) ?? blindfoldWeighBlock.ObjectNames.Last();
accessoryDNAValues["special_headgear_blindfold"] = new DNAAccessoryGeneValue(blindfoldTemplate.Id, blindfoldObjectName, blindfoldWeighBlock); // TODO: check if this is correctly added to portrait modifiers if needed
if (blindfoldTemplate.AgeSexWeightBlocks.TryGetValue(irCharacter.AgeSex, out WeightBlock? blindfoldWeighBlock)) {
var blindfoldObjectName = blindfoldWeighBlock.GetMatchingObject(1) ?? blindfoldWeighBlock.ObjectNames.Last();
accessoryDNAValues["special_headgear_blindfold"] = new(blindfoldTemplate.Id, blindfoldObjectName, blindfoldWeighBlock); // TODO: check if this is correctly added to portrait modifiers if needed

Check warning on line 214 in ImperatorToCK3/CK3/Characters/DNAFactory.cs

View workflow job for this annotation

GitHub Actions / Upload development build (win-x64)

TODO check if this is correctly added to portrait modifiers if needed (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0026.md)

Check warning on line 214 in ImperatorToCK3/CK3/Characters/DNAFactory.cs

View workflow job for this annotation

GitHub Actions / Upload development build (linux-x64)

TODO check if this is correctly added to portrait modifiers if needed (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0026.md)
}
} else if (irCharacter.Traits.Contains("one_eyed")) {
var eyePatchTemplate = ck3GenesDB.SpecialAccessoryGenes["special_headgear_eye_patch"]
.GeneTemplates["eye_patch"];
var eyePatchWeighBlock = eyePatchTemplate.AgeSexWeightBlocks[irCharacter.AgeSex];
var eyePatchObjectName = eyePatchWeighBlock.GetMatchingObject(1) ?? eyePatchWeighBlock.ObjectNames.Last();
accessoryDNAValues["special_headgear_eye_patch"] =
new DNAAccessoryGeneValue(eyePatchTemplate.Id, eyePatchObjectName, eyePatchWeighBlock); // TODO: check if this is correctly added to portrait modifiers if needed
if (eyePatchTemplate.AgeSexWeightBlocks.TryGetValue(irCharacter.AgeSex, out WeightBlock? eyePatchWeighBlock)) {
var eyePatchObjectName = eyePatchWeighBlock.GetMatchingObject(1) ?? eyePatchWeighBlock.ObjectNames.Last();
accessoryDNAValues["special_headgear_eye_patch"] = new(eyePatchTemplate.Id, eyePatchObjectName, eyePatchWeighBlock); // TODO: check if this is correctly added to portrait modifiers if needed

Check warning on line 221 in ImperatorToCK3/CK3/Characters/DNAFactory.cs

View workflow job for this annotation

GitHub Actions / Upload development build (win-x64)

TODO check if this is correctly added to portrait modifiers if needed (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0026.md)

Check warning on line 221 in ImperatorToCK3/CK3/Characters/DNAFactory.cs

View workflow job for this annotation

GitHub Actions / Upload development build (linux-x64)

TODO check if this is correctly added to portrait modifiers if needed (https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0026.md)
}
}

var irMorphGenesWithDirectEquivalents = new[] {
Expand Down Expand Up @@ -262,12 +268,13 @@ public DNA GenerateDNA(Imperator.Characters.Character irCharacter, PortraitData

// Use normal teeth for everyone. I:R doesn't have characters with no teeth.
var teethGeneTemplate = ck3GenesDB.AccessoryGenes["teeth_accessory"].GeneTemplates["normal_teeth"];
var teethWeightBlock = teethGeneTemplate.AgeSexWeightBlocks[irCharacter.AgeSex];
accessoryDNAValues["teeth_accessory"] = new DNAAccessoryGeneValue(
teethGeneTemplate.Id,
teethWeightBlock.GetMatchingObject(0.5) ?? teethWeightBlock.ObjectNames.First(),
teethWeightBlock
);
if (teethGeneTemplate.AgeSexWeightBlocks.TryGetValue(irCharacter.AgeSex, out WeightBlock? teethWeightBlock)) {
accessoryDNAValues["teeth_accessory"] = new DNAAccessoryGeneValue(
teethGeneTemplate.Id,
teethWeightBlock.GetMatchingObject(0.5) ?? teethWeightBlock.ObjectNames.First(),
teethWeightBlock
);
}

// Use middle values for the rest of the genes.
var missingMorphGenes = ck3GenesDB.MorphGenes
Expand Down Expand Up @@ -298,9 +305,14 @@ public DNA GenerateDNA(Imperator.Characters.Character irCharacter, PortraitData
.ToImmutableList();
// Get middle gene template.
var middleTemplate = geneTemplates.ElementAt(geneTemplates.Count / 2);
var middleTemplateWeightBlock = middleTemplate.AgeSexWeightBlocks[irCharacter.AgeSex];
var middleObjectName = middleTemplateWeightBlock.GetMatchingObject(0.5);
accessoryDNAValues.Add(gene.Id, new DNAAccessoryGeneValue(middleTemplate.Id, middleObjectName, middleTemplateWeightBlock));
if (middleTemplate.AgeSexWeightBlocks.TryGetValue(irCharacter.AgeSex, out WeightBlock? weightBlock)) {
var middleObjectName = weightBlock.GetMatchingObject(0.5);
if (middleObjectName is not null) {
accessoryDNAValues[gene.Id] = new(middleTemplate.Id, middleObjectName, weightBlock);
} else {
Logger.Warn($"Failed to find middle object for gene {gene.Id}!");
}
}
}

return new DNA(id, colorDNAValues, morphDNAValues, accessoryDNAValues);
Expand All @@ -321,20 +333,16 @@ private void ConvertBaldness(Imperator.Characters.Character irCharacter, Diction
// If m_hair_fp4_indian_01_full_bald (which is close to I:R baldness) exists, use it.
const string indianBaldnessObjectName = "m_hair_fp4_indian_01_full_bald";
if (hairstylesGene.GeneTemplates.TryGetValue("fp4_bald_hairstyles", out var ck3GeneTemplate)) {
var ageSexWeightBlock = ck3GeneTemplate.AgeSexWeightBlocks[irCharacter.AgeSex];

if (ageSexWeightBlock.ContainsObject(indianBaldnessObjectName)) {
hairstylesGeneValue = new DNAAccessoryGeneValue(ck3GeneTemplate.Id, indianBaldnessObjectName, ageSexWeightBlock);
if (ck3GeneTemplate.AgeSexWeightBlocks.TryGetValue(irCharacter.AgeSex, out WeightBlock? weightBlock) && weightBlock.ContainsObject(indianBaldnessObjectName)) {
hairstylesGeneValue = new DNAAccessoryGeneValue(ck3GeneTemplate.Id, indianBaldnessObjectName, weightBlock);
}
}

// Otherwise, just use the no_hairstyles template.
const string baldnessObjectName = "bald";
if (hairstylesGeneValue is null && hairstylesGene.GeneTemplates.TryGetValue("no_hairstyles", out var noHairStylesTemplate)) {
var ageSexWeightBlock = noHairStylesTemplate.AgeSexWeightBlocks[irCharacter.AgeSex];

if (ageSexWeightBlock.ContainsObject(baldnessObjectName)) {
hairstylesGeneValue = new DNAAccessoryGeneValue(noHairStylesTemplate.Id, baldnessObjectName, ageSexWeightBlock);
if (noHairStylesTemplate.AgeSexWeightBlocks.TryGetValue(irCharacter.AgeSex, out WeightBlock? weightBlock) && weightBlock.ContainsObject(baldnessObjectName)) {
hairstylesGeneValue = new DNAAccessoryGeneValue(noHairStylesTemplate.Id, baldnessObjectName, weightBlock);
}
}

Expand Down Expand Up @@ -377,7 +385,7 @@ AccessoryGene ck3Gene
return null;
}
var ck3GeneTemplate = ck3Gene.GeneTemplates
.FirstOrDefault(t => t.AgeSexWeightBlocks[irCharacter.AgeSex].ContainsObject(convertedSetEntry));
.FirstOrDefault(t => t.ContainsObjectForAgeSex(irCharacter.AgeSex, convertedSetEntry));
if (ck3GeneTemplate is null) {
Logger.Warn($"No template found for {convertedSetEntry} in CK3 gene {ck3Gene.Id}!");
return null;
Expand All @@ -388,7 +396,7 @@ AccessoryGene ck3Gene
return null;
}
var ck3GeneTemplateRecessive = ck3Gene.GeneTemplates
.FirstOrDefault(t => t.AgeSexWeightBlocks[irCharacter.AgeSex].ContainsObject(convertedSetEntryRecessive));
.FirstOrDefault(t => t.ContainsObjectForAgeSex(irCharacter.AgeSex, convertedSetEntryRecessive));
if (ck3GeneTemplateRecessive is null) {
Logger.Warn($"No template found for {convertedSetEntryRecessive} in CK3 gene {ck3Gene.Id}!");
return null;
Expand Down
4 changes: 4 additions & 0 deletions ImperatorToCK3/CommonUtils/Genes/AccessoryGeneTemplate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,8 @@ private void RegisterKeys(Parser parser) {
});
parser.IgnoreUnregisteredItems();
}

public bool ContainsObjectForAgeSex(string ageSex, string objectName) {
return AgeSexWeightBlocks.TryGetValue(ageSex, out var weightBlock) && weightBlock.ContainsObject(objectName);
}
}
2 changes: 1 addition & 1 deletion ImperatorToCK3/Data_Files/configurables/religion_map.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ link = { ck3 = arabic_pagan ir = arabian_pantheon }
# Hellenic - TFE
link = { ck3 = roman_pagan ir = italic_pantheon }
# Hellenic - Vanilla CK3
link = {
link = { # TODO: Change this mapping. The Zoroastrian cult of Mithra is not the same as the Roman Mithraic Mysteries.
ck3 = mithraic_mysteries
ir = mithra_religion # from Invictus
}
Expand Down

0 comments on commit 76957b4

Please sign in to comment.