Skip to content

Commit 5e81894

Browse files
committed
Added Beards* + some micro-optimizations.
*options may not be in the correct order & no previews have been generated yet.
1 parent 482c680 commit 5e81894

4 files changed

Lines changed: 206 additions & 12 deletions

File tree

CP2077SaveEditor/Resources/AppearanceValues.json

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,5 +435,98 @@
435435
"patmc",
436436
"short_afro",
437437
"thick_beard_afro"
438-
]
438+
],
439+
"BeardStyles":
440+
{
441+
"shadowbase_01":
442+
[
443+
""
444+
],
445+
"big_beard_afro":
446+
[
447+
"",
448+
"chin",
449+
"mustache"
450+
],
451+
"default":
452+
[
453+
"",
454+
"chin",
455+
"chin_mustache",
456+
"chin_sides",
457+
"mustache",
458+
"mustache_sides",
459+
"sides"
460+
],
461+
"handlebar_stache":
462+
[
463+
""
464+
],
465+
"jesse_beard":
466+
[
467+
"",
468+
"chin",
469+
"mustache"
470+
],
471+
"fu_manchu":
472+
[
473+
"",
474+
"chin",
475+
"chin_mustache",
476+
"chin_sides",
477+
"mustache",
478+
"mustache_sides",
479+
"sides"
480+
],
481+
"logan":
482+
[
483+
"",
484+
"chin",
485+
"chin_mustache",
486+
"chin_sides",
487+
"mustache",
488+
"mustache_sides",
489+
"sides"
490+
],
491+
"maelstrom_full":
492+
[
493+
"",
494+
"chin",
495+
"chin_mustache",
496+
"chin_sides",
497+
"mustache",
498+
"mustache_sides",
499+
"sides"
500+
],
501+
"maelstrom_goatie":
502+
[
503+
""
504+
],
505+
"patmc":
506+
[
507+
"",
508+
"chin",
509+
"chin_mustache",
510+
"chin_sides",
511+
"mustache",
512+
"mustache_sides",
513+
"sides"
514+
],
515+
"short_afro":
516+
[
517+
"",
518+
"chin",
519+
"mustache"
520+
],
521+
"thick_beard_afro":
522+
[
523+
"",
524+
"chin",
525+
"chin_mustache",
526+
"chin_sides",
527+
"mustache",
528+
"mustache_sides",
529+
"sides"
530+
]
531+
}
439532
}

CP2077SaveEditor/Utils/AppearanceHelper.cs

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,106 @@ public int Ears
352352
}
353353
}
354354

355+
public int Beard
356+
{
357+
get
358+
{
359+
if(BodyGender != AppearanceGender.Female)
360+
{
361+
var entries = GetEntries("first.main.beard_color_");
362+
foreach(HashValueEntry singleEntry in entries)
363+
{
364+
var name = singleEntry.GetPath().Split('\\').Last();
365+
var searchString = name.Substring(0, name.Length - ".app".Length).Substring("hb_000_pma__".Length).Split("__");
366+
367+
return AppearanceValueLists.Beards.FindIndex(x => x == searchString[0]) + 1;
368+
}
369+
return 0;
370+
}
371+
return -1;
372+
}
373+
set
374+
{
375+
if (value < 0 || value > AppearanceValueLists.Beards.Count)
376+
{
377+
return;
378+
}
379+
380+
SetNullableHashEntry("beard_color_", new HashValueEntry()
381+
{
382+
FirstString = "01_blonde_platinum",
383+
Hash = value == 0 ? 0 : CyberCAT.Extra.Utils.HashGenerator.CalcFNV1A64("base\\characters\\head\\player_base_heads\\appearances\\facial_hairs\\hb_000_pma__" + AppearanceValueLists.Beards[value - 1] + ".app"),
384+
SecondString = "beard_color1_0"
385+
},
386+
new[] { "TPP", "character_customization" }, AppearanceField.Hash);
387+
}
388+
}
389+
390+
public int BeardStyle
391+
{
392+
get
393+
{
394+
if (BodyGender != AppearanceGender.Female)
395+
{
396+
var entries = GetEntries("first.main.beard_color_");
397+
foreach (HashValueEntry singleEntry in entries)
398+
{
399+
var name = singleEntry.GetPath().Split('\\').Last();
400+
var searchString = name.Substring(0, name.Length - ".app".Length).Substring("hb_000_pma__".Length).Split("__");
401+
402+
if (searchString.Count() > 1)
403+
{
404+
return AppearanceValueLists.BeardStyles[searchString[0]].FindIndex(x => x == searchString[1]) + 1;
405+
}
406+
else if (AppearanceValueLists.BeardStyles[searchString[0]].Count < 2)
407+
{
408+
return -1;
409+
}
410+
else
411+
{
412+
return 1;
413+
}
414+
}
415+
}
416+
return -1;
417+
}
418+
set
419+
{
420+
var entries = GetEntries("first.main.beard_color_");
421+
422+
var path = ((HashValueEntry)entries[0]).GetPath().Split('\\');
423+
var parts = path.Last().Substring(0, path.Last().Length - ".app".Length).Split("__").ToList();
424+
425+
var options = AppearanceValueLists.BeardStyles[parts[1]];
426+
427+
if (value < 1 || value > options.Count)
428+
{
429+
return;
430+
}
431+
432+
if (options[value - 1] == string.Empty && parts.Count > 2)
433+
{
434+
parts.RemoveAt(2);
435+
}
436+
else if (options[value - 1] != string.Empty && parts.Count < 3)
437+
{
438+
parts.Add(options[value - 1]);
439+
}
440+
else if (options[value - 1] != string.Empty && parts.Count > 2)
441+
{
442+
parts[2] = options[value - 1];
443+
}
444+
445+
path[path.Length - 1] = string.Join("__", parts) + ".app";
446+
var finalPath = string.Join('\\', path);
447+
448+
foreach (HashValueEntry singleEntry in entries)
449+
{
450+
singleEntry.SetPath(finalPath);
451+
}
452+
}
453+
}
454+
355455
public int Cyberware
356456
{
357457
get
@@ -1709,5 +1809,7 @@ public static class AppearanceValueLists
17091809
public static List<string> PenisSizes { get; } = Values["PenisSizes"].ToObject<List<string>>();
17101810
public static List<ulong> PubicHairStyles { get; } = Values["PubicHairStyles"].ToObject<List<ulong>>();
17111811
public static List<string> NailColors { get; } = Values["NailColors"].ToObject<List<string>>();
1812+
public static List<string> Beards { get; } = Values["Beards"].ToObject<List<string>>();
1813+
public static Dictionary<string, List<string>> BeardStyles { get; } = Values["BeardStyles"].ToObject<Dictionary<string, List<string>>>();
17121814
}
17131815
}

CP2077SaveEditor/Utils/ResolverExtensions.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public class BinaryResolver : ITweakDbResolver
8585
{
8686
private BinaryReader br;
8787
private TweakDbParser parser = new TweakDbParser();
88-
public Dictionary<ulong, TdbIdInfo> TdbIdIndex = new Dictionary<ulong, TdbIdInfo>();
88+
public Dictionary<ulong, TdbIdInfo> TdbIdIndex;
8989

9090
public string GetName(TweakDbId tdbid)
9191
{
@@ -153,6 +153,8 @@ public BinaryResolver(byte[] data)
153153
var infoItemsCount = br.ReadUInt32();
154154
var infoIndex = new List<ulong>();
155155

156+
TdbIdIndex = new Dictionary<ulong, TdbIdInfo>((int)totalItemsCount);
157+
156158
for (uint i = 0; i < totalItemsCount; i++)
157159
{
158160
var name = br.ReadString();

CP2077SaveEditor/Views/Form1.cs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -727,16 +727,7 @@ private void saveChangesButton_Click(object sender, EventArgs e)
727727
var worker = new BackgroundWorker();
728728
worker.DoWork += (object sender, DoWorkEventArgs e) =>
729729
{
730-
byte[] saveBytes;
731-
if (saveType == 0)
732-
{
733-
saveBytes = activeSaveFile.Save();
734-
}
735-
else
736-
{
737-
saveBytes = activeSaveFile.Save(false);
738-
}
739-
e.Result = saveBytes;
730+
e.Result = activeSaveFile.Save(saveType == 0);
740731
};
741732
worker.RunWorkerCompleted += (object sender, RunWorkerCompletedEventArgs e) =>
742733
{
@@ -892,6 +883,12 @@ private void inventoryListView_Click (object sender, MouseEventArgs e)
892883
}
893884

894885
var contextMenu = new ContextMenuStrip();
886+
contextMenu.Items.Add("New Item").Click += (object sender, EventArgs e) =>
887+
{
888+
var inventory = activeSaveFile.GetInventory(1);
889+
inventory.Items.Add(inventory.Items.Last().CreateSimpleItem());
890+
};
891+
895892
if (containerID == "1")
896893
{
897894
var activeItem = (ItemData)inventoryListView.SelectedVirtualItems()[0].Tag;

0 commit comments

Comments
 (0)