@@ -26,45 +26,82 @@ export const generateRelative = ({
2626 race,
2727 } ) ;
2828
29- // Regenerate some properties always, and others with some probabilityF
30- const probRegenerate = 0.25 ;
31- const regenerateProperties = {
29+ // Regenerate some properties always, and others with some probability
30+ type RegenerateType =
31+ | "always"
32+ | "never"
33+ | "sometimes"
34+ | "sometimesIfRaceIsKnown" ;
35+ type ToRegenerateProperties < T , U > = T extends object
36+ ? T extends any [ ]
37+ ? U
38+ : {
39+ [ K in keyof T ] : T [ K ] extends object
40+ ? ToRegenerateProperties < T [ K ] , U > | U
41+ : U ;
42+ }
43+ : U ;
44+ type RegenerateProperties = ToRegenerateProperties <
45+ FaceConfig ,
46+ RegenerateType
47+ > ;
48+
49+ const regenerateProperties : RegenerateProperties = {
3250 accessories : "always" ,
33- " body.id" : "sometimes" ,
34- "body.size" : "always " ,
35- "ear.id" : "sometimes" ,
36- "ear. size" : "sometimes " ,
37- "eye.angle" : "sometimes" ,
38- "eye.id" : "sometimes" ,
39- "eyebrow.angle" : "sometimes" ,
40- " eyebrow.id" : "sometimes" ,
51+ body : {
52+ color : "sometimesIfRaceIsKnown " ,
53+ id : "sometimes" ,
54+ size : "always " ,
55+ } ,
56+ ear : "sometimes" ,
57+ eye : "sometimes" ,
58+ eyebrow : "sometimes" ,
4159 eyeLine : "sometimes" ,
42- "face.body.color" : "sometimesIfRaceIsKnown" ,
43- "face.hair.color" : "sometimesIfRaceIsKnown" ,
4460 facialHair : "always" ,
4561 fatness : "always" ,
4662 glasses : "always" ,
47- "hair.flip" : "always" ,
48- "hair.id" : "always" ,
63+ hair : {
64+ color : "sometimesIfRaceIsKnown" ,
65+ flip : "always" ,
66+ id : "always" ,
67+ } ,
4968 hairBg : "always" ,
50- "head.id" : "sometimes" ,
51- "head.shave" : "always" ,
69+ head : {
70+ id : "sometimes" ,
71+ shave : "always" ,
72+ } ,
73+ jersey : "never" ,
5274 miscLine : "sometimes" ,
5375 mouth : "sometimes" ,
5476 nose : "sometimes" ,
5577 smileLine : "sometimes" ,
56- } as const ;
78+ teamColors : "never" ,
79+ } ;
5780
58- for ( const [ path , regenerateType ] of Object . entries ( regenerateProperties ) ) {
59- if (
60- regenerateType === "always" ||
61- ( ( regenerateType === "sometimes" ||
62- ( regenerateType === "sometimesIfRaceIsKnown" && race !== undefined ) ) &&
63- Math . random ( ) < probRegenerate )
64- ) {
65- dset ( face , path , delve ( randomFace , path ) ) ;
81+ const probRegenerate = 0.25 ;
82+ const processRegenerateProperties = (
83+ objOutput : any ,
84+ objRandom : any ,
85+ regeneratePropertiesLocal :
86+ | RegenerateProperties
87+ | Record < string , RegenerateType > ,
88+ ) => {
89+ for ( const [ key , value ] of Object . entries ( regeneratePropertiesLocal ) ) {
90+ if ( typeof value === "string" ) {
91+ if (
92+ value === "always" ||
93+ ( ( value === "sometimes" ||
94+ ( value === "sometimesIfRaceIsKnown" && race !== undefined ) ) &&
95+ Math . random ( ) < probRegenerate )
96+ ) {
97+ objOutput [ key ] = objRandom [ key ] ;
98+ }
99+ } else {
100+ processRegenerateProperties ( objOutput [ key ] , objRandom [ key ] , value ) ;
101+ }
66102 }
67- }
103+ } ;
104+ processRegenerateProperties ( face , randomFace , regenerateProperties ) ;
68105
69106 // Override any ID properties that are not valid for the specified gender
70107 for ( const key of features ) {
0 commit comments